如何在c中将文本文件传递到数组中?

如何在c中将文本文件传递到数组中?,c,arrays,file,C,Arrays,File,这里没有程序员…所以请容忍我。我试图将一个现有的文本文件传递到一个数组中,但是一旦我的主菜单加载了该文件中曾经存在的信息,即使我没有做任何更改,这些信息也会消失。它只是不保存信息。该程序应该允许用户创建新文件或更新和/或加载现有文件。关于如何解决这个问题有什么想法吗?谢谢大家! char fileName[20] = ""; void loadEmployee() { FILE* fPtr; char singleLine[150]; if (strcmp(fileN

这里没有程序员…所以请容忍我。我试图将一个现有的文本文件传递到一个数组中,但是一旦我的主菜单加载了该文件中曾经存在的信息,即使我没有做任何更改,这些信息也会消失。它只是不保存信息。该程序应该允许用户创建新文件或更新和/或加载现有文件。关于如何解决这个问题有什么想法吗?谢谢大家!

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();
}
char文件名[20]=“”;
void loadEmployee()
{
文件*fPtr;
字符单线[150];
如果(strcmp(文件名“”)==0)
{
printf(“\n文件名是什么?”);
扫描文件(“%s”,文件名,20);
}
fopen_s(&fPtr,文件名,“r”);
而(!feof(fPtr))
{
fgets(单线,150,fPtr);
puts(单线);
}
fclose(fPtr);
}
void saveEmployee()
{
文件*fPtr;
如果(strcmp(文件名“”)==0)
{
printf(“\n文件名是什么?”);
扫描文件(“%s”,文件名,20);
}
fopen_s(&fPtr,文件名,“w”);
对于(int i=0;i
您的函数
loadEmployee
只写入函数本地的字符[](这意味着它在最后被丢弃)

当程序退出时,您通过在write模式下重新打开文件来«保存»员工,该模式将清除该文件,随后的操作可能不会起到多大作用,因此该文件保持为空


尝试在函数外部实际返回或存储文件中的数据,以便以后可以重用。

正如@hugo所说,程序读取文件,但不存储内容。这意味着
emp
将为空。退出时,打开文件进行写入并删除其内容。因为emp
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
的返回值。当你读台词的时候


代码中的其他问题

您没有检查文件是否已实际打开

    fopen_s(&fPtr, fileName, "r");
    if( !fPtr ) {
        perror(fileName);
        exit(1);
    }
代码使用了很多全局变量。这导致了难以理解的代码,因为任何东西都可以随时更改这些全局变量。相反,利用函数参数和返回值。然后,您可以通过查看函数来完全理解它

例如,
loadEmployee
应该获取要填充的结构和要读取的文件名,然后返回读取的数量<代码>保存员工与此类似

int loadEmployee(struct Employee *emps, char *fileName) {
    ...
    return numEmps;
}

void saveEmployee(struct Employee *emps, char *fileName) {
    ...
}
两者都不应负责向用户询问文件名。这应该由调用方处理。功能应该做一件事;它使它们更简单、更灵活

我们可以移动逻辑,将文件名放入函数中。我们使用的不是全局的,而是全局的。此变量仍然是函数的局部变量,但不会重置
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;
}
...


这些不是问题的根源,但它们有助于构建代码,使其更易于理解和调试。

为什么要使用Microsoft非标准函数
scanf_s
fopen_s
?如果我不使用安全版本,可能会重复使用visual studio,它抛出了一个错误。请查看我的答案以消除错误。加载时,您似乎没有对
单线
中包含的数据执行任何操作,可能您想使用
fscanf
而不是
fgets
。感谢您提供的所有反馈。我一定会实施这个。现在,我尝试添加您的代码,但是
emp
不起作用,它抛出此错误不允许使用不完整类型。我不应该把这个添加到索引中吗?就像我使用的
saveEmployee
<代码>fprintf(fPtr,”%