Noob程序员在这里...所以请忍受我。我正在尝试将现有文本文件传递到数组中,但是一旦我的主菜单加载了该文件中曾经存在的信息,即使我没有进行任何更改,该信息也会消失。它只是不保留信息。该程序应允许用户创建新文件或更新和/或加载现有文件。有关如何解决此问题的任何想法?谢谢你们!
char fileName[20] = "";
void loadEmployee()
{
FILE* fPtr;
char singleLine[150];
if (strcmp(fileName, "") == 0)
{
printf("\nWhat's the name of the file? ");
scanf_s("%s", fileName, 20);
}
fopen_s(&fPtr, fileName, "r");
while (!feof(fPtr))
{
fgets(singleLine, 150, fPtr);
puts(singleLine);
}
fclose(fPtr);
}
void saveEmployee()
{
FILE* fPtr;
if (strcmp(fileName, "") == 0)
{
printf("\nWhat's the name of the file? ");
scanf_s("%s", fileName, 20);
}
fopen_s(&fPtr, fileName, "w");
for (int i = 0; i < numEmps; i++)
{
fprintf(fPtr, "%s %f %f\n", emps[i].emps.name,
emps[i].emps.rate, emps[i].emps.hours);
}
fclose(fPtr);
}
void loadMenu()
{
int i = 0;
printf("1. Load from a file \n");
printf("2. Keyboard \n");
scanf_s("%d", &choice);
switch (choice)
{
case 1: loadEmployee();
break;
default:
break;
}
do
{
printf("\nMAIN MENU\n");
printf("1.Add Employee\n");
printf("2.Edit Employee\n");
printf("3.Print Employee\n");
printf("4.Print ALL employees\n");
printf("5.Exit\n");
scanf_s("%d", &choice);
switch (choice)
{
case 1: NameInput();
break;
case 2: printf("Choose employee: \n");
for (int i = 0; i < numEmps; i++)
{
printf("%d. %s \n", i + 1,
emps[i].emps.name);
}
scanf_s("%d", &choice);
empUpdate(choice - 1);
break;
case 3: printf("Choose employee: \n\n");
for (int i = 0; i < numEmps; i++)
{
printf("%d) %s \n", i + 1,
emps[i].emps.name);
}
scanf_s("%d", &choice);
printf("%s \n", emps[choice -
1].emps.name);
printf("%.2f \n", emps[choice -
1].emps.hours);
printf("%.2f \n", emps[choice -
1].emps.rate);
break;
case 4: PayOutput();
break;
case 5: printf("Quitting program!");
saveEmployee();
return;
default: printf("Invalid choice try again \n\n");
break;
}
} while (choice != 5);
}
int main()
{
struct information empsi[20];
loadMenu();
}
最佳答案
正如@hugo所说,该程序读取文件但不存储内容。这意味着emps
将为空。退出时,打开文件进行写入以删除其内容。 Beause emps
为空,不写任何内容。
这可以通过阅读类似于您的写作方式来解决。我不完全知道emps
是什么样子,但是像这样。
for( numEmps = 1; fgets(singleLine, 150, fPtr); numEmps++ ) {
// I'm assuming emps is preallocated.
struct Employee emp = emps[numEmps-1];
sscanf(singleLine, "%80s %f %f",
emp.emps.name,
&emp.emps.rate,
&emp.emps.hours
);
}
请注意,而不是使用
feof
,我正在查看fgets
的返回值。与Edward Karak mentioned一样,当读取行don't check for eof
时。代码中的其他问题...
您无需检查文件是否实际打开。
fopen_s(&fPtr, fileName, "r");
if( !fPtr ) {
perror(fileName);
exit(1);
}
该代码使用许多全局变量。这导致难以理解的代码,因为任何事物都可以随时更改这些全局变量。而是利用函数参数和返回值。然后,您只需看一下即可完全理解其功能。
例如,
loadEmployee
应该使用要填充的结构和要读取的文件名,然后返回读取的文件数。 saveEmployee
是相似的。int loadEmployee(struct Employee *emps, char *fileName) {
...
return numEmps;
}
void saveEmployee(struct Employee *emps, char *fileName) {
...
}
都不应该负责询问用户文件名。这应该由调用方处理。函数应该做一件事;它使它们更简单,更灵活。
我们可以移动逻辑以将文件名转换为函数。我们使用static variable而不是使用全局。该变量仍然是函数的局部变量,但不会重置。
getFileName
记住文件名。char *getFileName() {
static char fileName[80] = "";
if (strcmp(fileName, "") == 0)
{
printf("\nWhat's the name of the file? ");
scanf("%20s", fileName);
}
return fileName;
}
...
switch(choice) {
case 1:
numEmps = loadEmployee(emps, getFileName());
break;
...
case 5:
printf("Quitting program!");
saveEmployee(emps, getFileName());
return;
}
...
这些不是问题的根源,但是它们将帮助结构化代码,以便于理解和调试。