Свободные массивы и указатели
Термин “свободный ” относят к двумерным массивам. Свободный массив – это массив, в котором длины его строк (то есть количество элементов в строке) могут быть различными. Свободные массивы могут быть любого типа. Для работы со свободными массивами используют массивы указателей, содержащие количество элементов, равное количеству строк свободного массива. Оперативная память для каждой строки может выделяться либо статически, либо динамически. Например:
int *a[100];
Объявлен массив указателей ( в нем 100 элементов) на данные типа int. Память выделяется для 100 указателей , по одному указателю на каждую из 100 строк свободного массива. Память для строк массива не выделена. Это можно сделать динамически. Например, если m - количество элементов в строке с индексом i, то память для этой строки может быть выделена так:
a[i] = (int *)malloc(m*sizeof )int) );
Наиболее часто свободные массивы в программах на С используются при работе со строками, когда нужно иметь стандартный набор строк. Например, если мы хотим хранить сообщения о возможных ошибках, это можно сделать так:
char *errors[]={“Невозможно открыть файл”,
“Ошибка распределения памяти”,
“Системная ошибка”
};
Таким объявлением память распределена:
1. Для одномерного массива указателей. Количество элементов этого массива определяется при его инициализации – по количеству символьных строк. Каждый указатель содержит адрес начала соответствующей символьной строки. Для нашего примера память выделена под массив указателей, в котором 3 элемента – по количеству строк свободного массива.
2. Для двумерного символьного массива со строками разной длины:
errors[ 0 ] | Н | е | в | о | з | м | о | ж | н | о | о | т | к | р | ы | т | ь | ф | а | й | л | \0 | ||||||
errors[ 1 ] | О | ш | и | б | к | а | р | а | с | п | р | е | д | е | л | е | н | и | я | п | а | м | я | т | и | \0 | ||
errors[ 2 ] | С | и | с | т | е | м | н | а | я | о | ш | и | б | к | а | \0 |
В памяти строки этого массива будут располагаться друг за другом, каждая строка займет минимально возможную память:
Здесь нет неиспользуемых байт, которые появились бы, если бы был объявлен двумерный массив:
char errors[3][28]={“Невозможно открыть файл”,
“Ошибка распределения памяти”,
“Системная ошибка”
};
При таком объявлении каждая строка занимает 28 байт – по размеру самой длинной строки- ‘Ошибка распределения памяти”,, поэтому при размещении строки, например ”Системная ошибка” будет занято всего 17 байт, а 11 байт окажутся не использованными.
Преимущества использования массивов указателей на строки:
1. каждая строка занимает минимально возможную память;
2. появляется возможность манипулировать не с самими строками, а только с их указателями, что дает значительный выигрыш в скорости работы программы при решении , например, задач, сортировки строк.
Пример.Сортировка строк в алфавитном порядке. Используется алгоритм пузырьковой сортировки.
#include <stdio.h>
#include <string.h>
#define SIZE 81 //предел длины строки, включая ‘\0’
#define LIM 20 //максимальное количество сортируемых строк
#define STOP " " //признак конца ввода – ввод пустой строки
void main(void)
{
// массив для сохранения результатов ввода строк в памяти
unsigned char input[LIM][SIZE];
// массив указателей на строки
unsigned char *ptstr[LIM];
// указатель на переменную, используемую в процессе перестановки
unsigned char *temp;
// управляющие переменные циклов
int i,jk;
int ct=0; //счетчик введенных строк
printf ("Введите не более %d строк, которые нужно отсортировать",LIM);
puts("Окончание ввода - пустая строка");
//ввод продолжается, пока не прочитано LIM строк и пока не введена пустая строка
while ( ct < LIM && gets (input[ct]) !=NULL && input[ct][0]!='\0')
{
//установка указателей на строки
//указателю на строку присваивается адрес очередной введенной строки
ptstr[ct]=input[ct];
ct++;
}
//выполнение сортировки строк путем сортировки указателей
for(i=0; i<ct-1; i++)
for(j=i+1; j<ct; j++)
{
if(strcmp(ptstr[i],ptstr[j]) >0)
{//перестановка указателей на строки
temp= ptstr[i];
ptstr[i]=ptstr[j];
ptstr[j]=temp;
}
}
//вывод отсортированных строк
puts("Отсортированный массив");
for(k=0; k<ct; k++)
puts(ptstr[k]);
}