Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Конспект лекций по Си

.pdf
Скачиваний:
116
Добавлен:
08.05.2015
Размер:
636.16 Кб
Скачать

Рис. 22.1

Фрагмент программы реализации двухмерного массива со строками одинаковой длины показан ниже.

#include <malloc.h> #include <stdio.h> main()

{

float **b;

int n, m, i, j;

printf ("\n введите количество строк n="); scanf ("%d", &n);

printf ("\n введите количество столбцов m="); scanf ("%d", &m); b=(float**)malloc(n*sizeof(float*)); /*Выделяется блок оперативной памяти для хранения

адресов строк матрицы. Используется двойная косвенная адресация.*/

for (i=0; i<=n-1; i++) b[i]=(float*)malloc(n*sizeof(float)); /*В цикле динамически выделяются блоки

оперативной памяти под строки. Адреса строк записываются в массив указателей b. */

for (i=0; i<=n-1; i++) for (j=0; j<=m-1; j++)

{

51

printf ("\n введите элемент b[%d][%d]=", i+1, j+1);

scanf ("%f", &b[i][j]);

}

for (i=0; i<=n-1; i++) for (j=0; j<=m-1; j++)

{

. . .

b[i][j]= /* обработка массива */

. . .

}

. . .

}

Для размещения в оперативной памяти матрицы со строками разной длины необходимо ввести дополнительный массив m, в котором будут храниться размеры строк. Фрагмент программы, в которой реализуется динамическое размещение такой матрицы приведен ниже.

#include <stdio.h> #include <malloc.h> main()

{

float **b; int i, j, n; int *m;

printf("\nВведите количество строк n= "); scanf("%u", &n);

b=(float **) malloc (n*sizeof(float*)); m=(int *) malloc(n*sizeof(int));

for(i=0; i<=n-1; i++)

{

printf("\n Введите длину строки m[%u]=", i+1); scanf("%u", m+i)

}

for(i=0; i<=n-1; i++) b[i]=(float*)malloc(m[i]*sizeof(float));

for(i=0; i<=n-1; i++)

52

for(j=0; j<=m[i]-1; j++)

{

printf("\n Введите элемент b[%u][%u]= ", i+1, i+1);

scanf("%f",& b[i][j]);

}

for(i=0; i<=n-1; i++) for(j=0; j<=m[i]-1; j++)

{

. . .

b[i][j]= . . .

}

. . .

}

Графическое представление двухмерного массива со строками разной длины представлено на рис. 22.2.

Рис. 22.2.

Для динамического распределения памяти под трехмерный массив необходимо размером n*m*l необходимо: 1) динамически, как в первом примере, выделить память под матрицу адресов размером n*m, 2) динамически выделить память под n*m строк, состоящих из l элементов, и 3) сохранить адреса этих строк в матрице. Графическое представление такой конструкции в опертивной памяти представлено на рис. 22.3. Обращение к элементу массива будет осуществляться следующим образом:

b[i][j][k],

где i, j, k — индексы, определяющие положение элемента в трехмерном массиве.

53

Фрагмент программы, реализующей трехмерный массив, приведен ниже.

#include <malloc.h> #include <stdio.h> main()

{

float ***b;

int n, m ,l i, j, k;

printf ("\n Введите n, m, l \n"); scanf ("%u u %u", &n, &m, &l);

b=(float***)malloc(m*sizeof(float**)); /*матрица*/ for (i=0; i<=m-1; i++)

b[i]=(float**)malloc(n*sizeof(float*));

for (i=0; i<=m-1; i++) for (j=0; j<=n-1; j++)

b[i]=(float*)malloc(l*sizeof(float)); /*строки*/

/ инициализация массива */ for (i=0; i<=m-1; i++) for (j=0; j<=n-1; j++) for (k=0; k<=l-1;k++)

{

printf("\nВведите b[%u][%u][%u]=",i+1,j+1,k+1); scanf ("%f", &b[i][j][k]);

}

/* обработка массива */ for(i=0; i<= m-1; i++) for(j=0; j<= n-1; j++) for(k=0; k<=l-1; k++)

{

. . .

b[i][j][k]= . . .

}

...

}

54

Рис. 22.3

Пример 1. Разработать программу, которая печатает название месяца по введенному номеру и выявляет неверно введенный номер месяца.

Названия месяцев и фраза «неверно введен номер месяца» являются одномерными массивами символов различной длины — строками. Каждой из этих строк можно поставить в соответствие указатель на её начало (см. рис. 25.4).

*name[0] ->"Неверно введен номер месяца";

*name[1] ->"Январь" \0 *name[2] ->"Февраль" \0

. . .

*name[11]->"Ноябрь" \0 *name[12]->"Декабрь" \0

Рис. 25.4. Схема хранения информации

Каждый указатель name[i] будет ссылаться на ячейку памяти, непосредственно следующую за ячейкой, в которой размещен символ '\0' предыдущей строки. Поэтому запрашиваемая память будет в точности соответствовать фактической потребности в ней.

Программа

#include <stdio.h> main()

{

char *name[]={

55

"Неверно введен номер массива", "Январь","Февраль","Март","Апрель", "Май","Июнь","Июль","Август", "Сентябрь","Октябрь","Ноябрь","Декабрь" };

int i;

printf("\n Укажите номер месяца\n"); scanf("%d",&i);

if(i<1||i>12) printf("%s", name[0]):

else

printf("%s", name[i]); for(i=0;i<13;i++)

printf("\n Адрес name[%d]= %u",i,name[i]);

}

Результат работы программы

Укажите номер месяца

2 <Enter>

Февраль

Адрес name[0]=196 Адрес name[1]=224 Адрес name[2]=231 Адрес name[3]=239

. . . . .

Пример 2. С оптового рынока продукция постовляется в четыре магазина. Магазины подают заявки, которые сразу же выполняются. Необходимо подсчитать суммарное количество продукции, поставленной с рынка каждому магазину за некоторый период. Объемы поставок опишем в виде двухмерного массива, строки которого соответствуют магазинам, столбцы — порядковым номером заявок. Поскольку каждый магазин подает различное число заявок, то статическое распределение памяти под массив неэффективно. Попробуем использовать массив указателей и динамическое распределение памяти для хранения полученных от магазинов заявок. Структура хранения информации представлена на рис. 2.22.5.

56

Рис. 2.22.5

Программа

#include <malloc.h> #include <stdio.h>

main()

{

int *post[4]; /*объем поставок*/ int kol[4]; /*количество заявок*/ int s[4]; /*суммарные поставки*/

int i, j; /*вспомогательные переменные */

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

{

printf ("Введите количество заявок для %u -го магазина \n", i+1);

scanf ("%d", &kol[i];) post[i]=(int*)malloc(kol[i]*sizeof(int));

/*Распределение памяти под объемы поставок */ printf ("Введите объем поставок %u -го магазина в

количестве %d штук \n", i+1, kol[i]);

for (j=0; j<kol[i]; j++) scanf ("%d", post[i]+j);

}

/*Определение суммарного объема поставок*/

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

{

s[i]=0;

for (j=0; j<kol[i]; j++) s[i]+=*(post[i]+j);

}

57

printf ("\n \n Объемы поставок"); for (i=0; i<4; i++)

{

printf ("Магазин № %d: %d штук \n", i+1, s[i]); free (post[i]);

}

}

§23. Структуры

Структура — это объединение одного или нескольких объектов, возможно, различного типа под одним именем, которое является типом структуры. В качестве объектов могут выступать переменные, массивы, указатели и другие структуры.

Структуры позволяют трактовать группу связанных между собой объектов не как множество отдельных элементов, а как единое целое.

Пример — строка платёжной ведомости, которая содержит следующие сведения о работнике: полное имя, адрес, зарплату и так далее.

Таким образом, структура — сложный тип данных, составленный из простых типов.

Общая форма объявления структуры

struct тип_структуры

{

тип_1 имя элемента1; тип 2 имя элемента2;

. . .

тип_n имя элементаn;

};

После закрывающей фигурной скобки « } » в объявлении структуры обязательно ставится точка с запятой.

Пример объявления структуры

struct date

{

int day; int month; int year;

};

Элементы структуры располагаются в памяти ЭВМ в том же порядке, в котором они объявляются.

При объявлении структур, их разрешается вкладывать одну в другую.

58

Пример

struct persone

{

char fam[20]; char im[20]; char ot [20]; struct date bd;

};

Здесь одним из элементов структуры person является структура типа date с именем структурной переменной bd (birthday).

Инициализация структуры может осуществляться двумя способами:

присвоение значений элементам структуры в процессе объявления переменной, относящейся к типу структуры;

присвоение начальных значений элементам структуры с использованием функций printf() и scanf().

В первом случае инициализация осуществляется по следующей форме:

struct тип_структуры имя_переменной= {значение_элемента_1, значение_элемента_2, . . . , значение_ элемента_n};.

Второй случай не отличается от способа инициализации объектов языка Си уже известных типов.

Для обращения к элементу структуры нужно указать не только имя самого элемента, но и имя переменной. Они разделяются точкой:

имя_переменной.имя_элемента.

Иногда говорят, что имя элемента структуры является составным.

Имя структурной переменной может быть указано при объявлении структуры. В этом случае оно размещается после закрывающейся фигурной скобки.

Пример

struct complex_type

{

double real; doubl imag;

} number;

59

В этом примере элементами структуры будут переменные number.real и number.imag.

Пример 1. Объявление и инициализация структуры

/* Объявление структуры computer, состоящей из двух элементов: model и memory. */

struct computer

{

char model[30]; int memory;

};

/* Объявление и инициализация переменной elecom типа computer. */

struct compute={"IBM PC Pentium 4", 1024};

Пример 2. Объявление и инициализация структуры

#include <stdio.h> main()

{

/* Объявление структуры типа data. */ struct data

{

int day;

char month[10]; int year;

};

/* Объявление структуры типа person; одним из элементов структуры person является структурная переменная bd типа data.*/

struct person

{

char fam[20]; char im[20]; char ot[20]; struct data bd;

};

/*Объявление структурной переменной ind1 типа person.*/ struct person ind1;

printf ("\n Укажите через Enter фамилию, имя, отчество,");

printf ("\n День, месяц и год рождения гражданина ind1\n");

60