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;
}
...



这些不是问题的根源,但是它们将帮助结构化代码,以便于理解和调试。

09-10 23:50