Сформировать массив структур из уже созданных - C (СИ)
Формулировка задачи:
Здравствуйте.
Составил программку которая успешно работает: создает бинарный файл со структурой, просматривает и решает поставленную задачу (рассчитать надбавку к стипендии в зависимости от успеваемости).
Всё хорошо работает и все условия проходят, кроме одного: никак не могу заставить ее считать надбавку ТОЛЬКО для студентов определенной группы номер которой надо ввести с клавиатуры.
По идее надо так: пробегаюсь по общему уже созданному массиву структур и сравниваю через strcmp поле student.nomer (номер группы). Если 0, то формирую новый массив структур. Затем надо выполнить задачу, но только для этих структур. А у меня считается для всех групп и нет разницы, что я ввожу только 2-ю или например 5-ю группу для расчета.
Может кто подскажет как исправить? Какие строки надо дописать? Я так понимаю не формируется нужный массив структур для расчета.
Код *.cpp в спойлере. Проблема в case 4.
Бинарный файл в прикрепленном архиве.
/*
Создать программу (выполнив функциональное разбиение) реализующую следующие функции работы с бинарным файлом.
Предусмотреть создание меню со следующими пунктами:
1 – СОЗДАНИЕ НОВОГО ФАЙЛА
2 – ПРОСМОТР ФАЙЛА
3 – КОРРЕКТИРОВКА ЗАПИСЕЙ ФАЙЛА (изменение, добавление новой записи, удаление записи)
4 – ВЫПОЛНЕНИЕ ЗАДАЧИ
5 – ВЫХОД
Создать файл, содержащий сведения о результатах сдачи студентами сессии.
Структура записи:
номер группы, ФИО, оценки по 3 предметам, признак участия в общественной работе: 1 – участие, 0 – неучастие.
ПРОГРАММА ДОЛЖНА НАЧИСЛЯТЬ СТУДЕНТАМ ГРУППЫ Х (ввести с клавиатуры)
СТИПЕНДИЮ. ПРИ ЭТОМ СТУДЕНТ ОТЛИЧНИК И ОБЩЕСТВЕННИК ПОЛУЧАЕТ 50% НАДБАВКУ К БАЗОВОЙ СТИПЕНДИИ,
ПРОСТО ОТЛИЧНИК – 25%, БЕЗ ТРОЕК – 10%. СТУДЕНТ ОБЩЕСТВЕННИК С ОДНОЙ ТРОЙКОЙ ТАКЖЕ ПОЛУЧАЕТ
СТИПЕНДИЮ С НАДБАВКОЙ 10%. НЕУСПЕВАЮЩИЕ СТУДЕНТЫ СТИПЕНДИЮ НЕ ПОЛУЧАЮТ. РЕЗУЛЬТАТ ОТСОРТИРОВАТЬ ПО ФАМИЛИИ.*/
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <locale.h>
#include <io.h>
#include <windows.h>
bool flag (void);
struct stipendia {
char fio[20];
char nomer[1];
int pred1;
int pred2;
int pred3;
int people;
int zp;
};
void main ()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
FILE *money;
FILE *temp;
int select, select1;
int p,n,u,j=0,k,i=0;
int zp=0;
struct stipendia student,temporary;
char surname[20];
char surname_del[20];
char surnomer[1];
setlocale(LC_CTYPE,"Russian");
for (;;) {
puts("\n\t\t\tМЕНЮ");
puts("\t\t1 - Создание нового файла");
puts("\t\t2 – Просмотр файла");
puts("\t\t3 – Корректировка записей файла");
puts("\t\t4 – Выполнение задачи");
puts("\t\t5 – Выход");
printf("Выберите действие: \r\n");
scanf("%d",&select);
fflush(stdin);
switch (select) {
case 1:
if(!(money = fopen("stipendia.bin", "w+b"))) {
printf("\t\tНевозможно открыть файл \n");
return;
}
do {
fflush(stdin);
printf("\nВведите номер группы: "); scanf("%s",&student.nomer); fflush(stdin);
printf("Введите фамилию студента: "); scanf("%s",&student.fio); fflush(stdin);
printf("Оценка по 1-му предмету: "); scanf("%i",&student.pred1); fflush(stdin);
printf("Оценка по 2-му предмету: "); scanf("%i",&student.pred2); fflush(stdin);
printf("Оценка по 3-му предмету: "); scanf("%i",&student.pred3); fflush(stdin);
printf("Участие в общественной работе 1-Да / 0-Нет: "); scanf("%i",&student.people);
if(student.people<0||student.people>1) {
printf("Неверное значение!\n");
student.people=0; }
fflush(stdin);
fwrite (&student,sizeof(student),1,money);
printf("\t\tПродолжить ( д / н )?");
}
while (flag()!=true);
fclose(money);
break;
case 2:
if(!(money = fopen("stipendia.bin", "r+b"))) {printf("\t\tНевозможно открыть файл \n"); return; }
while (fread(&student,sizeof(student),1,money)) {
if (feof(money)) break;
printf("#%s %s\t%i %i %i %i\n",student.nomer, student.fio, student.pred1,student.pred2,student.pred3, student.people);
}
fclose (money);
break;
case 3:
puts("\n\t\t\tВЫБЕРИТЕ КОМАНДУ");
puts("\t\t1 - Изменить запись");
puts("\t\t2 – Добавить запись");
puts("\t\t3 – Удалить запись");
scanf("%d",&select1); fflush(stdin);
switch (select1) {
case 1:
if(!(money = fopen("stipendia.bin", "r+b"))) {printf("\t\tНевозможно открыть файл \n"); return; }
printf("Введите фамилию для изменения: "); fflush(stdin);
gets(surname);
fread(&student,sizeof(student),1,money);
while (!feof(money)) {
if (strcmp(student.fio,surname)==0) {
printf("#%s %s\t%i %i %i %i\n",student.nomer,student.fio,student.pred1,student.pred2,student.pred3,student.people);
printf("\t\tИзменить? ( д / н )");
if (flag()!=true) {
fflush(stdin);
printf("\nВведите номер группы: "); scanf("%s",&student.nomer); fflush(stdin);
printf("Введите фамилию студента: "); scanf("%s",&student.fio); fflush(stdin);
printf("Оценка по 1-му предмету: "); scanf("%i",&student.pred1); fflush(stdin);
printf("Оценка по 2-му предмету: "); scanf("%i",&student.pred2); fflush(stdin);
printf("Оценка по 3-му предмету: "); scanf("%i",&student.pred3); fflush(stdin);
printf("Участие в общественной работе 1-Да / 0-Нет: "); scanf("%i",&student.people);
if(student.people<0||student.people>1) {
printf("Неверное значение!\n");
student.people=0; }
fflush(stdin);
p=sizeof(student);
fseek(money,-p,1);
fwrite(&student,sizeof(student),1,money);
break;
}
}
fread(&student,sizeof(student),1,money);
}
fclose (money);
break;
case 2:
if(!(money = fopen("stipendia.bin", "a+b"))) {printf("\t\tНевозможно открыть файл \n"); return; }
do {
fflush(stdin);
printf("\nВведите номер группы: "); scanf("%s",&student.nomer); fflush(stdin);
printf("Введите фамилию студента: "); scanf("%s",&student.fio); fflush(stdin);
printf("Оценка по 1-му предмету: "); scanf("%i",&student.pred1); fflush(stdin);
printf("Оценка по 2-му предмету: "); scanf("%i",&student.pred2); fflush(stdin);
printf("Оценка по 3-му предмету: "); scanf("%i",&student.pred3); fflush(stdin);
printf("Участие в общественной работе 1-Да / 0-Нет: "); scanf("%i",&student.people);
if(student.people<0||student.people>1) {
printf("Неверное значение!\n");
student.people=0; }
fflush(stdin);
fwrite (&student,sizeof(student),1,money);
printf("\t\tПродолжить ( д / н )?");
}
while (flag()!=true);
fclose (money);
break;
case 3:
if(!(money = fopen("stipendia.bin", "r+b"))) {printf("\t\tНевозможно открыть файл \n"); return; }
if(!(temp = fopen("temp.bin", "w+b"))) {printf("\t\tНевозможно открыть файл \n"); return; }
printf("Введите фамилию для удаления: ");
fflush(stdin);
gets(surname_del);
fread(&student,sizeof(student),1,money);
while (!feof(money)) {
if (strcmp(student.fio,surname_del)!=0) {
fwrite(&student,sizeof(student),1,temp);
fread(&student,sizeof(student),1,money);
}
else fread(&student,sizeof(student),1,money);
}
fclose (money);
remove ("stipendia.bin");
fclose (temp);
rename ("temp.bin","stipendia.bin");
if(!(temp = fopen("stipendia.bin", "r+b"))) {printf("\t\tНевозможно открыть файл \n"); return; }
while (fread(&student,sizeof(student),1,money)) {
if (feof(temp)) break;
printf("#%s %s\t%i %i %i %i\n",student.nomer, student.fio, student.pred1,student.pred2,student.pred3, student.people);
}
break;
}
break;
case 4:
if(!(money = fopen("stipendia.bin", "r+b"))) {printf("Невозможно открыть файл \n"); return; }
//Ввод номера группы для расчета стипендии
printf_s ("\nВведите номер группы для расчета надбавки к стипендии: "); fflush(stdin);
gets(surnomer);
fread(&student,sizeof(student),1,money);
while (!feof(money)) {
if (strcmp(student.nomer,surnomer)==0) {
puts("\nБез сортировки: ");
while(student.nomer)
{
//Расчет стипендии
stipendia *sortirovka;
fseek( money, 0, 2 );
n = ftell(money) / sizeof(student);
rewind(money);
sortirovka=(stipendia*)malloc(n*sizeof(stipendia));
for(i=0; i<n; i++) {
fread(&student,sizeof(student),1,money);
if (((student.pred1 & student.pred2 & student.pred3) >4) & student.people>0) {student.zp=50;} //студент отличник и общественник + 50%
if (((student.pred1 & student.pred2 & student.pred3) >4) & student.people<1) {student.zp=25;} //просто отличник + 25%
if (((student.pred1 & student.pred2 & student.pred3)>3 & (student.pred1 & student.pred2 & student.pred3)<5) & (student.people>0 || student.people<1)) {student.zp=10;} //без троек + 10%
if (( ((student.pred1>2 & student.pred1<4) & student.pred2>3 & student.pred3>3) || (student.pred1>3 & (student.pred2>2 & student.pred2<4) & student.pred3>3) || (student.pred1>3 & student.pred2>3 & (student.pred3>2 & student.pred3<4))) & student.people>0) {student.zp=10;} //студент общественник с одной тройкой + 10%
if (((student.pred1<4 & student.pred2>0 & student.pred3>0) || (student.pred1>0 & student.pred2<4 & student.pred3>0) || (student.pred1>0 & student.pred2>0 & student.pred3<4)) & (student.people>0 || student.people<1)) {student.zp=0;} //неуспевающие студенты стипендию + 0%
sortirovka[i]=student;
printf("#%s %s\t%i %i %i %i\tНадбавка = %i%%\n",student.nomer, student.fio, student.pred1,student.pred2,student.pred3, student.people, student.zp);
}
//Сортировка по фамилии
for(i=0; i<n; i++) {
for(k=i; k<n-1 ; k++) {
if(strcmp(sortirovka[i].fio, sortirovka[k+1].fio) > 0) {
temporary = sortirovka[i];
sortirovka[i] = sortirovka[k+1];
sortirovka[k+1] = temporary;
}
}
}
////Сортировка по 1-й оценке
//for(i=0; i<n; i++) {
// for(k=0; k<n-1 ; k++) {
// //OemToCharA(student.fio,(LPSTR)student.fio);
// if(sortirovka[k].pred1 < sortirovka[k+1].pred1) {
// temporary = sortirovka[k];
// sortirovka[k] = sortirovka[k+1];
// sortirovka[k+1] = temporary;
// }
// }
//}
puts("\nОтсортировано по фамилии: ");
for(i=0; i<n; i++) {
printf("#%s %s\t%i %i %i %i\tНадбавка = %i%%\n",sortirovka[i].nomer,sortirovka[i].fio, sortirovka[i].pred1,sortirovka[i].pred2,sortirovka[i].pred3, sortirovka[i].people, sortirovka[i].zp);
}
free(sortirovka);
break;
}
break;
}
}
fclose (money); break;
case 5: exit(0);
default: puts ( "Неверный выбор, нажмите любую клавишу"); _getch();
}
}
}
bool flag (void)
{
char flag1;
bool flag2=true;
scanf("%c",&flag1);
fflush(stdin);
if (flag1!='Н' && flag1!='н') {
flag2=false;
}
else flag2=true;
return flag2;
}Решение задачи: «Сформировать массив структур из уже созданных»
textual
Листинг программы
// если не-Windows то некоректная работа - виноват fflush(stdin).
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h> // если С++ - закоментировать.
#include <locale.h>
enum{ FIO_SIZE = 25 };
typedef struct Student {
char fio[FIO_SIZE];
int nomer;
int pred1, pred2, pred3;
bool people;
}Student;
typedef struct Stipendia{
char fio[FIO_SIZE];
int n;
}Stipendia;
Student* input_stud(Student *);
bool question(const char []);
int print_menu(void);
void create_file(const char []);
void print_file (const char []);
void corect_file(const char []);
void doing (const char []);
// -------------- MAIN --------------------------
int main(void){
const char filename[] = "stipendia.bin";
setlocale(LC_ALL, "Rus");
for (;;){
switch (print_menu()){
case 1: create_file(filename); break;
case 2: print_file(filename); break;
case 3: corect_file(filename); break;
case 4: doing(filename); break;
case 5: goto exit_from_menu;
}
}
exit_from_menu:
return EXIT_SUCCESS;
}
// ---------------- END MAIN -----------------------
int print_corect_menu(void);
void change_record(Student *, const int);
void add_record (Student **, int *);
void delete_record(Student *, int *);
int compare(const void *, const void *);
int print_menu(void){
printf("\n\t\tМЕНЮ\n");
printf("\t1 - Создание нового файла\n");
printf("\t2 – Просмотр файла\n");
printf("\t3 – Корректировка записей файла\n");
printf("\t4 – Выполнение задачи\n");
printf("\t5 – Выход\n");
printf("Выберите действие: ");
int n;
scanf("%d",&n);
fflush(stdin);
return n;
}
Student* input_stud(Student *stud){
printf("\nВведите фамилию студента: "); fgets(stud->fio, FIO_SIZE, stdin);
stud->fio[strlen(stud->fio)-1] = '\0';
printf("Введите номер группы: "); scanf("%d",&stud->nomer); fflush(stdin);
printf("Оценка по 1-му предмету: "); scanf("%d",&stud->pred1); fflush(stdin);
printf("Оценка по 2-му предмету: "); scanf("%d",&stud->pred2); fflush(stdin);
printf("Оценка по 3-му предмету: "); scanf("%d",&stud->pred3); fflush(stdin);
stud->people = question("Участие в общественной работе(y-Да / n-Нет): ");
return stud;
}
void create_file(const char filename[]){
printf("\n******* Создание нового файла(%s) *******\n", filename);
FILE *f = fopen(filename, "wb");
if (!f){
fprintf(stderr, "Невозможно создать файл: %s", filename);
exit(EXIT_FAILURE);
}
do{
Student stud;
fwrite(input_stud(&stud), sizeof(Student), 1, f);
}while (question("Продолжить( y-Да / n-Нет )?"));
fclose(f);
printf("\n******* Файл создан(%s) *******\n", filename);
}
void print_file(const char filename[]){
printf("\n******* Просмотр файла(%s) *******\n", filename);
FILE *f = fopen(filename, "rb");
if (!f){
fprintf(stderr, "Невозможно открыть файл: %s", filename);
exit(EXIT_FAILURE);
}
printf("\n------------------------------------------------------------------\n");
printf("|N %-25s %s %s %s %s %s\n", "FIO", "NOMER", "PRED1", "PRED2", "PRED3", "PEOPLE|");
printf("------------------------------------------------------------------\n");
Student stud;
for (int i = 1; fread(&stud, sizeof(Student), 1, f); ++i){
printf("|%d %-25s %5d %5d %5d %5d %6s|\n", i, stud.fio, stud.nomer,
stud.pred1, stud.pred2, stud.pred3, (stud.people ? "true" : "false"));
}
printf("------------------------------------------------------------------\n");
fclose(f);
}
void corect_file(const char filename[]){
printf("\n******* Корректировка записей файла(%s) *******\n", filename);
FILE *f = fopen(filename, "rb");
if (!f){
fprintf(stderr, "Невозможно открыть файл: %s", filename);
exit(EXIT_FAILURE);
}
fseek(f, 0, SEEK_END);
int number_studs = ftell(f) / sizeof(Student);
rewind(f);
Student *studs = (Student*)malloc(sizeof(Student) * number_studs);
fread(studs, sizeof(Student), number_studs, f);
fclose(f);
switch (print_corect_menu()){
case 1: change_record(studs, number_studs); break;
case 2: add_record(&studs, &number_studs); break;
case 3: delete_record(studs, &number_studs); break;
}
if (!(f = fopen(filename, "wb"))){
fprintf(stderr, "Невозможно создать файл: %s", filename);
exit(EXIT_FAILURE);
}
fwrite(studs, sizeof(Student), number_studs, f);
fclose(f);
free(studs);
printf("\n******* Файла скорректирован(%s) *******\n", filename);
}
void doing(const char filename[]){
const int BASE = 100; // базовая степендия
printf("\n******* Выполнение задачи(%s) *******\n", filename);
FILE *f = fopen(filename, "rb");
if (!f){
fprintf(stderr, "Невозможно открыть файл: %s", filename);
exit(EXIT_FAILURE);
}
fseek(f, 0, SEEK_END);
const int number_studs = ftell(f) / sizeof(Student);
rewind(f);
Student *studs = (Student*)malloc(sizeof(Student) * number_studs);
fread(studs, sizeof(Student), number_studs, f);
fclose(f);
printf("\nВведите номер группы для расчета надбавки к стипендии: ");
int nomer;
scanf("%d", &nomer); fflush(stdin);
Stipendia st[number_studs];
int count_group = 0;
for (int i = 0; i < number_studs; ++i){
if (studs[i].nomer == nomer){
strcpy(st[count_group].fio, studs[i].fio);
if ((studs[i].pred1 == 5) && (studs[i].pred2 == 5) && (studs[i].pred3 == 5)){
st[count_group].n = BASE + (BASE / 100 * (studs[i].people ? 50 : 25));
}else if ((studs[i].pred1 > 3) && (studs[i].pred2 > 3) && (studs[i].pred3 > 3)){
st[count_group].n = BASE + (BASE / 100 * 10);
}else if (!((studs[i].pred1 < 3) && (studs[i].pred2 < 3) && (studs[i].pred3 < 3)) && studs[i].people){
int count_three = 0;
if (studs[i].pred1 == 3) ++count_three;
if (studs[i].pred2 == 3) ++count_three;
if (studs[i].pred3 == 3) ++count_three;
if (count_three == 1) st[i].n = BASE + (BASE / 100 * 10);
}else{
st[count_group].n = BASE;
}
++count_group;
}
}
if (count_group > 1) qsort(st, count_group, sizeof(Stipendia), compare);
printf("\nРезультат\n");
printf("--------------------------------------\n");
printf("|%-25s %s\n", "FIO", "STIPENDIA|");
printf("--------------------------------------\n");
for (int i = 0; i < count_group; ++i){
printf("|%-25s %9d|\n", st[i].fio, st[i].n);
}
printf("--------------------------------------\n");
}
int print_corect_menu(void){
printf("\n\t\t\tДЕЙСТВИЯ\n");
printf("\t\t1 - Изменить запись\n");
printf("\t\t2 – Добавить запись\n");
printf("\t\t3 – Удалить запись\n");
printf("Выберите действие: ");
int n;
scanf("%d",&n);
fflush(stdin);
return n;
}
void change_record(Student *studs, const int number_studs){
printf("\nВведите FIO для изменения: ");
char fio[FIO_SIZE];
fgets(fio, FIO_SIZE, stdin);
fio[strlen(fio)-1] = '\0';
int i = 0;
for (; i < number_studs; ++i){
if (!strcmp(studs[i].fio, fio)) break;
}
if (i != number_studs){
printf("\nНайдено: %s %d %d %d %d %s\n", studs[i].fio, studs[i].nomer, studs[i].pred1,
studs[i].pred2, studs[i].pred3, (studs[i].people ? "true" : "false"));
printf("Введите данные для замены\n");
input_stud(&studs[i]);
}else{
printf("\nFAIL: FIO такое как '%s' не найдено\n", fio);
}
}
void add_record(Student **studs, int *number_studs){
printf("\nВведите данные для добавления\n");
Student stud;
input_stud(&stud);
Student *new_studs = (Student*)malloc(sizeof(Student) * (*number_studs + 1));
memcpy(new_studs, *studs, sizeof(Student) * *number_studs);
new_studs[(*number_studs)++] = stud;
free(*studs);
*studs = new_studs;
printf("\nДобавлено: %s %d %d %d %d %s\n", stud.fio, stud.nomer, stud.pred1,
stud.pred2, stud.pred3, (stud.people ? "true" : "false"));
}
void delete_record(Student *studs, int *number_studs){
printf("\nВведите FIO для удаления: ");
char fio[FIO_SIZE];
fgets(fio, FIO_SIZE, stdin);
fio[strlen(fio)-1] = '\0';
int i = 0;
for (; i < *number_studs; ++i){
if (!(strcmp(studs[i].fio, fio))) break;
}
if (i != *number_studs){
printf("\nУдалено: %s %d %d %d %d %s\n", studs[i].fio, studs[i].nomer, studs[i].pred1,
studs[i].pred2, studs[i].pred3, (studs[i].people ? "true" : "false"));
for (int j = i; j < *number_studs-1; ++j) studs[j] = studs[j+1];
--*number_studs;
}else{
printf("\nFAIL: FIO такое как '%s' не найдено\n", fio);
}
}
bool question(const char str[]){
char ch;
for (;;){
printf("%s", str);
ch = tolower(getchar());
fflush(stdin);
if (strchr("yn", ch)) break;
printf("Неверное значение, повторите.\t");
}
return ch == 'y';
}
int compare(const void *arg1, const void *arg2){
return strcmp(((Stipendia*)arg1)->fio, ((Stipendia*)arg2)->fio);
}