Статический массив указателей можно использовать также для работы с массивом строк, количество которых определено в виде константы. Пусть нам надо представить в виде массива список студентов группы (фамилия, инициалы).
Это можно сделать без использования массива указателей, обычным образом объявив матрицу символов:
char FIO[40][20];
Здесь 40 — максимальное количество студентов в группе, а длина каждой фамилии с именем и отчеством не превышает 19 символов (букв). Напомним, что один байт будет использоваться для хранения символа конца строки. При таком определении массива его размеры всегда фиксированы: 40*20= 850 байт. Как для фамилии “Шилдт Г.”, так и для фамилии “Страуструп Б.”, то есть независимо от длины строки, всегда выделяется одно и то же количество байтов (20), указанное в качестве предельного значения второго индекса матрицы FIO.
При определении матрицы один из его предельных размеров (самого левого индекса) можно не указывать:
char FIO2[][20] ={“Петров П. И.”, “Иванов И. С.”, “Сидоров С. К.”};
В этом случае количество элементов массива строк (количество фамилий) определяется инициализацией. Но и в этом случае каждая из трёх строк по-прежнему занимает максимальный объём памяти, равный 20 байтам.
При использовании массива указателей память распределяется гораздо рациональнее. Объявляем статический массив указателей фиксированной размерности n, где n – константа и определяет количество фамилий:
const n=30; char * S[n];
Память под каждую строку резервируем на этапе выполнения в зависимости от её длины. Для этого объявляем дополнительную строку и резервируем для неё (для одной строки, а не для массива!) память максимального размера:
char *t= new char [20];
Затем в цикле вводим строку, для каждой строки массива S динамически выделяем память, размер которой равен длине введённой строки и введённую строку копируем в i–ю строку массива S:
for(int i=0;i<n;i++)
{ gets(t);
S[i]=new char (strlen(t));
strcpy(S[i],t);
}
После этого с S[i] работаем как с обычной строкой. Более того, аналогично, как и в 5.1, можно переставлять две строки (фамилии), не меняя их физически в памяти.
Одномерный массив указателей на строки можно проинициализировать при объявлении:
char *S2[]={“Петровский П. И.”, “Иванов И. С.”, “Сидоров С. К.”};
При таком объявлении компилятор размещает в памяти три строковые константы длиной 17, 13 и 14 байт соответственно, а их адреса становятся значениями элементов массива указателей S2[0], S2[1], S2[2].
Пример 1. (+). Работа со статическим массивом строк как со статическим массивом указателей на строки. В каждой строке массива строк удалить введённый символ.
int main() { const n=5;
/* Объявляем статический массив указателей фиксированной размерности n, где n – константа.*/
char *S[n]; char C,*p, t[40]; cout<<"Symbol"; C=getch();
unsigned K=0; cout << endl<<endl;
for(int i=0;i<n;i++)
{ gets(t);
/* Для каждой строки динамически выделяем память, размер которой равен длине строки */
S[i]=new char [strlen(t)];
strcpy(S[i],t); // Введённую строку копируем в i–ю строку массива S
}
for(int i=0;i<n;i++)
{ p=S[i]; // В p засылаем адрес строки S[i]
do
{ /* Начиная с p, находим адрес символа C и засылаем его в эту же переменную указатель p */
p=strchr(p,C);
if (!p) /* это тоже самое, что if (p == NULL), т.е. если не нашли символ C, то заканчиваем анализ строки */
break;
K++;
strcpy(p,p+1); /* Удаляем найденный символ, т. е. всю строку сдвигаем на один символ влево */
}
while(1);
}
for(int i=0;i<n;i++) puts (S[i]); // Вывод массива слов
cout <<"\n Number"<< K<<" ";
getch(); return 0; }