Некорректная работа меню - C (СИ)
Формулировка задачи:
Почему "Choose smth" два раза выводится? И не понимаю, почему ввод выбора осуществляется именно так, через atoi (содрано с Шилдта). Почему нельзя сразу, напр., через scanf в int положить?
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
struct instr
{
int num;
char name[10];
int amount;
double price;
} data[MAX];
FILE *fp;
int menu_select();
void enter();
void rewrite();
void print_d();
int main()
{
if((fp=fopen("ins.dat","ab"))==NULL)
{
printf("Error opening\n");
exit(1);
}
fclose(fp);
char choice;
//1 ввод данных в файл
//2 обновление информации
//3 печать всех данных
for(;;)
{
choice=menu_select();
switch(choice)
{
case 1: enter();
break;
case 2: rewrite();
break;
case 3: print_d();
break;
case 4: exit(0);
}
}
return 0;
}
int menu_select()
{
int i;
char s[3];
printf("1 - enter some data\n");
printf("2 - rewrite data\n");
printf("3 - print all data\n");
printf("4 - exit\n");
do
{
printf("Choose smth:\n");
gets(s);
i=atoi(s);
} while (i<1||i>4);
return i;
}
void enter()
{
if((fp=fopen("ins.dat","r+"))==NULL)
{
printf("Error opening\n");
exit(1);
}
int x=0;
// rewind(fp);
do
{
fread(&data[x],sizeof(struct instr),1,fp);
printf("data[%d].num=%d\n",x,data[x].num);
x++;
} while((data[x-1].num!=0) && x<MAX);
x--;
if(x==MAX)
{
puts("Theres no free space\n");
exit(1);
}
else
printf("%d is free\n",x);
data[x].num=x+1;
printf("Enter the name\n");
scanf("%s",data[x].name);
printf("Enter the amount\n");
scanf("%d",&data[x].amount);
printf("Enter the price\n");
scanf("%lf",&data[x].price);
fseek(fp,x*sizeof(struct instr),SEEK_SET);
fwrite(&data[x],sizeof(struct instr),1,fp);
fclose(fp);
}
void rewrite()
{
if((fp=fopen("ins.dat","ab+"))==NULL)
{
printf("Error opening\n");
exit(1);
}
fclose(fp);
}
void print_d()
{
if((fp=fopen("ins.dat","r"))==NULL)
{
printf("Error opening\n");
exit(1);
}
int x=0;
rewind(fp);
do
{
fflush(stdin);
fscanf(fp,"%d%s%d%lf\n",&data[x].num,data[x].name,&data[x].amount,&data[x].price);
printf("%-3d%-10s%-5d%-10.2f\n",data[x].num,data[x].name,data[x].amount,data[x].price);
x++;
} while(data[x].num!=0);
fclose(fp);
}Решение задачи: «Некорректная работа меню»
textual
Листинг программы
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
struct instr
{
int num;
char name[10];
int amount;
double price;
};
FILE *fp;
int menu_select();
void enter();
void rewrite();
void print_d();
#define file_name "ins.dat"
int main()
{
char choice;
//1 ввод данных в файл
//2 обновление информации
//3 печать всех данных
for(;;)
{
choice=menu_select();
switch(choice)
{
case 1: enter();
break;
case 2: rewrite();
break;
case 3: print_d();
break;
case 4: exit(0);
}
}
return 0;
}
int menu_select()
{
int i;
char s[3];
printf("1 - enter some data\n");
printf("2 - rewrite data\n");
printf("3 - print all data\n");
printf("4 - exit\n");
do
{
printf("Choose smth:\n");
scanf("%s",s);
i=atoi(s);
} while (i<1||i>4);
return i;
}
void enter()
{
// открывает существующий файл или создает новый для дозаписи
if((fp=fopen(file_name,"a+b"))==NULL){
printf("Error opening\n");
exit(1);
}
// устанавливает указатель на начало файла
rewind(fp);
int x=0;
instr tempData;
while(fread(&tempData,sizeof(instr),1,fp)){
printf("data[%d].num=%d\n",x,tempData.num);
x++;
}
if(x==MAX)
{
printf("Theres no free space\n");
fclose(fp);
return;
}
else
printf("%d is free\n",MAX-x);
tempData.num=x;
printf("Enter the name\n");
scanf("%s",tempData.name);
printf("Enter the amount\n");
scanf("%d",&tempData.amount);
printf("Enter the price\n");
scanf("%lf",&tempData.price);
fwrite(&tempData,sizeof(instr),1,fp);
fclose(fp);
}
void rewrite()
{
// открывает существующий файл для чтения и записи
if((fp=fopen(file_name,"r+b"))==NULL)
{
printf("Error opening file\n");
return;
}
char Name[10]={};
printf("Enter the name\n");
scanf("%s",Name);
printf("the name is %s\n", Name);
instr tempData;
while(fread(&tempData,sizeof(instr),1,fp)){
if(!strcmp(tempData.name,Name)){
printf("The number of that thing is %d\n",tempData.num);
printf("enter the new amount\n");
scanf("%d",&tempData.amount);
fseek(fp,-sizeof(instr),SEEK_CUR);
fwrite(&tempData,sizeof(instr),1,fp);
fclose(fp);
return;
}
}
printf("Name is not found\n");
fclose(fp);
}
void print_d()
{
// открывает существующий файл для чтения
if((fp=fopen(file_name,"rb"))==NULL) {
printf("Error opening file\n");
return;
}
instr tempData;
while(fread(&tempData,sizeof(instr),1,fp)){
printf("%-3d%-10s%-5d%-10.2lf\n",tempData.num,tempData.name,tempData.amount,tempData.price);
}
fclose(fp);
}
Объяснение кода листинга программы
- Структура
instrсодержит поляnum,name,amountиprice. - Переменная
fpиспользуется для работы с файлом. - Функция
menu_selectиспользуется для выбора действия из меню. - В функции
enterпроисходит добавление нового элемента в файл. - В функции
rewriteпроисходит изменение количества товара в файле. - Функция
print_dиспользуется для печати всех данных из файла. - В основной функции
mainпроисходит бесконечный цикл, в котором выбирается действие из меню. - Если выбран вариант 1, то вызывается функция
enter. - Если выбран вариант 2, то вызывается функция
rewrite. - Если выбран вариант 3, то вызывается функция
print_d. - Если выбран вариант 4, то выполняется выход из программы.
- В функции
enterиспользуется функцияfopenдля открытия файла и функцияfcloseдля его закрытия. - В функции
rewriteиспользуется функцияfopenдля открытия файла и функцияfcloseдля его закрытия. - В функции
print_dиспользуется функцияfopenдля открытия файла и функцияfcloseдля его закрытия. - В функции
enterиспользуется функцияfreadдля чтения данных из файла и функцияfwriteдля записи данных в файл. - В функции
rewriteиспользуется функцияfreadдля чтения данных из файла и функцияfwriteдля записи данных в файл. - В функции
print_dиспользуется функцияfreadдля чтения данных из файла. - В функции
enterиспользуется функцияscanfдля ввода данных. - В функции
rewriteиспользуется функцияscanfдля ввода данных. - В функции
print_dиспользуется функцияprintfдля вывода данных на экран.