Найти в Дзене
BAZA_KUDR

Структуры в Си. (9лаба)

Сегодня мы с вами поговорим об некой BAZE языка С структуры. Структура – это тип данных, который может включать в себя несколько полей – элементов разных типов (в том числе и другие структуры).
Зачем нужны структуры? Представим себе базу данных библиотеки, в которой хранится информация о книгах. Для каждой из них нужно запомнить автора, название, год издания, количество страниц, число экземпляров и т.д. Как хранить эти данные? Поскольку книг много, нужен массив. Но в массиве используются элементы одного типа, тогда как информация о книгах разнородна, она содержит целые числа и символьные строки разной длины. Конечно, можно разбить эти данные на несколько массивов (массив авторов, массив названий и т.д.), так чтобы i-ый элемент каждого массива относился к книге с номером i. Но такой подход оказывается слишком неудобен и ненадежен. Например, при сортировке нужно переставлять элементы всех массивов (отдельно!) и можно легко ошибиться и нарушить связь данных. Возникает естественная идея –

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

Зачем нужны структуры? Представим себе базу данных библиотеки, в которой хранится информация о книгах. Для каждой из них нужно запомнить автора, название, год издания, количество страниц, число экземпляров и т.д. Как хранить эти данные? Поскольку книг много, нужен массив. Но в массиве используются элементы одного типа, тогда как информация о книгах разнородна, она содержит целые числа и символьные строки разной длины. Конечно, можно разбить эти данные на несколько массивов (массив авторов, массив названий и т.д.), так чтобы i-ый элемент каждого массива относился к книге с номером i. Но такой подход оказывается слишком неудобен и ненадежен. Например, при сортировке нужно переставлять элементы всех массивов (отдельно!) и можно легко ошибиться и нарушить связь данных. Возникает естественная идея – объединить все данные, относящиеся к книге, в единый блок памяти, который в программировании называется структурой.

Перейдём сразу к практике.

Задача звучит так:

В файле marks.csv записаны сведения о результатах экзаменов в студентов.

Всего в списке 1000 записей, каждая из которых содержит:

фамилию студента;

имя студента;

отметки по четырем предметам (физике, математике, информатике и истории).

Все элементы в каждой строке разделены запятыми.

Напишите программу, которая читает данные из файла в массив структур, выводит на экран и в файл:

а) средний балл по каждому предмету;

б) максимальную сумму баллов, полученных студентом;

в) список учащихся (фамилии и имена), набравших максимальную сумму баллов;

г) количество студентов, получивших хотя бы одну отметку "3"

д) фамилии и имена студентов, получивших отметку "4" по информатике.

Чтение из файла, поиск в массиве структур и вывод результата реализовать в виде отдельных функций.

Начнём с малого, с объявления структур:

typedef struct{
char Surname[100];

char Name[100];

int score[4];

} St;

Данная структура понадобится нам для чтения данных из файла в неё мы будем записывать фамилию, имя и оценки по 4 предметам.


Как видите в функцию read мы передали ссылку на нашу структуру и начали работу с файлом. Прошу заметить функцию fscanf в которой мы используем приём("%[^,],%[^,],%s,%s,%s "), который поможет нам считывать отдельно данные разделённые запятой и сразу записывать их в 3 массива данных. Вместо того чтобы записать всё в 1 и далее выбирать из него данные.

void read(St *s){
FILE *f;

f = fopen("marks.csv", "r");

char score[10];

for (int i=0; i<1000; i ){

fscanf(f,"%[^,],%[^,],%s,%s,%s ",s[i].Surname,s[i].Name,score);

s[i].score[0] = score[0] - '0';

s[i].score[1]= score[2]-'0';

s[i].score[2]= score[4]-'0';

s[i].score[3]= score[6]-'0';

}

}

Также зная что в массиве score будет всегда фиксированное количество чисел, запятых и их расположение мы преобразуем каждый второй элемент (пропуская запятую) в тип int отнимая символ '0' и записываем их в структуру.

Для дальнейшей работы мы создадим ещё 1 структуру.

typedef struct {
char surname[100];

char name[100];

int scores[4];

int phys;

int math;

int inf;

int his;

float midphys;

float midmath;

float midinf;

float midhis;

char wellinf[100];

int max;

char MAX[100];

int count;

} Sc;

В нее мы с запишем прочитанные файлы с помощью функции processing и далее будем записывать обработанные данные.

void processing(St *n, Sc *m)

{for (int i=0; i<1000; i ){

strcpy(m[i].surname,n[i].Surname);

strcpy(m[i].name,n[i].Name);

m[i].phys=n[i].score[0];

m[i].math =n[i].score[1];

m[i].inf=n[i].score[2];

m[i].his=n[i].score[3];

}

}

В функцию processing мы передали ссылки на 2 структуру.

И наконец приступим к выполнению пунктов заданий в функции calcul

int calcul(Sc *B){
int midf=0;

float midlef=0;

int midi=0;

float midlei=0;

int midh=0;

float midleh;

int midm=0;

float midlem;

int max[1000];

int M=0;

int count=0;

for (int i=0; i<1000; i ){

midf=midf B[i].phys;

midm=midm B[i].math;

midi=midi B[i].inf;

midh=midh B[i].his;


max[i]=B[i].phys B[i].math B[i].inf B[i].his;

if (B[i].phys==3||B[i].math==3|B[i].inf==3||B[i].his==3) count;

}

midlef=(float)midf/1000;

midlem=(float)midm/1000;

midlei=(float)midi/1000;

midleh=(float)midh/1000;

B->midphys=midlef;

B->midmath=midlem;

B->midinf=midlei;

B->midhis=midleh;

B->count=count;

printf ("Средний бал по физике:%.2f\n",midlef);

printf ("Средний балл по математике:%.2f\n",midlem);

printf ("Средний балл по информатике:%.2f\n",midlei);

printf ("Средний балл по истории:%.2f\n",midleh);

printf ("Максимальная сумма баллов полученная студентом:");

for (int i=0; i<1000; i ) {if(max[i]>max[M]) M=i;}

B->max=max[M];

printf ("%d\n", B->max);

printf ("Фамилии и имена студентов набравших максимальное количество баллов:\n");

for (int i=0; i<1000; i ) if(max[i]==max[M])

{strcpy(B[i].MAX,B[i].surname); strcat(B[i].MAX," ");strcat(B[i].MAX,B[i].name);

printf("%s\n",B[i].MAX);}

printf("количество студентов, получивших хотя бы одну отметку 3: %d\n\n", count);

printf(" фамилии и имена студентов, получивших отметку 4 по информатике:\n\n");

for (int i=0; i<1000; i ) if(B[i].inf==4) {strcpy(B[i].wellinf,B[i].surname); strcat(B[i].wellinf," ");

strcat(B[i].wellinf,B[i].name); printf("%s\n", B[i].wellinf);}

return 0;

}

Выполняя обработку мы также записываем эти данные в структуру для дальнейшего вывода в файл.


Осталось только вывести данные в файл.

int out(Sc *G){
FILE *fout;

fout = fopen("res.txt", "a");

fprintf(fout,"Средний балл по физике:%.2f\n",G->;midphys);

fprintf(fout,"Средний балл по математике:%.2f\n",G->;midmath);

fprintf(fout,"Средний балл по информатике:%.2f\n",G->;midinf);

fprintf(fout,"Средний балл по истории:%.2f\n",G->;midhis);

fprintf (fout,"Максимальная сумма баллов полученная студентом:%d\n", G->max);

fprintf (fout,"Фамилии и имена студентов набравших максимальное количество баллов:\n");

for (int j=0; j<1000; j ) fprintf(fout,"%s",G[j].MAX);

fprintf(fout,"%s\n",G[1000].MAX);

fprintf (fout,"количество студентов, получивших хотя бы одну отметку 3: %d\n", G->count);

fprintf (fout,"фамилии и имена студентов, получивших отметку 4 по информатике:\n");

for (int i=0; i<1000; i ) fprintf(fout,"%s",G[i].wellinf);

fclose (fout);

}

Благодаря структурам мы смогли работать с большим количеством данных и не запутались в их хитросплетениях.

Вот полный код к этой работе:


#include
#include
#include
#include
#include
typedef struct{char Surname[100];
char Name[100];
int score[4];} St;
typedef struct {char surname[100];
char name[100];
int scores[4];
int phys;
int math;
int inf;
int his;
float midphys;
float midmath;
float midinf;
float midhis;
char wellinf[100];
int max;
char MAX[100];
int count;} Sc;
void read(St *s){FILE *f;
f = fopen("marks.csv", "r");
char score[10];
for (int i=0; i<1000; i ){
fscanf(f,"%[^,],%[^,],%s,%s,%s ",s[i].Surname,s[i].Name,score);
s[i].score[0] = score[0] - '0';
s[i].score[1]= score[2]-'0';
s[i].score[2]= score[4]-'0';
s[i].score[3]= score[6]-'0';}
}
void processing(St *n, Sc *m)
{for (int i=0; i<1000; i ){
strcpy(m[i].surname,n[i].Surname);
strcpy(m[i].name,n[i].Name);
m[i].phys=n[i].score[0];
m[i].math =n[i].score[1];
m[i].inf=n[i].score[2];
m[i].his=n[i].score[3];

}
}
int calcul(Sc *B){int midf=0;
float midlef=0;
int midi=0;
float midlei=0;
int midh=0;
float midleh;
int midm=0;
float midlem;
int max[1000];
int M=0;
int count=0;
for (int i=0; i<1000; i ){
midf=midf B[i].phys;
midm=midm B[i].math;
midi=midi B[i].inf;
midh=midh B[i].his;

max[i]=B[i].phys B[i].math B[i].inf B[i].his;
if (B[i].phys==3||B[i].math==3|B[i].inf==3||B[i].his==3) count;}
midlef=(float)midf/1000;
midlem=(float)midm/1000;
midlei=(float)midi/1000;
midleh=(float)midh/1000;
B->midphys=midlef;
B->midmath=midlem;
B->midinf=midlei;
B->midhis=midleh;
B->count=count;
printf ("Средний бал по физике:%.2f\n",midlef);
printf ("Средний балл по математике:%.2f\n",midlem);
printf ("Средний балл по информатике:%.2f\n",midlei);
printf ("Средний балл по истории:%.2f\n",midleh);
printf ("Максимальная сумма баллов полученная студентом:");
for (int i=0; i<1000; i ) {if(max[i]>max[M]) M=i;}
B->max=max[M];
printf ("%d\n", B->max);
printf ("Фамилии и имена студентов набравших максимальное количество баллов:\n");
for (int i=0; i<1000; i ) if(max[i]==max[M])
{strcpy(B[i].MAX,B[i].surname); strcat(B[i].MAX," ");strcat(B[i].MAX,B[i].name);
printf("%s\n",B[i].MAX);}
printf("количество студентов, получивших хотя бы одну отметку 3: %d\n\n", count);
printf(" фамилии и имена студентов, получивших отметку 4 по информатике:\n\n");
for (int i=0; i<1000; i ) if(B[i].inf==4) {strcpy(B[i].wellinf,B[i].surname); strcat(B[i].wellinf," ");
strcat(B[i].wellinf,B[i].name); printf("%s\n", B[i].wellinf);}
return 0;}
int out(Sc *G){FILE *fout;
fout = fopen("res.txt", "a");
fprintf(fout,"Средний балл по физике:%.2f\n",G->;midphys);
fprintf(fout,"Средний балл по математике:%.2f\n",G->;midmath);
fprintf(fout,"Средний балл по информатике:%.2f\n",G->;midinf);
fprintf(fout,"Средний балл по истории:%.2f\n",G->;midhis);
fprintf (fout,"Максимальная сумма баллов полученная студентом:%d\n", G->max);
fprintf (fout,"Фамилии и имена студентов набравших максимально количество баллов:\n");
for (int j=0; j<1000; j ) fprintf(fout,"%s",G[j].MAX);
fprintf(fout,"%s\n",G[1000].MAX);
fprintf (fout,"количество студентов, получивших хотя бы одну отметку 3: %d\n", G->count);
fprintf (fout,"фамилии и имена студентов, получивших отметку 4 по информатике:\n");
for (int i=0; i<1000; i ) fprintf(fout,"%s",G[i].wellinf);
fclose (fout);}
int main()
{system("chcp 65001");
system("cls");
St *p;
St student[1000];
p = &student;
Sc *t;
Sc List[1000];
t=&List;
read(p);
processing(p,t);
calcul(t);
out (t);
return 0;}ты одного типа, тогда как информация о книгах разнородна, она содержит целые числа и символьные строки разной длины. Конечно, можно разбить эти данные на несколько массивов (массив авторов, массив названий и т.д.), так чтобы i-ый элемент каждого массива относился к книге с номером i. Но такой подход оказывается слишком неудобен и ненадежен. Например, при сортировке нужно переставлять элементы всех массивов (отдельно!) и можно легко ошибиться и нарушить связь данных. Возникает естественная идея – объединить все данные, относящиеся к книге, в единый блок памяти, который в программировании называется структурой.

Перейдём сразу к практике.

Задача звучит так:

В файле marks.csv записаны сведения о результатах экзаменов в студентов.

Всего в списке 1000 записей, каждая из которых содержит:

фамилию студента;

имя студента;

отметки по четырем предметам (физике, математике, информатике и истории).

Все элементы в каждой строке разделены запятыми.

Напишите программу, которая читает данные из файла в массив структур, выводит на экран и в файл:

а) средний балл по каждому предмету;

б) максимальную сумму баллов, полученных студентом;

в) список учащихся (фамилии и имена), набравших максимальную сумму баллов;

г) количество студентов, получивших хотя бы одну отметку "3"

д) фамилии и имена студентов, получивших отметку "4" по информатике.

Чтение из файла, поиск в массиве структур и вывод результата реализовать в виде отдельных функций.

Начнём с малого с объявления структур:

typedef struct{

char Surname[100];

char Name[100];

int score[4];

} St;

Данная структура понадобится нам для чтения данных из файла в неё мы будем записывать фамилию, имя и оценки по 4 предметам.

Как видите в функцию read мы передали ссылку на нашу структуру и начали работу с файлом. Прошу заметить функцию fscanf в которой мы используем приём("%[^,],%[^,],%s,%s,%s "), который поможет нам считывать отдельно данные разделённые запятой и сразу записывать их в 3 массива данных. Вместо того чтобы записать всё в 1 и далее выбирать из него данные.

void read(St *s){

FILE *f;

f = fopen("marks.csv", "r");

char score[10];

for (int i=0; i<1000; i++){

fscanf(f,"%[^,],%[^,],%s,%s,%s ",s[i].Surname,s[i].Name,score);

s[i].score[0] = score[0] - '0';

s[i].score[1]= score[2]-'0';

s[i].score[2]= score[4]-'0';

s[i].score[3]= score[6]-'0';

}

}

Также зная что в массиве score будет всегда фиксированное количество чисел, запятых и их расположение мы преобразуем каждый второй элемент (пропуская запятую) в тип int отнимая символ '0' и записываем их в структуру.

Для дальнейшей работы мы создадим ещё 1 структуру.

typedef struct {

char surname[100];

char name[100];

int scores[4];

int phys;

int math;

int inf;

int his;

float midphys;

float midmath;

float midinf;

float midhis;

char wellinf[100];

int max;

char MAX[100];

int count;

} Sc;

В нее мы с запишем прочитанные файлы с помощью функции processing и далее будем записывать обработанные данные.

void processing(St *n, Sc *m)

{for (int i=0; i<1000; i++){

strcpy(m[i].surname,n[i].Surname);

strcpy(m[i].name,n[i].Name);

m[i].phys=n[i].score[0];

m[i].math =n[i].score[1];

m[i].inf=n[i].score[2];

m[i].his=n[i].score[3];

}

}

В функцию processing мы передали ссылки на 2 структуру.

И наконец приступим к выполнению пунктов заданий в функции calcul

int calcul(Sc *B){

int midf=0;

float midlef=0;

int midi=0;

float midlei=0;

int midh=0;

float midleh;

int midm=0;

float midlem;

int max[1000];

int M=0;

int count=0;

for (int i=0; i<1000; i++){

midf=midf+B[i].phys;

midm=midm+B[i].math;

midi=midi+B[i].inf;

midh=midh+B[i].his;

max[i]=B[i].phys+B[i].math+B[i].inf+B[i].his;

if (B[i].phys==3||B[i].math==3|B[i].inf==3||B[i].his==3) count++;

}

midlef=(float)midf/1000;

midlem=(float)midm/1000;

midlei=(float)midi/1000;

midleh=(float)midh/1000;

B->midphys=midlef;

B->midmath=midlem;

B->midinf=midlei;

B->midhis=midleh;

B->count=count;

printf ("Средний бал по физике:%.2f\n",midlef);

printf ("Средний бал по математике:%.2f\n",midlem);

printf ("Средний бал по информатике:%.2f\n",midlei);

printf ("Средний бал по истории:%.2f\n",midleh);

printf ("Максимальная сумма баллов полученная студентом:");

for (int i=0; i<1000; i++) {if(max[i]>max[M]) M=i;}

B->max=max[M];

printf ("%d\n", B->max);

printf ("Фамилии и имена студентов набравших максимально количество баллов:\n");

for (int i=0; i<1000; i++) if(max[i]==max[M])

{strcpy(B[i].MAX,B[i].surname); strcat(B[i].MAX," ");strcat(B[i].MAX,B[i].name);

printf("%s\n",B[i].MAX);}

printf("количество студентов, получивших хотя бы одну отметку 3: %d\n\n", count);

printf(" фамилии и имена студентов, получивших отметку 4 по информатике:\n\n");

for (int i=0; i<1000; i++) if(B[i].inf==4) {strcpy(B[i].wellinf,B[i].surname); strcat(B[i].wellinf," ");

strcat(B[i].wellinf,B[i].name); printf("%s\n", B[i].wellinf);}

return 0;

}

Выполняя обработку мы также записываем эти данные в структуру для дальнейшего вывода в файл.

Осталось только вывести данные в файл.

int out(Sc *G){

FILE *fout;

fout = fopen("res.txt", "a");

fprintf(fout,"Средний балл по физике:%.2f\n",G->midphys );

fprintf(fout,"Средний балл по математике:%.2f\n",G->midmath );

fprintf(fout,"Средний балл по информатике:%.2f\n",G->midinf );

fprintf(fout,"Средний балл по истории:%.2f\n",G->midhis );

fprintf (fout,"Максимальная сумма баллов полученная студентом:%d\n", G->max);

fprintf (fout,"Фамилии и имена студентов набравших максимально количество баллов:\n");

for (int j=0; j<1000; j++) fprintf(fout,"%s",G[j].MAX);

fprintf(fout,"%s\n",G[1000].MAX);

fprintf (fout,"количество студентов, получивших хотя бы одну отметку 3: %d\n", G->count);

fprintf (fout,"фамилии и имена студентов, получивших отметку 4 по информатике:\n");

for (int i=0; i<1000; i++) fprintf(fout,"%s",G[i].wellinf);

fclose (fout);

}

Благодаря структурам мы смогли работать с большим количеством данных и не запутались в их хитросплетениях.

Вот полный код к этой работе:


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <locale.h>
typedef struct{
char Surname[100];
char Name[100];
int score[4];
} St;
typedef struct {
char surname[100];
char name[100];
int scores[4];
int phys;
int math;
int inf;
int his;
float midphys;
float midmath;
float midinf;
float midhis;
char wellinf[100];
int max;
char MAX[100];
int count;
} Sc;
void read(St *s){
FILE *f;
f = fopen("marks.csv", "r");
char score[10];
for (int i=0; i<1000; i++){
fscanf(f,"%[^,],%[^,],%s,%s,%s ",s[i].Surname,s[i].Name,score);
s[i].score[0] = score[0] - '0';
s[i].score[1]= score[2]-'0';
s[i].score[2]= score[4]-'0';
s[i].score[3]= score[6]-'0';
}
}
void processing(St *n, Sc *m)
{for (int i=0; i<1000; i++){
strcpy(m[i].surname,n[i].Surname);
strcpy(m[i].name,n[i].Name);
m[i].phys=n[i].score[0];
m[i].math =n[i].score[1];
m[i].inf=n[i].score[2];
m[i].his=n[i].score[3];

}
}
int calcul(Sc *B){
int midf=0;
float midlef=0;
int midi=0;
float midlei=0;
int midh=0;
float midleh;
int midm=0;
float midlem;
int max[1000];
int M=0;
int count=0;
for (int i=0; i<1000; i++){
midf=midf+B[i].phys;
midm=midm+B[i].math;
midi=midi+B[i].inf;
midh=midh+B[i].his;

max[i]=B[i].phys+B[i].math+B[i].inf+B[i].his;
if (B[i].phys==3||B[i].math==3|B[i].inf==3||B[i].his==3) count++;
}
midlef=(float)midf/1000;
midlem=(float)midm/1000;
midlei=(float)midi/1000;
midleh=(float)midh/1000;
B->midphys=midlef;
B->midmath=midlem;
B->midinf=midlei;
B->midhis=midleh;
B->count=count;
printf ("Средний бал по физике:%.2f\n",midlef);
printf ("Средний бал по математике:%.2f\n",midlem);
printf ("Средний бал по информатике:%.2f\n",midlei);
printf ("Средний бал по истории:%.2f\n",midleh);
printf ("Максимальная сумма баллов полученная студентом:");
for (int i=0; i<1000; i++) {if(max[i]>max[M]) M=i;}
B->max=max[M];
printf ("%d\n", B->max);
printf ("Фамилии и имена студентов набравших максимально количество баллов:\n");
for (int i=0; i<1000; i++) if(max[i]==max[M])
{strcpy(B[i].MAX,B[i].surname); strcat(B[i].MAX," ");strcat(B[i].MAX,B[i].name);
printf("%s\n",B[i].MAX);}
printf("количество студентов, получивших хотя бы одну отметку 3: %d\n\n", count);
printf(" фамилии и имена студентов, получивших отметку 4 по информатике:\n\n");
for (int i=0; i<1000; i++) if(B[i].inf==4) {strcpy(B[i].wellinf,B[i].surname); strcat(B[i].wellinf," ");
strcat(B[i].wellinf,B[i].name); printf("%s\n", B[i].wellinf);}
return 0;
}
int out(Sc *G){
FILE *fout;
fout = fopen("res.txt", "a");
fprintf(fout,"Средний балл по физике:%.2f\n",G->midphys );
fprintf(fout,"Средний балл по математике:%.2f\n",G->midmath );
fprintf(fout,"Средний балл по информатике:%.2f\n",G->midinf );
fprintf(fout,"Средний балл по истории:%.2f\n",G->midhis );
fprintf (fout,"Максимальная сумма баллов полученная студентом:%d\n", G->max);
fprintf (fout,"Фамилии и имена студентов набравших максимально количество баллов:\n");
for (int j=0; j<1000; j++) fprintf(fout,"%s",G[j].MAX);
fprintf(fout,"%s\n",G[1000].MAX);
fprintf (fout,"количество студентов, получивших хотя бы одну отметку 3: %d\n", G->count);
fprintf (fout,"фамилии и имена студентов, получивших отметку 4 по информатике:\n");
for (int i=0; i<1000; i++) fprintf(fout,"%s",G[i].wellinf);
fclose (fout);
}
int main()
{
system("chcp 65001");
system("cls");
St *p;
St student[1000];
p = &student;
Sc *t;
Sc List[1000];
t=&List;
read(p);
processing(p,t);
calcul(t);
out (t);
return 0;
}