Программирование на C и C++

Онлайн справочник программиста на C и C++

Указатели на символьные массивы

Многие строковые операции в С выполняются с помощью указателей, поскольку доступ к строкам осуществляется последовательно.

Например, здесь показана версия стандартной библиотечной функции strcmp(), использующей указатели:

/* Использование указателей. */
int strcmp (const char *s1, const char *s2)
{
while(*s1) if(*s1-*s2)
return *s1-*s2;
else {
s1++;
s2++;
}
return 0; /* равенство */
}

Надо помнить, что все строки в С оканчиваются нулевым символом, который интерпретируется как ложь. Следовательно, оператор

while (*s1)

выдает истину, пока не достигнет конца строки. strcmp() возвращает 0, если s1 равно s2. Она возвращает число меньше 0, если s1 меньше s2. Иначе возвращает число больше нуля.

Большинство строковых функций похожи по способу работы на strcmp(). Особенно там, где используется контролирующий цикл. Использование указателей быстрее, более эффективно и часто легче для понимания, чем использование индексации массива. Типичная ошибка использования указателей продемонстрирована в следующей программе:

/* Данная программа некорректна */
#include <stdio.h>
#include <string.h>
int main(void)
{
char *p1, s[80];
p1 = s; /* присвоение p1 базового адреса s */
do {
gets(s); /* чтение строки */

/* вывод десятичного эквивалента каждого символа */
while (*p1) printf (" %d", *p1++);
} while (strcmp (s, "done"));
return 0;
}

Где здесь ошибка?

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

/* Программа корректна. */
#include <stdio.h>
#include <string.h>
int main(void)
{
char *p1, s [80];
do {
p1 = s; /* присвоение p1 базового адреса s */
gets(s); /* чтение строки */

/* вывод десятичного эквивалента каждого символа */
while(*p1) printf (" %d", *p1++);
} while(strcmp(s, "done"));
return 0;
}

Здесь на каждой итерации цикла p1 присваивается начало строки s.