1 Структура Одним из наиболее важных шагов при проектировании программы является выбор подходящего способа представления данных. Во многих случаях простой переменной или массива оказывается недостаточно. Язык С позволяет расширить возможности представления данных с помощью переменных типа структура. В качестве примера использования таких данных можно привести: каталог книг в библиотеке, расписание самолетов, перечень товаров в магазине и многое другое. Структура – это совокупность нескольких переменных (элементов или полей), объединенных одним именем, возможно разного типа. С помощью структур удобно организовывать данные связанные между собой и обрабатываемые как одно целое. При объявлении структуры используется зарезервированное слово struct: struct [имя_структурного_типа] { <тип_1> < имя элемента_1>; <тип_2> < имя элемента_2>; ……………………. <тип_n> < имя элемента_n>; }; имя_структурного_типа – это необязательный идентификатор для конкретного структурного типа. Но если он есть, в дальнейшем его удобно использовать для определения переменной структуры. В фигурных скобках указан список переменных, которые называются элементами или полями структуры. Каждая переменная в этом списке описана своим типом и заканчивается точкой с запятой. Объявление структуры заканчивается точкой с запятой. Пример объявления структуры. 1 2 struct Student { int number; char name[20]; char group[5]; }; Объявление структуры не создает реальный объект, но определяет, из чего состоит этот объект, то есть определяется новый тип, а не переменную. Объявление переменной Struct < имя структуры> < имя переменной> или < имя структуры> < имя переменной> ………………….. main() { int i; Student s; ………………… } Таким образом, s является переменной (экземпляром, объектом) типа Student. Другой способ объявления переменной: struct Student { int number; char name[20]; char group[5]; } s; Когда объявляется переменная типа структура, компилятор автоматически выделяет количество памяти, достаточное, чтобы разместить 2 3 все ее элементы. Под структурный объект s будет выделено 27 (29) байт памяти. Инициализация: struct Student { int number; char name[20]; char group[5]; } s = { 1, “Русин”, “И183” }; В примере объявлена переменная s, которая проинициализирована списком значений-констант, разделенных запятыми: Поле number - номер студента; Поле name[20] символьный массив для фамилии студента; Поле group[5] символьный массив для группы студента; Ввод с клавиатуры Ввод переменной типа структуры с клавиатуры осуществляется по отдельным ее полям. Обращение к отдельным полям (элементам) структуры выполняется с помощью следующей конструкции: < имя переменной структуры > . < имя элемента структуры > Разделителем в этой конструкции является знак <точка>. Пример ввода с клавиатуры по полям для выше описанной структуры: scanf (“%d%s%s”, s.number, s.name, s.group); Можно использовать оператор присваивания для задания значений полям: s. number = 9; s. name = “Логачев”; s.group = “И193”; Поля можно использовать в выражениях, как переменную. 3 4 Стандарт языка С ANSI разрешает следующие операции над структурами целиком: − присваивание; − взятие адреса; − передача в функцию; − возврат из функции. Например, объявлены две переменные: Student s_191, s_192; Можно присвоить s_191 = s_192; Вывод переменной на экран можно выполнить по полям: Printf (“%5d %s %s\n”, s.number, s.name, s.group); Структуры могут быть вложенными друг в друга, то есть одно из полей может иметь тип структуры. Из структур можно создавать массивы: Student str[10]; Под объявленный из 10 элементов массив структур типа Student, будет выделено 270 (290) байт памяти. Обращение к полям: str[i].number, str[i].name, str[i].group. Ввод с клавиатуры: for(i=0;i<10;i++) scanf(“%d%s%s”, &str[i].number, str[i].name, str[i].group); УКАЗАТЕЛЬ НА СТРУКТУРУ Объявляется с помощью следующей конструкции: имя_структурного_типа *имя_указателя; Student *st; Доступ к отдельным полям структуры осуществляется с помощью оператора стрелки (->): st -> number = 2; scanf(“%s%s”, st->name, st->group); 4 5 Пример. Создать базу данных для группы студентов, со следующими полями: Фамилия студента, группа, год рождения и оценки по трем предметам: математика, физика и информатика. Вывести на экран список студентов, год рождения у которых меньше введенного. Вывести на экран средний балл группы, номер которой вводится. В программе предусмотреть интерфейс с пользователем, через меню. База должна храниться в бинарном файле, имя которого вводится пользователем. Структура программы 1 уровень: Функция main(). Из нее вызываются 4 функции. 2 уровень: − Функция создания файла или добавления записей; − Функция вывода данных из файла на экран; − Функция вывода списка студентов, год рождения которых не превышает заданный; − Функция вычисления среднего арифметического заданной группы. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> struct stud { char name [30]; char group [6]; int year; int m,f,inf; }; void sozd_add(char *); void show(char *); void poisk(char *); void average(char *); main() { char file_name[25]; int ans; setlocale (LC_ALL, "Rus"); 5 6 puts("\n Vvedi name fila: \n"); gets(file_name); while (1) { system ("cLs"); puts(" \n M E N U"); puts(" \n 1.Sozd or Add"); puts(" \n 2.Show is fila"); puts(" \n 3.Poisk po usloviu"); puts(" \n 4.Sred arif"); puts(" \n 5.Exit"); puts(" \n Vvedite punkt menu ans= \n"); scanf("%d",&ans); switch (ans) { case 1 : sozd_add (file_name);break; case 2 : show (file_name);break; case 3: poisk (file_name);break; case 4 : average (file_name);break; case 5 : system ("cLs"); printf("\n\n rabota programmy end\n\n\n"); system ("pause"); return 0; default : { system ("cLs"); printf("\n\n net takogo punkta v menu\n\n\n"); system ("pause"); return (2); } } } } struct stud in_stud(void) { struct stud st; printf(" Vvedi name\n "); scanf("%30s",st.name); printf("\n Vvedi gruppu\n "); scanf("%10s",st.group); printf("\n Vvedi god: \n "); scanf("%d",&st.year); printf("\n Vvedi mark: \n "); scanf("%d%d%d",&st.m,&st.f,&st.inf); return st; } 6 7 void sozd_add (char *file) { FILE *f; stud st; int i=1,n; system ("cLs"); if((f=fopen(file,"ab"))==NULL) { perror("\n Ошибка открытия файла"); puts("\n Нажмите любую клавишу, чтобы вернуться в меню...\n"); system("pause"); return; } printf("\n vv kol zap \n"); scanf("%d",&n); for(i;i<=n;i++) { st=in_stud(); fwrite(&st, sizeof(stud),1,f); } printf(" \n vvod zaconcen \n\n"); system ("pause"); fclose(f); } void out_stud(struct stud st) { printf("\n%22s %11s %9d %5d%3d%3d\n", st.name,st.group,st.year,st.m,st.f,st.inf); } void show(char *file) { FILE *f; stud st; system ("cLs"); if((f=fopen(file,"rb"))==NULL) { perror("\n Ошибка открытия файла"); puts("\n Нажмите любую клавишу, чтобы вернуться в меню...\n"); system("pause"); return; } printf(" name group year mark\n"); while (fread(&st, sizeof(stud),1,f)) out_stud( st); system ("pause"); fclose(f); 7 8 } void poisk(char * file) { FILE *f; stud st; int god; bool f1=true; system ("cLs"); f=fopen(file, "rb"); puts("\n vvedi god dly poiska stud\n"); scanf("%d",&god); while (fread(&st,sizeof(stud),1,f)) if (st.year<god) { f1=false; out_stud(st); } if (f1) { printf("\n takix stud net\n"); } system ("pause"); fclose(f); } void average(char * file) { FILE *f; stud st; int k=0,flag=0; float sr=0; char n_group[6]; system ("cLs"); f=fopen(file, "rb"); puts(" Vvedi nomer groop"); scanf("%9s",n_group); while (fread(&st,sizeof(stud),1,f)) if (strcmp(st.group,n_group)==0) { sr+=st.m+st.f+st.inf; k++; flag=1; } if (flag) { printf(" sr= %f\n",sr/(3*k)); 8 9 system ("pause"); fclose(f); } else { printf("\n net takoi group\n"); system ("pause"); } } После запуска программы на выполнение, появляется запрос: По нажатию клавиши “Enter”, появляется меню и просьба ввести пункт из этого меню. Ввод каждого пункта заканчивается нажатием клавиши Enter. Например, при выборе пункта 1, появится окно для ввода количества записей и самих записей: 9 10 После выполнения этого пункта меню опять появится для выбора следующих действий: После выбора пункта 2, появится результат: После выбора пункта 3, появится запрос на ввод и результат: 10 11 После выбора пункта 4, появится запрос на ввод и результат: После выбора пункта 5, появится результат: 11