5.5. Указатели символов и функции
Строчная константа, как, например,
“I AM A STRING”
является массивом символов. Компилятор завершает внутреннее
представление такого массива символом \0, так что программы
могут находить его конец. Таким образом, длина массива в па-
мяти оказывается на единицу больше числа символов между
двойными кавычками.
По-видимому чаще всего строчные константы появляются в
качестве аргументов функций, как, например, в
PRINTF (“HELLO, WORLD\N”);
когда символьная строка, подобная этой, появляется в прог-
рамме, то доступ к ней осуществляется с помощью указателя
символов; функция PRINTF фактически получает указатель сим-
вольного массива.
Конечно, символьные массивы не обязаны быть только аргу-
ментами функций. Если описать MESSAGE как
CHAR *MESSAGE;
то в результате оператора
MESSAGE = “NOW IS THE TIME”;
переменная MESSAGE станет указателем на фактический массив
символов. Это не копирование строки; здесь участвуют только
указатели. в языке “C” не предусмотрены какие-либо операции
для обработки всей строки символов как целого.
Мы проиллюстрируем другие аспекты указателей и массивов,
разбирая две полезные функции из стандартной библиотеки вво-
да-вывода, которая будет рассмотрена в главе 7.
·
109 -
Первая функция - это STRCPY(S,T), которая копирует стро-
ку т в строку S. Аргументы написаны именно в этом порядке по
аналогии с операцией присваивания, когда для того, чтобы
присвоить T к S обычно пишут
S = T
сначала приведем версию с массивами:
STRCPY(S, T) /* COPY T TO S */
CHAR S[], T[];
{
INT I;
I = 0;
WHILE ((S[I] = T[I]) != '\0')
I++;
}
Для сопоставления ниже дается вариант STRCPY с указате-
лями.
STRCPY(S, T) /* COPY T TO S; POINTER VERSION 1 */ CHAR *S, *T;
{
WHILE ((*S = *T) != '\0') {
S++;
T++;
}
}
Так как аргументы передаются по значению, функция STRCPY
может использовать S и T так, как она пожелает. Здесь они с
удобством полагаются указателями, которые передвигаются
вдоль массивов, по одному символу за шаг, пока не будет ско-
пирован в S завершающий в T символ \0.
На практике функция STRCPY была бы записана не так, как
мы показали выше. Вот вторая возможность:
STRCPY(S, T) /* COPY T TO S; POINTER VERSION 2 */ CHAR *S, *T;
{
WHILE ((*S++ = *T++) != '\0')
;
}
Здесь увеличение S и T внесено в проверочную часть. Зна-
чением *T++ является символ, на который указывал T до увели-
чения; постфиксная операция ++ не изменяет T, пока этот сим-
вол не будет извлечен. Точно так же этот символ помещается в
старую позицию S, до того как S будет увеличено. Конечный
результат заключается в том, что все символы, включая завер-
шающий \0, копируются из T в S.
· 110 -
И как последнее сокращение мы опять отметим, что сравне-
ние с \0 является излишним, так что функцию можно записать в
виде
STRCPY(S, T) /* COPY T TO S; POINTER VERSION 3 */
CHAR *S, *T;
{
WHILE (*S++ = *T++)
;
}
хотя с первого взгляда эта запись может показаться загадоч-
ной, она дает значительное удобство. Этой идиомой следует
овладеть уже хотя бы потому, что вы с ней будете часто вст-
речаться в “C”-программах.
Вторая функция - STRCMP(S, T), которая сравнивает сим-
вольные строки S и т, возвращая отрицательное, нулевое или
положительное значение в соответствии с тем, меньше, равно
или больше лексикографически S, чем T. Возвращаемое значение
получается в результате вычитания символов из первой пози-
ции, в которой S и T не совпадают.
STRCMP(S, T) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */
CHAR S[], T[];
{
INT I;
I = 0;
WHILE (S[I] == T[I])
IF (S[I++] == '\0')
RETURN(0);
RETURN(S[I]-T[I]);
}
Вот версия STRCMP с указателями:
STRCMP(S, T) /* RETURN <0 IF S<T, 0 IF S==T, >0 IF S>T */ CHAR *S, *T;
{
FOR ( ; *S == *T; S++, T++)
IF (*S == '\0')
RETURN(0);
RETURN(*S-*T);
}
так как ++ и—могут быть как постфиксными, так и
префиксными операциями, встречаются другие комбинации * и
++ и --, хотя и менее часто.
Например
*++P
·
111 -
увеличивает P до извлечения символа, на который указывает
P, а
*--P
сначала уменьшает P.
Упражнение 5-2.
Напишите вариант с указателями функции STRCAT из главы
2: STRCAT(S, T) копирует строку T в конец S.
Упражнение 5-3.
Напишите макрос для STRCPY.
Упражнение 5-4.
Перепишите подходящие программы из предыдущих глав и уп-
ражнений, используя указатели вместо индексации массивов.
Хорошие возможности для этого предоставляют функции GETLINE
/главы 1 и 4/, ATOI, ITOA и их варианты /главы 2, 3 и 4/,
REVERSE /глава 3/, INDEX и GETOP /глава 4/.
... основаниям. При этом философская абстракция языка оказывается неразрывно связана с основными темами и движениями философии в целом. Более конкретно, на ранние стадии традиционно рассматриваемого в рамках АФ анализа обыденного языка глубокое влияние оказала философия Дж. Э. Мура, особенно его учение о здравом смысле, согласно которому такие понятия, как «человек», «мир», «я», «внешний мир», « ...
... и других странах СНГ, а также облегчение доступа к русской и мировой культуре и науке. Таким образом, судя по данным наших исследований, востребованность русского языка осталась в республике достаточно высокой. Многие представители современной молдавской молодежи продолжают, как их отцы и деды, тянуться к русской культуре, научным и техническим достижениям России. Русский язык остается языком ...
... рисуночное словесно-слоговое письмо). Памятники среднеэламского периода (14—12 вв. до н.э.) выполнены аккадской клинописью. Памятники новоэламского периода относятся к 8—6 вв. до н.э. Был официальным языком в персидском государстве Ахеменидов в 6—4 вв. предполагается, что он, подвергшись влиянию древнеперсидского, сохранился до раннего средневековья. 7. Бурушаски язык Язык бурушаски ( ...
... /диалект), скифский, согдийский, среднеперсидский, таджикский, таджриши (язык/диалект), талышский, татский, хорезмийский, хотаносакский, шугнано-рушанская группа языков, ягнобский, язгулямский и др. Они относятся к индоиранской ветви индоевропейских языков. Области распространения: Иран, Афганистан, Таджикистан, некоторые районы Ирака, Турции, Пакистана, Индии, Грузии, Российской Федерации. Общее ...
0 комментариев