Указатель (указатели), передаваемый этим функциям, должен указывать на массив (массивы) с нулевым символом в конце.
char ca[] = {'C', '+', '+'}; // без нулевого символа в конце
cout << strlen(ca) << endl; // катастрофа: ca не завершается нулевым
// символом
В данном случае ca — это массив элементов типа char, но он не завершается нулевым символом. Результат непредсказуем. Вероятней всего, функция strlen() продолжит просматривать память уже за пределами массива ca, пока не встретит нулевой символ.
Таблица 3.8. Функции для символьных строк в стиле С
strlen(p)
|
Возвращает длину строки p без учета нулевого символа |
strcmp(p1, p2)
|
Проверяет равенство строк p1 и p2. Возвращает 0, если p1 == p2, положительное значение, если p1 > p2, и отрицательное значение, если p1 < p2 |
strcat(p1, p2)
|
Добавляет строку p2 к p1. Результат возвращает в строку p1 |
strcpy(p1, p2)
|
Копирует строку p2 в строку p1. Результат возвращает в строку p1 |
Сравнение двух строк в стиле С осуществляется совсем не так, как сравнение строк библиотечного типа string. При сравнении библиотечных строк используются обычные операторы равенства или сравнения:
string s1 = "A string example";
string s2 = "A different string";
if (s1 < s2) // ложно: s2 меньше s1
Использование этих же операторов для подобным образом определенных строк в стиле С приведет к сравнению значений указателей, а не самих строк.
const char ca1[] = "A string example";
const char ca2[] = "A different string";
if (ca1 < ca2) // непредсказуемо: сравниваются два адреса
Помните, что при использовании массива в действительности используются указатели на их первый элемент (см. раздел 3.5.3). Следовательно, это условие фактически сравнивает два значения const char*. Эти указатели содержат адреса разных объектов, поэтому результат такого сравнения непредсказуем.
Чтобы сравнить строки, а не значения указателей, можем использовать функцию strcmp(). Она возвращает значение 0, если строки равны, положительное или отрицательное значение, в зависимости от того, больше ли первая строка второй или меньше.
if (strcmp(ca1, ca2) < 0) // то же, что и сравнение строк s1 < s2
Конкатенация и копирование строк в стиле С также весьма отличается от таких же операций с библиотечным типом string. Например, если необходима конкатенация строк s1 и s2, определенных выше, то это можно сделать так:
// инициализировать largeStr результатом конкатенации строки s1,
// пробела и строки s2
string largeStr = s1 + " " + s2;
Подобное с двумя массивами, ca1 и ca2, было бы ошибкой. Выражение ca1 + ca2 попытается сложить два указателя, что некорректно и бессмысленно.
Вместо этого можно использовать функции strcat() и strcpy(). Но чтобы использовать эти функции, им необходимо передать массив для хранения результирующей строки. Передаваемый массив должен быть достаточно большим, чтобы содержать созданную строку, включая нулевой символ в конце. Хотя представленный здесь код следует традиционной схеме, потенциально он может стать причиной серьезной ошибки.
// катастрофа, если размер largeStr вычислен ошибочно
strcpy(largeStr, ca1); // копирует ca1 в largeStr
strcat(largeStr, " "); // добавляет пробел в конец largeStr
strcat(largeStr, ca2); // конкатенирует ca2 с largeStr
Проблема в том, что можно легко ошибиться в расчете необходимого размера largeStr. Кроме того, при каждом изменении значения, которые следует сохранить в largeStr, необходимо перепроверить правильность вычисления его размера. К сожалению, код, подобный этому, широко распространен в программах. Такие программы подвержены ошибкам и часто приводят к серьезным проблемам защиты.