Процедурное программирование на языке С. Часть 2. Указатели на объекты. Многоуровневая адресация: Методические указания к лабораторным работам по курсам «Алгоритмические языки и программирование» и «Процедурное программирование», страница 13

1.  Для статического многомерного массива выделяется 1 участок памяти, а для динамического – несколько.

2.  При выделении памяти для статического многомерного массива программе автоматически становятся доступными указатели-константы, память под которые не выделяется. При выделении памяти для динамического многомерного массива прежде всего следует выделить память для указателей-переменных (их значениями будут адреса по аналогии со значениями указателей-констант для статического массива), а только потом можно выделять участки памяти для элементов массива и сохранять начальные адреса выделенных участков в переменных-указателях.

Программа примера 5.4 демонстрирует выделение памяти для  матрицы, каждый элемент которой – любой представимый символ. Матрица состоит из hстрок и lстолбцов. Используются разные способы ввода  значений элементов матрицы. Использование спецификации %s в управляющей строке функции scanf() обеспечивает ввод сразу всех символов очередной строки матрицы. При этом очередная строка автоматически завершается нулевым символом. Тем самым матрица рассматривается как массив, состоящий из h строк, длина каждой строки – l (без учета нулевого символа). Значения переменных h и lвводятся с клавиатуры в ходе выполнения программы. Приведены и способы вывода значений элементов матрицы на экран.

Пример 5.4.

#include <stdio.h>

#include <stdlib.h>

void main (void)

{ char c; char **x;             int l, h, i, j;

 printf("Vvod dlini stroki\n");     scanf("%d",&l);

 printf("Vvod kolihestva strok\n");         scanf("%d",&h);

x=(char**)malloc(h*sizeof(char*)); /*Выделение памяти  для адресов всех строк*/

for (i=0; i< h ; i++)

         *(x+i)=(char*)malloc((l+1)*sizeof(char)); /* На i-ой итерации цикла выделяется память под i-ую строку*/

for (i=0; i<h; i++)

         {  printf("\n Vvod %d stroki \n",i); scanf("%s",*(x+i));

 /* На экран выводится  i-ая строка, т.е. все символы, записанные с начального адреса *(x+i) до символа ‘\0’;   */   }

/*  Далее возможны различные  варианты вывода символов на экран*/

printf("\n Variant vvoda_1:”); 

for (i=0; i<h; i++)

printf("\nStrokasnomerom  %d :  %s ",i, *(x+i));   /*  На экран выводится i-ая строка,  начиная с ее  адреса    *(x+i) */

printf("\nVariantvvoda_2:”); 

for (i=0; i<h; i++)  printf("\nStrokasnomerom  %d : %s ",i,x[i]);      /* На экран выводится i-ая строка,  начиная с ее  адреса    x[i], при этом выражение   *(x+i)   эквивалентно выражению    x[i], */

printf("\n Variant vvoda_3:”); 

for (i=0; i<h; i++)

  { for (j=0;j<l-1;j++)

        {printf("\n Vvod %d simbol % d stroki  ", j,i);

c=getchar(); /* Искусственное очищение входного потока: вместо

использования функции fflush()*/

        scanf ("%c",(*(x+i)+j)); /*   Ввод символа по адресу элемента массива, при этом выражение   &x[i][j]   эквивалентно выражению   *(x+i)+j   */

        }     x[i][l-1]='\0'; /* Завершение каждой строки нулевым символом. Если при посимвольном вводе «вручную»  не дописать нулевой символ,  то при выводе на экран строки с  использование спецификации %s в функции printf () на  экране после самой строки появится "мусор" */

}     printf("\n Variant vivoda_1:”); 

for (i=0; i<h; i++)

 {    printf("\n  stroka  s nomerom  % d =  ",i);

     for (j=0;j< l-2;j++)

printf("\t%c",x[i][j]); /*   Вывод символа как элемента массива */    

}      printf("\n Variant vivoda_2:”); 

for (i=0; i<h; i++)

 {    printf("\n  stroka s nomerom  % d =  ",i);

for (j=0;  x[i][ l-1];  j++)       printf("\t%c",x[i][j]);    /*   Вывод символа как элемента массива, при этом условие завершение цикла по j : значением элемента является нулевой символ */    

}   printf("\n Variant vivoda_3:”); 

for (i=0; i<h; i++)

printf("\nstrokasnomerom  % d :  %s ", i , x[i]);  /*   вывод на экран  символов i -ой строки, начиная с ее адреса,  x[i], до нулевого символа */