5.3. Разработка текста программы
Текст программы начинаем с включения файла stdio.h.
Поскольку нам придется проводить сравнение (блок 15) поля name в элементах массива, а это поле - символьная строка, включаем также файл string.h, где описаны функции работы с символьными строками. В самом начале программы вводим также описание структуры mon и одновременно - объявление массива mm. Массив будет размещен в статической памяти.
Потом открывается главная функция программы, и в ней объявляются остальные переменные. Объявление:
float sqx;
мы прокомментируем ниже.
Открывается простой цикл со счетчиком n, в каждой итерации цикла выводится приглашение и вводятся значения полей очередного элемента массива. Сравнение поля name с константой "***" - признаком конца ввода выполняется с помощью функции strcmp(). Если введен признак конца, происходит досрочный выход из цикла за оператором break.
Следует, однако, остановиться на вводе значения для поля sq. Тут мы столкнулись (не впервые в нашей практике) с явлением, которое не можем объяснить иначе, чем ошибкой в системе программирования: функция scanf() работает ненадежно при вводе значений типа float и double, если это - значения полей элементов массива структур. Поэтому мы объявили рабочую переменную sqx типа float и значение поля sq сначала вводится в эту переменную, а потом присваивается полю структуры.
Вывод массива состоит из вывода заголовка как нескольких строк-констант и вывода в цикле строк с фактическими данными - так же, как в работе ╧2.
Следующие операторы программы подробно реализуют блоки 12 - 17 схемы алгоритма (для сравнения символьных строк применяется функция strcmp()). Детального рассмотрения требует только реализация блока 18 - перестановка элементов. Во-первых, при перестановке используется рабочая структура x: сначала содержимое i-го элемента пересылается в x, потом содержимое m-го элемента пересылается в i-ый элемент, а потом содержимое x пересылается в m-ый элемент. Во-вторых, операция присваивания, которая обычно применяется для пересылки значений, не может применяться к структуре в целом, так что присваивания происходит для каждого поля отдельно. К тому же, поле name является символьной строкой, а строки тоже не могут присваиваться прямо, а только - через функцию strcpy(). (Впрочем, для присваивания структур можно использовать функцию пересылки в памяти - memcpy().)
Вывод таблицы-результата - такой же, как и начальной таблицы.
Полный текст программы приведен ниже.
/********************************************************/
/* Лабораторная работа ╧10 */
/* Структуры и массивы структур */
/* Пример выполнения. ВарЁант ╧30. */
/********************************************************/
#include <stdio.h>
#include <string.h>
/* Описание структуры, которая представляет монастырь */
struct mon {
char name[15]; /* название */
char sc; /* школа */
int cnt; /* количество монахов */
float sq; /* площадь */
} mm[10]; /* определение массива монастирей */
int main(void) {
struct mmm x; /* рабочая переменная */
int n; /* количество элементов в массиве */
int i, j; /* текущие индексы в массиве */
int m; /* индекс минимального элемента */
float sqx;/* рабочая переменная */
/* Ввод данных */
for (n=0; n<10; n++){
printf("%d. Введите: название, школу, количество, площадь >",
n+1);
scanf("%s",mm[n].name);
if (!strcmp(mm[n].name,"***")) break;
scanf("%s",&mm[n].sc);
scanf("%d",&mm[n].cnt);
/* Внимание! Мы обходим ошибку в системе программирования */
scanf("%f",&sqx); mm[n].sq=sqx;
}
/* Вывод таблицы */
printf("---------------------------------------------\n");
printf("|Буддийське монастыри Японии перiода Нара |\n");
printf("|--------------------------------------------|\n");
printf("| Название | Школа |Количество| Площадь |\n");
printf("| | | монахов | земель(га) |\n");
printf("|-----------|-------|----------|-------------|\n");
/* вывод строк фактических данных */
for (i=0; i<n; i++)
printf("| %9s | %c | %3d | %-5.1f |\n",
mm[i].name,mm[i].sc,mm[i].cnt,mm[i].sq);
printf("---------------------------------------------\n");
/* сортировка массива */
for (i=0; i<n-1; i++) {
m=i; /* минимальный элемент - первый */
for (j=i+1; j<n; j++)
/* если текущий элемент > минимального,
он становится минимальным */
if (strcmp(mm[m].name,mm[j].name)>0) m=j;
if (m>i) {
/* перестановка первого и минимального элементов */
strcpy(x.name,mm[i].name); x.sc=mm[i].sc;
x.cnt=mm[i].cnt; x.sq=mm[i].sq;
strcpy(mm[i].name,mm[m].name); mm[i].sc=mm[m].sc;
mm[i].cnt=mm[m].cnt; mm[i].sq=mm[m].sq;
strcpy(mm[m].name,x.name); mm[m].sc=x.sc;
mm[m].cnt=x.cnt; mm[m].sq=x.sq;
}
}
/* Вывод таблицы */
printf("---------------------------------------------\n");
printf("|Буддийське монастыри Японии перiода Нара |\n");
printf("|--------------------------------------------|\n");
printf("| Название | Школа |Количество| Площадь |\n");
printf("| | | монахов | земель(га) |\n");
printf("|-----------|-------|----------|-------------|\n");
for (i=0; i<n; i++)
printf("| %9s | %c | %3d | %-5.1f |\n",
mm[i].name,mm[i].sc,mm[i].cnt,mm[i].sq);
printf("---------------------------------------------\n");
return 0;
}
