Урок 79. Строки C-style

   ⁄ 

 Обновлено 5 Сен 2017

  ⁄   

В уроке 57 о введении в std::string мы определили понятие «строка» как набор последовательных символов (например, «Hello, world!»). Строки — это основной способ работы с текстом в C++, а std::string позволяет сделать эту работу проще.

Современный C++ поддерживает два разных типа строк: std::string (как часть стандартной библиотеки) и строки C-style (изначально унаследованные от языка C). std::string реализован с помощью строк C-style. В этом уроке мы подробно их рассмотрим.

Строки C-style

Строка C-style — это простой массив символов, который использует нуль-терминатор. Нуль-терминатор — это специальный символ (‘\0’, код ASCII — 0), используемый для обозначения конца строки. Строка C-style еще называется нуль-терминированной строкой.

Для её определения нужно просто объявить массив char и инициализировать его литералом (например, «string»):

Хотя «string» имеет только 6 букв, C++ автоматически добавляет нуль-терминатор в конец строки (нам не нужно добавлять его вручную). Следовательно, длина массива mystring на самом деле 7!

В качестве примера рассмотрим следующую программу, которая выводит длину строки, а затем коды ASCII всех символов литерала «string»:

Результат:

string has 7 characters.
115 116 114 105 110 103 0

Нуль в конце — код ASCII нуль-терминатора, который был добавлен в конец строки.

При таком объявлении строк рекомендуется использовать [], чтобы позволить компилятору вычислить длину массива самому. Таким образом, если вы измените строку позже, вам не придется вручную изменять значение длины массива.

Важно отметить, строки C-style следуют всем тем же правилам, что и массивы. Это означает, что вы можете инициализировать строку при создании, но после этого вы не сможете присваивать ей значения с помощью оператора присваивания!

Это тоже самое, как если бы мы сделали следующее:

Поскольку строки C-style являются массивами, вы можете использовать оператор [] для изменения отдельных символов в строке:

Результат:

spring

При выводе строки C-style std::cout выводит символы до тех пор, пока не встретит нуль-терминатор. Если вы случайно перезаписали нуль-терминатор в строке (например, присвоив что-либо для mystring[6]), вы не только получите все символы строки, но std::cout также выведет всё, что находится в соседних слотах памяти до тех пор, пока не попадется 0!

Обратите внимание, это нормально, если длина массива больше строки, которую он хранит:

В этом случае строка «Max» будет выведена, а std::cout остановится на нуль-терминаторе. Остальные символы в массиве будут проигнорированы.

Строки C-style и std::cin

Бывает много случаев, когда мы не знаем заранее, насколько длинной будет наша строка. Например, рассмотрим проблему написания программы, где мы просим пользователя ввести свое имя. Насколько длинным оно будет? Неизвестно до тех пор, пока пользователь его не введет!

В таком случае мы можем объявить массив больше, чем нам нужно:

В программе выше мы объявили массив из 255 символов, предполагая, что пользователь не введет имя длиннее 255 символов. Хоть это и распространенная практика, но она не очень эффективна, так как пользователю ничего не мешает ввести имя более 255 символов (случайно или намеренно).

Намного лучше сделать так:

Вызов cin.getline() будет принимать до 254 символов в массив name (оставляя место для нуль-терминатора!). Любые лишние символы будут отброшены. Таким образом, мы можем гарантировать, что массив не будет переполнен!

Управление строками C-style

C++ предоставляет множество функций для управления строками C-style, которые находятся в составе библиотеки <cstring>. Вот несколько самых полезных:

strcpy() позволяет копировать содержимое одной строки в другую. Чаще всего это используется для присваивания значения строке:

Тем не менее, использование strcpy() может легко вызвать переполнение массива, если не быть осторожным! В следующей программе, длина массива dest меньше длины копируемой строки, поэтому в результате мы получим переполнение массива.

В C++11 вместо strcpy() используется strcpy_s, в который добавлен параметр для определения размера места назначения (т.е. массива, строки и прочего, куда мы будем копировать содержимое). Однако не все компиляторы поддерживают эту функцию и для её использования вы должны определить __STDC_WANT_LIB_EXT1__ со значением 1. Если ваш компилятор не поддерживает strcpy_s – используйте strcpy.

Другой полезной функцией является strlen(), которая возвращает длину строки C-style (без нуль-терминатора).

В результате:

My name is: Max
Max has 3 letters.
Max has 15 characters in the array.

Обратите внимание на разницу между strlen() и sizeof(). strlen() выводит количество символов до нуль-терминатора, тогда как sizeof() возвращает размер целого массива, независимо от того, что в нем находится.

Другие полезные функции:

  strcat() — добавляет одну строку к другой (опасно);

  strncat() — добавляет одну строку к другой (с проверкой размера места назначения);

  strcmp() — сравнивает две строки (возвращает 0, если они равны);

  strncmp() — сравнивает две строки до определенного количества символов (возвращает 0, если они равны).

Вот пример программы, в которой используются некоторые концепции из этого урока:

Не используйте строки C-style

Знать о строках C-style стоит, так как они используются во множестве кода. Однако теперь, когда мы уяснили, как они работают, мы рекомендуем избегать их вообще! Если у вас нет конкретной, убедительной причины использовать строки C-style, используйте std::string (находится в заголовке <string>). std::string проще, безопаснее и гибче.

Правило: Используйте std::string вместо строк C-style.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (4 оценок, среднее: 5,00 из 5)
Загрузка...
Поделиться в:
Подписаться на обновления:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *