Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
http.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.34 Mб
Скачать

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

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

Например, здесь показана версия стандартной библиотечной функции 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.

Массивы указателей

Можно создавать массивы указателей. Для объявления массива целочисленных указателей из десяти элементов следует написать: int *х[10]; Для присвоения адреса целочисленной переменной var третьему элементу массива следует написать: х[2] = &var; Для получения значения var следует написать: *х [2]

Если необходимо передать массив указателей в функцию, можно использовать метод, аналогичный передаче обычных массивов. Просто надо вызвать функцию с именем массива без индексов. Например, функция, получающая массив х, должна выглядеть следующим образом: void display_array(int *q[]) { int t; for(t=0; t<10; t++) printf ("%d ", *q[t]); } Надо помнить, что q - это не указатель на целое, а массив указателей на целые. Следовательно, необходимо объявить параметр q как массив целых указателей. Он не может объявиться как простой целочисленный указатель, поскольку он не является им.

Типичным использованием массивов указателей является хранение сообщений об ошибках. Можно создать функцию, выводящую сообщение по полученному номеру, как показано ниже: void serror(int num) { static char *err[] = { "Cannot Open File\n", "Read Error\n", "Write Error\n", "Media Failure\n" }; printf ("%s", err[num]); } Как можно видеть, printf() в serror() вызывается с указателем на символ, указывающим на одно из сообщений, номер которого передается в функцию. Например, если num приняла значение 2, будет выведено сообщение «Write Error».

Интересно заметить, что аргумент командной строки argv является массивом указателей на символы.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]