Конспект лекций по Си
.pdfРис. 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