Элементы массива могут иметь любой тип (кроме массива и функции) в том числе могут быть и указателями-переменными. Наиболее часто массивы указателей используется для компактного расположения строк текста, структурных переменных и других “протяженных” объектов данных.
Массивы указателей должны описывается так же как и другие массивы, например, интерпретируем следующее описание массива:
char *massage [20];
1) объект с этим именем есть
2) массив из 20 элементов
3) указателей
4) на символьные данные.
При описание можно задать инициализацию массива:
char *massage [ ] = { “Не открыт файл”,
“Ошибка ввода”,
“Диск”,
“Тайм – аут” };
Компилятор резервирует место для 4-х указателей-констант, равных адресам начала в памяти соответствующих строковых литералов.
Существует принципиальное различие в расположении в памяти массива указателей и, на первый взгляд, подобного ему двухмерного массива:
char array [ ] [16] = { “Не открыт файл”,
“Ошибка ввода”,
“Диск”,
“Тайм – аут” };
Внутреннее преставление массивов array и massage в памяти при компиляции можно представит следующей схемой.
|
|
Массив char array [4] [16] (размер 4*16 = 64 байта):
адреса
(16-чные):
019С | Н | е | о | т | к | р | ы | т | ф | а | й | л | ||||
01AC | О | ш | и | б | к | а | в | в | о | д | а | |||||
01BC | Д | и | с | к | ||||||||||||
01CC | Т | а | й | м | - | а | у | т |
Массив указателей char *massage [4] (размер 8 байт):
01DC | 01EB | 01F8 | 01ED |
Строковые литералы, адресами которых инициировался массив
char *massage [4] (размер 42 байта):
01DС | Н | е | о | т | к | р | ы | т | ф | а | й | л | ||||
01EB | О | ш | и | б | к | а | в | в | о | д | а | |||||
01F8 | Д | и | с | к | ||||||||||||
01ED | Т | а | й | м | - | а | у | т |
Преимущества использования массивов указателей в том, что появляется возможность манипулировать не самими объектами, а только их адресами, что дает выигрыш в скорости выполнения программы, а также в объеме памяти, выделяемой для объектов, например, при перестановке протяженных объектов.
Пример. Выполнить сортировку вводимых с клавиатуры строк в алфавитном порядке. Признаком завершения ввода является ввод пустой строки (“”). Вводимые строки помещаются в двухмерный массив. Сортировка объектов предполагает перемещение их в памяти. Однако перенос текстовых строк из одного места памяти в другое требует значительных затрат времени и места в памяти. Намного проще будет работа с массивом указателей. Он сортируется так, чтобы первый элемент указывал на “наименьшую” (по коду символов) строку, а последний – на “наибольшую” строку. Таким образом сортируется не массив строк, а массив указателей на них.
|
|
В программе для сравнения строк в лексикографическом порядке используется библиотечная функция
int strcmp (const char *s1, const char *s2);
где *s1, *s2 – указатели на строки.
Программа:
#include<stdio.h>
#include<conio.h>
#include<string.h> /* для функции strcmp() */
#define STOPSTR “” /* символ окончания строки */
#define BUFSIZE 81 /* размер буфера */
#define STRNUM 100 /* количество строк */
void main() /* главная программа */
{ char buffer [STRNUM][BUFSIZE]; /* массив для приема строк */
char *pointers [STRNUM], *ptr; /* массив указателей */
int i, ns, ind; /* параметры циклов */
clrscr(); /* очистка экрана */
puts (“Введите строки, заканчивая нажатием клавиши <Enter>.”);
puts (“Для завершения ввода нажмите <Enter>”);
for (ind=0; ind < STRNUM; ind++) /* цикл ввода строк в buffer */
{ gets (buffer[ind]; /* ввод строки */
if (!strcmp(buffer[ind], STOPSTR)) /* если введена пустая строка */
break; /* закончить цикл ввода строк*/
pointers [ind] = buffer [ind]; /* запись указателя в массив */
}
ns = ind; /* запись числа строк */
puts (“Прием строк завершен.”);
puts (“Сортировка строк по возрастанию методом ‘пузырька’:”);
for (ind=0; ind < ns; ind++) /* цикл по строкам */
for (i=ns -1; i >= ind; i- -) /* обратный цикл по строкам */
{ if (strcmp(pointers[i –1], pointers[i]) > 0) /* если строка i > i-1, */
{ ptr = pointers[i]; /* то перестановка */
pointers[i] = pointers[i –1]; /* местами */
pointers[i –1] = ptr; /* указателей */
}
}
for (i=0; i >= ns; i++) /* цикл пока есть строки */
puts (pointers[i]); /* вывод строк по указателям */
puts (“\nНажмите любую клавишу.”);
getch(); /* задержка экрана */
}
Результаты программы:
Введите строки, заканчивая нажатием клавиши <Enter>.
Для завершения ввода нажмите <Enter>
ПЕРВАЯ СТРОКА
ВТОРАЯ СТРОКА
Прием строк завершен.
Сортировка строк по возрастанию методом ‘пузырька’
ВТОРАЯ СТРОКА
ПЕРВАЯ СТРОКА
Нажмите любую клавишу.