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

  Юрий  | 

    | 

  Обновл. 6 мая 2019  | 

 12065

 ǀ   3 

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

Современный C++ поддерживает два разных типа строк:

   std::string (как часть стандартной библиотеки);

   строки C-style (изначально унаследованные от языка C).

std::string реализован с помощью строк C-style.

Строки C-style

Строка C-style — это простой массив символов, который использует нуль-терминатор. Нуль-терминатор — это специальный символ (код 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_s() позволяет копировать содержимое одной строки в другую. Чаще всего это используется для присваивания значений строке:

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

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

Результат выполнения программы выше:

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

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

Вот ещё полезные функции для управления строками C-style:

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

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

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

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

Например:

Стоит ли использовать строки C-style?


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

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

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

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (77 оценок, среднее: 4,95 из 5)
Загрузка...

Комментариев: 3

  1. Аватар Ad1lMkn:

    Лол, интересно)))))00)))))))))

  2. Аватар Владимир:

    При переборе символьной строки безопаснее перебирать её до тех пор, пока не встретится завершающий ноль (если вы его конечно же не перезаписали) вместо использования функции strlen(), например:

    Результат:
    Put any text here.

    1. Аватар Юра:

      Ну и в чем безопасность? strlen возвращает кол-во символов до ТЕРМИНАЛЬНОГО НУЛЯ. Зачем переписывать велосипед?

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

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