Этот шаг будет посвящен взаимосвязи строк и указателей.
В программе доступ к строке осуществляется с помощью указателя на символ. Если описать переменную message как
char *message;
message = "и прощай!";
#include <iostream.h> char *message; char privet[] = "и прощай!"; char *pr = privet; void main () { message = "Здравствуй"; cout << " " << message << " " << pr << endl; int i = 0; while (*(pr+i)!='\0') { cout << *(pr+i++) << " "; } }
Приступим к работе с массивом строк. В этом случае к каждой строке можно обратиться с помощью указателя на его первый символ. Это удобно тем, что для перестановки двух строк, расположенных в неправильном порядке, фактически достаточно переставить указатели в массиве указателей, а не сами строки.
Рассматривается функция month_name(), которая возвращает указатель на строку, содержащий имя n-го месяца. Это типичная задача для использования внутреннего статического массива (инициализировать можно только массивы внешнего или статистического класса памяти!).
Функция month_name() содержит локальный массив строк и при обращении к ней возвращает указатель на нужную строку.
В описании массива указателей на символы name[] инициализатором является просто список строк. Символы i-й строки помещаются в определенное место памяти, а указатель на ее начало хранится в элементе name[i]. Поскольку размер массива name не указан, компилятор сам подсчитывает количество инициализаторов и соответственно устанавливает правильное число.
#include <iostream.h> #define n 15 void main () { char *month_name(int); /* ------------- */ for (int i=0; i < n; i++) cout << "месяц номер " << i << " - " << month_name(i) << endl; } /* ------------------------------------------- */ char *month_name (int k) /* Название k-го месяца */ { static char *name[] = { "неверный месяц","январь", "февраль","март","апрель", "май","июнь","июль","август", "сентябрь","октябрь","ноябрь", "декабрь" }; return (k<1||k>12)?name[0]:name[k]; }
Результат работы программы:
месяц номер 0 - неверный месяц месяц номер 1 - январь месяц номер 2 - февраль месяц номер 3 - март месяц номер 4 - апрель месяц номер 5 - май месяц номер 6 - июнь месяц номер 7 - июль месяц номер 8 - август месяц номер 9 - сентябрь месяц номер 10 - октябрь месяц номер 11 - ноябрь месяц номер 12 - декабрь месяц номер 13 - неверный месяц месяц номер 14 - неверный месяц
#include <iostream.h>
char *c[]={ "ENTER","NEW","POINT","FIRST" };
char **cp[]={ c+3,c+2,c+1,c };
char ***cpp=cp;
void main ()
{
cout << **++cpp;
cout << *--*++cpp+3 << " ";
cout << *cpp[-2]+3;
cout << cpp[-1][-1]+1 << endl;
}
Результаты работы программы:
POINTER STEW
Ответы и комментарии.
char *c[]={ "ENTER" c - массив ссылок на символ. Элементы c иници- "NEW" ализируются так, что они указывают на массивы "POINT" символов "ENTER", "NEW", "POINT" и "FIRST". "FIRST" }; char **cp[]={ Описатель **cp[] соответствует символу, *cp - c+3,c+2,c+1,c ссылке на символ и cp[] - ссылке на ссылку на }; символ. Элементы cp инициализируются так, что они указывают на элементы c. char ***cpp = cp; Описатель ***cpp дает символ, **cpp - ссылку на символ, *cpp - ссылку на ссылку на символ, наконец, cpp - ссылка, указывающая на ссылку на ссылку на символ.
В рисунках, приведенных ниже, сплошными линиями обозначены указатели, а пунктирными - временные ссылки аргументов для вывода.
Рисунок 1 показывает взаимосвязь между cpp, cp и c.
Рис.1. Взаимосвязь между cpp, cp и c
*(*(++cpp)) Увеличим cpp, а затем проследим цепочку ссылок. (Рис.2)
Рис.2. Цепочка ссылок
(*(--(*(++cpp))))+3 Увеличим cpp, по ссылке дойдем до cp[2], уменьшим cp[2],по ссылке дойдем до c[0] и эту ссылку (т.е. c[0]) увеличим на 3. (Рис.3)
Рис.3. Цепочка ссылок
(*(cpp[(-2)]))+3 Индексируя cpp значением -2, получим cp[0], по ссылке дойдем до c[3] и проиндексируем его значением 3. (Рис.4)
Рис.4. Цепочка ссылок
((cpp[-1])[-1])+1 Индексируя cpp значением -1, получим cp[1], снова индексируем с -1 и доходим до c[1], эту последнюю ссылку индексируем значением 1. (Рис.5)
Рис.5. Цепочка ссылок
Если вы правильно решили последнюю задачу, то знаете все, что можно знать о механизме использования ссылок.
Сила ссылок заключается в их универсальности: ссылки можно связывать
друг с другом,
получая сложные структуры данных. Но опасность ссылок как раз и
заключается в их
силе: сложные цепочки ссылок редко бывают понятными и еще реже верными!
На следующем шаге мы рассмотрим функции работы со строками.