好的,我知道代码可能很长但我尽可能地将其最小化。我希望代码能够工作,这样你就可以重新创建我的问题了。我的问题是,当我尝试阅读文本文件时,它并没有读取所有项目。它似乎只读了最后几个。我可能会在没有注意的情况下意外地改变了一些东西,因为之前它工作得很好。当您进入程序并注册项目时,它会对项目进行计数。但是当你打开文件时,你刚刚保存了你的项目。它计算的项目数量少于实际文件中的数量,并且数组完全错误。如果有人能在我的代码中看到问题,那将非常感激。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 20
struct items
{
int itemnumber;
char name[30];
int balance;
};
void open_file(FILE *enter_filename, char filename[], struct items aItems[], int *num_items)
{
int i=0;
printf("Choose filename (.txt).\n");
scanf("%19s", filename);
enter_filename=fopen(filename, "r+");
if(enter_filename)
{
while(!feof(enter_filename))
{
for(i = 0; i < *num_items; i++)
{
fscanf(enter_filename, "Itemnumber: %d\n", &aItems[i].itemnumber);
fscanf(enter_filename, "Name: %s\n", aItems[i].name);
fscanf(enter_filename, "Balance: %d\n", &aItems[i].balance);
}
if(!feof(enter_filename))
{
*num_items=*num_items + 1;
}
}
printf("\nNumber of items: %d \n",*num_items);
fclose(enter_filename);
}
else
{
printf("That file doesn't exist! Create a new one.\n");
printf("What name do you want for your new file?\n");
scanf("%19s", filename);
enter_filename=fopen(filename, "w+");
printf("File is created!\n");
*num_items = 0;
fclose(enter_filename);
}
}
void register_item(struct items *aItems, int *num_items)
{
int success=1;
if(*num_items < MAX)
{
while(1)
{
printf("Item number:\n");
scanf("%d", &aItems[*num_items].itemnumber);
for(int i=0; i < *num_items; i++)
{
if(aItems[*num_items].itemnumber == aItems[i].itemnumber)
{
printf("Item number already exists, choose a unique item number.\n");
success=0;
break;
}
else
{
success=1;
}
}
if(success)break;
}
printf("Name:\n");
scanf("%29s", aItems[*num_items].name);
strlwr(aItems[*num_items].name);
printf("Balance:\n");
scanf("%d", &aItems[*num_items].balance);
*num_items+=1;
}
}
void print_item(struct items aItems[], int num_items)
{
int i;
for (i=0; i < num_items; i++)
{
printf("%d. Item number: %d Name: %s Balance: %d\n", i+1, aItems[i].itemnumber, aItems[i].name, aItems[i].balance);
}
}
void quit_program(char filename[], struct items aItems[], int *num_items)
{
FILE *fil;
fil=fopen(filename, "w+");
int i;
for(i = 0; i < *num_items; i++)
{
fprintf(fil, "Itemnumber: %d\n", aItems[i].itemnumber);
fprintf(fil, "Name: %s\n", aItems[i].name);
fprintf(fil, "Balance: %d\n\n", aItems[i].balance);
}
fclose(fil);
}
int main(void)
{
FILE *enter_filename;
struct items aItems[MAX];
int menu, num_items=0;
char filename[20];
open_file(enter_filename,filename, aItems, &num_items);
while(menu!=3)
{
printf("\n");
printf("1. Register new items to inventory.\n");
printf("2. Print all items from inventory.\n");
printf("3. Quit\n");
scanf("%d", &menu);
if(menu==1)
{
register_item(aItems, &num_items);
}
if(menu==2)
{
print_item(aItems, num_items);
}
if(menu==3)
{
quit_program(filename, aItems, &num_items);
}
}
return 0;
}
答案 0 :(得分:1)
您的错误在这里:
while(!feof(enter_filename))
{
for(i = 0; i < *num_items; i++)
{
fscanf(enter_filename, "Itemnumber: %d\n", &aItems[i].itemnumber);
fscanf(enter_filename, "Name: %s\n", aItems[i].name);
fscanf(enter_filename, "Balance: %d\n", &aItems[i].balance);
}
if(!feof(enter_filename))
{
*num_items=*num_items + 1;
}
}
在第一次循环中,*num_items
为零,因此不会输入执行实际读数的iner循环,aItems[i]
将未初始化。然后,您可以增加项目计数器。
在下一个传递中,将只读取一个项目,即aItems[1]
,但它将接收第一个项目的数据。您可以增加计数器。在第三遍中,您读取aItems[2]
,但会立即覆盖它,因为您的内部循环会产生与数组中当前元素一样多的遍历。显然,这是错误的。
当您阅读文件时,您不知道有多少项目。因此,您必须阅读一个项目,测试是否可以读取,然后相应地增加计数器。测试文件是否已经结束或输入是否正确是通过fscanf
的返回值完成的,它返回成功转换的项目数。
你的循环可以像这样工作:
while (*num_items < MAX) {
struct items *p = &aItems[*num_items];
if (fscanf(f, "Itemnumber: %d\n", &p->itemnumber) < 1
|| fscanf(f, "Name: %s\n", p->name) < 1
|| fscanf(f, "Balance: %d\n", &p->balance) < 1) {
break;
}
(*num_items)++;
}
(我称之为文件句柄f
:enter_filename
太长且太误导了。)
其他注意事项:
menu
未初始化,启动程序时可能为3。答案 1 :(得分:0)
在open_file
功能中,您使用while(!feof(enter_filename))
。
这不是一种可靠的文件阅读方式,as it is stated in this question.
对于您的情况,您最终的结果是,因为您在错误的num_items
循环中设置了while(!feof(enter_filename))
,您的num_items
包含错误的值,并且它会通过您的程序逻辑传播,因为您正在使用它几乎无处不在,特别是当再次写回文件时,这解释了缺失的线条。实施here或here中提到的方法之一后,请使用调试器确保num_items
与输入文件一致。