Литмир - Электронная Библиотека
A
A

const char* s1 = "asdf";

const char* s2 = "asdf";

if (s1==s2) { /* ссылаются ли указатели s1 и s2 на один и тот же

                 массив? */

              /* (обычно это нежелательно) */

}

if (strcmp(s1,s2)==0) { /* хранят ли строки s1 и s2 одни и те же

                           символы? */

}

Функция

strcmp()
может дать три разных ответа. При заданных выше значениях
s1
и
s2
функция
strcmp(s1,s2)
вернет нуль, что означает полное совпадение. Если строка
s1
предшествует строке
s2
в соответствии с лексикографическим порядком, то она вернет отрицательное число, и если строка
s1
следует за строкой
s2
в лексикографическом порядке, то она вернет положительное число. Термин лексикографический (lexicographical) означает “как в словаре.” Рассмотрим пример.

strcmp("dog","dog")==0

strcmp("ape","dodo")<0 /* "ape" предшествует "dodo" в словаре */

strcmp("pig","cow")>0 /* "pig" следует после "cow" в словаре */

Результат сравнения указателей

s1==s2
не обязательно равен 0 (
false
). Механизм реализации языка может использовать для хранения всех строковых литералов одну и ту же область памяти, поэтому можем получить ответ 1 (
true
). Обычно функция
strcmp()
хорошо справляется со сравнением С-строк.

Длину С-строки можно найти с помощью функции

strlen()
.

int lgt = strlen(s1);

Обратите внимание на то, что функция

strlen()
подсчитывает символы, не учитывая завершающий нуль. В данном случае
strlen(s1)==4
, а строка "
asdf
" занимает в памяти пять байтов. Эта небольшая разница является источником многих ошибок при подсчетах.

Мы можем копировать одну С-строку (включая завершающий нуль) в другую.

strcpy(s1,s2); /* копируем символы из s2 в s1 */

Программист должен сам гарантировать, что целевая строка (массив) имеет достаточный размер, чтобы в ней поместились символы исходной строки.

Функции

strncpy()
,
strncat()
и
strncmp()
являются версиями функций
strcpy()
,
strcat()
и
strcmp()
, учитывающими не больше
n
символов, где параметр
n
задается как третий аргумент. Обратите внимание на то, что если в исходной строке больше n символов, то функция
strncpy()
не будет копировать завершающий нуль, поэтому результат копирования не будет корректной С-строкой. Функции
strchr()
и
strstr()
находят свой второй аргумент в строке, являющейся их первым аргументом, и возвращают указатель на первый символ совпадения. Как и функция
find()
, они выполняют поиск символа в строке слева направо. Удивительно, как много можно сделать с этими простыми функциями и как легко при этом допустить незаметные ошибки. Рассмотрим простую задачу: конкатенировать имя пользователя с его адресом, поместив между ними символ @. С помощью класса
std::string
это можно сделать так:

string s = id + '@' + addr;

С помощью стандартных функций для работы с С-строками этот код можно написать следующим образом:

char* cat(const char* id, const char* addr)

{

  int sz = strlen(id)+strlen(addr)+2;

  char* res = (char*) malloc(sz);

  strcpy(res,id);

  res[strlen(id)+1] = '@';

  strcpy(res+strlen(id)+2,addr);

  res[sz–1]=0;

  return res;

}

Правильный ли ответ мы получили? Кто вызовет функцию

free()
для строки, которую вернула функция
cat()
?

ПОПРОБУЙТЕ

Протестируйте функцию

cat()
. Почему в первой инструкции мы добавляем число 2? Мы сделали глупую ошибку в функции
cat()
, найдите и устраните ее. Мы “забыли” прокомментировать код. Добавьте соответствующие комментарии, предполагая, что читатель знает стандартные функции для работы с С-строками.

27.5.1. Строки в стиле языка С и ключевое слово const

Рассмотрим следующий пример:

char* p = "asdf";

p[2] = 'x';

 

Программирование. Принципы и практика использования C++ Исправленное издание - _003.png
 В языке С так писать можно, а в языке С++ — нет. В языке C++ строковый литерал является константой, т.е. неизменяемой величиной, поэтому оператор p
[2]='x'
(который пытается превратить исходную строку в строку "asxf") является недопустимым. К сожалению, некоторые компиляторы пропускают присваивание указателю
p
, что приводит к проблемам. Если вам повезет, то произойдет ошибка на этапе выполнения программы, но рассчитывать на это не стоит. Вместо этого следует писать так:

const char* p = "asdf"; // теперь вы не сможете записать символ

                        // в строку "asdf" с помощью указателя p

393
{"b":"847443","o":1}