如何使用带有索引的struct在c中使用文件描述符或系统调用来读写文件和处理文件

How to read and write files and process files using file-descriptor or system call in c using struct with index

我正在使用文件描述符在 c 中编写应用程序,打开、读取、写入以使用具有内容 {name,age,mob} 的结构数组将信息存储到文件中,例如 struct Students student[50]。我如何处理读回结构并说通过名称检索学生的其他信息,如搜索......? 感谢帮助

这是我迄今为止尝试过的方法,但仍未按预期工作

// functions to implement
short studentInDatabase;
void saveStudentToFile();
void requireEntered();
void addStudent();
void showStudents();
void loadStudentFromFile();
void searchDatabase();
struct Student
{
    char name[20];
    char surname[20];
    char age[20]; //using char array because i can't save int to file
    char telephone[20];

};

struct Student newStudent[500];
struct Student myUserInfo;
void addStudent()
{

    printf("Type Student Name: ");
    scanf("%s",  myUserInfo.name );

    printf("Type Surname: ");
    scanf("%s", myUserInfo.surname);

    printf("Type Age: ");
    scanf("%s", myUserInfo.age);

    printf("Type Telephone: ");
    scanf("%s", myUserInfo.telephone);

    studentInDatabase++;

}
void showStudents()
{
    if(peopleInDatabase > 0)
    {
        for(int i = 0; i < peopleInDatabase; i++)
        {
            printf("Person in index %d\n", i+1);
            printf("Name: %s \n", myUserInfo.name);
            printf("Surname: %s\n",myUserInfo.surname );
            printf("Age: %s\n",myUserInfo.age);
            printf("Telephone: %s\n\n",myUserInfo.telephone);
// Use this is using the newStudents Array structure
//            printf("Person in index %d\n", i+1);
//            printf("Name: %s \n", newStudents [i].name);
//            printf("Surname: %s\n", newStudents [i].surname );
//            printf("Age: %s\n", newStudents [i].age);
//            printf("Telephone: %s\n\n", newStudents [i].telephone);

        }
    }
    else {
          printf("There is nobody available...");
    }
}
void savePeopleToFile()
{
    //char *mega_string;
    int  fd, ret, sz, ssz, asz, tsz, psz, fdd;
    char fn[]="writefile.txt";

    fd = open(fn, O_WRONLY| O_CREAT| O_APPEND );
    if(fd < 0 )
    {
        perror("open write() error");
        printf("Error Creating File\n");
    }

    printf("Open File Successfully......%d\n\n", fd);

    if(peopleInDatabase > 0)
    {
//        printf("People in Database......%d\n", psz);
        for(int i = 0; i < peopleInDatabase; i++)
        {
            //
            sz = write(fd, myUserInfo.name , sizeof( myUserInfo.name));
            printf("Size for name......%d\n", sz);

            ssz = write(fd, myUserInfo.surname, sizeof(myUserInfo.surname));
            printf("Size for Surname......%d\n", ssz);

            asz = write(fd, myUserInfo.age, sizeof(myUserInfo.age));
            printf("Size for age......%d\n", asz);

            tsz = write(fd, myUserInfo.telephone, sizeof(myUserInfo.telephone));
            printf("Size for telephone......%d\n", tsz);
        }
//
//            sz = write(fd, newStudents [i].name, sizeof(people[i].name));
//            printf("Size for name......%d\n", sz);
//
//            ssz = write(fd, newStudents[i].surname, sizeof(people[i].surname));
//            printf("Size for Surname......%d\n", ssz);
//
//            asz = write(fd, newStudents [i].age, sizeof(people[i].age));
//            printf("Size for age......%d\n", asz);
//
//            tsz = write(fd, newStudents[i].telephone, sizeof(people[i].telephone));
//            printf("Size for telephone......%d\n", tsz);
        }
    close(fd);
}
void loadStudentFromFile()
{
    int readret, someSize;
    int foo;
    int  fd;
    char buf[4096];
    char fn[]="writefile.txt";
     if((fd = open(fn, O_RDONLY )) < 0)
    {
        perror("creat() error");
        printf("Error Creating File\n");
    }

    // Use this when using array structure
    readret = read(fd, newStudent , sizeof(newStudent) != EOF);

    // Use this when using myUserInfo structure
    readret = read(fd, &myUserInfo , sizeof(myUserInfo) != EOF);

    while (readret = read(fd, &myUserInfo , sizeof(people) != EOF))
    {
           printf("Person Index: %d \n", (i+1));
           printf("Name: %s  \n",   myUserInfo.name);
           printf("Surname: %s  \n",   myUserInfo.surname);
           printf("Age: %s  \n",   myUserInfo.age);
           printf("Tel: %s  \n\n",  myUserInfo.telephone);
    };

// Check for readret in not -1 or EOF
//    if(readret > 0)
//    {
//        int i = 0;
//        for(; i < 10; i++)
//        {
////             printf("Person Index: %d \n", (i+1));
////             printf("Name: %s  \n",   newStudent[i].name);
//               printf("Name: %s  \n",   myUserInfo.name);
//               printf("Surname: %s  \n",   myUserInfo.surname);
////             printf("Age: %s  \n",   newStudent[i].age);
////             printf("Tel: %s  \n\n",   newStudent[i].telephone);
//
//             if(newStudent[i].surname == "Midel" )
//             {
//                 printf("%s %s is Available ....\n",myUserInfo.name, myUserInfo.surname);
//             }
//      }
//   }

    close(fd);
}
void searchDatabase(char search[])
{
    int readret, someSize;
    int foo;
    int  fd;
    char buf[4096];
    char fn[]="writefile.txt";
     if((fd = open(fn, O_RDONLY )) < 0)
    {
        perror("creat() error");
        printf("Error Creating File\n");
    }

    // Use this when using array structure
    readret = read(fd, newStudent , sizeof(newStudent) != EOF);

    // Use this when using myUserInfo structure
    readret = read(fd, &myUserInfo , sizeof(myUserInfo) != EOF);

    while (readret = read(fd, &myUserInfo , sizeof(people) != EOF))
    {
         if(newStudent[i].surname == "search" )
//        {
//           Return Details of User when Found....  
//            printf("Person Index: %d \n", (i+1));
//           printf("Name: %s  \n",   myUserInfo.name);
//           printf("Surname: %s  \n",   myUserInfo.surname);
//           printf("Age: %s  \n",   myUserInfo.age);
//           printf("Tel: %s  \n\n",  myUserInfo.telephone);
//        }

    };

// Check for readret in not -1 or EOF
//    if(readret > 0)
//    {
//        int i = 0;
//        for(; i < 10; i++)
//        {
////             printf("Person Index: %d \n", (i+1));
////             printf("Name: %s  \n",   newStudent[i].name);
//               printf("Name: %s  \n",   myUserInfo.name);
//               printf("Surname: %s  \n",   myUserInfo.surname);
////             printf("Age: %s  \n",   newStudent[i].age);
////             printf("Tel: %s  \n\n",   newStudent[i].telephone);
//
//             if(&people[i].surname == "search" )
//             {
//                 printf("%s %s is Available ....\n",myUserInfo.name, myUserInfo.surname);
//             }
//      }
//   }

    close(fd);
}

我在阅读时期望得到 DB 文件中的学生人数

// Write four (4) students or people
if(peopleInDatabase < 4)
    {
//        printf("People in Database......%d\n", psz);
        for(int i = 0; i < peopleInDatabase; i++)
        {
            //
            sz = write(fd, myUserInfo.name , sizeof( myUserInfo.name));
            printf("Size for name......%d\n", sz);

            ssz = write(fd, myUserInfo.surname, sizeof(myUserInfo.surname));
            printf("Size for Surname......%d\n", ssz);

            asz = write(fd, myUserInfo.age, sizeof(myUserInfo.age));
            printf("Size for age......%d\n", asz);

            tsz = write(fd, myUserInfo.telephone, sizeof(myUserInfo.telephone));
            printf("Size for telephone......%d\n", tsz);
        }
// Use this when using array structure should return 4 
// i.e Shouldn't exceed 4
    readret = read(fd, newStudent , sizeof(newStudent) != EOF);

    // Use this when using myUserInfo structure
    readret = read(fd, &myUserInfo , sizeof(myUserInfo) != EOF);

    while (readret = read(fd, &myUserInfo , sizeof(people) != EOF))
    {
           printf("Person Index: %d \n", (i+1));
           printf("Name: %s  \n",   myUserInfo.name);
           printf("Surname: %s  \n",   myUserInfo.surname);
           printf("Age: %s  \n",   myUserInfo.age);
           printf("Tel: %s  \n\n",  myUserInfo.telephone);
    };
void searchStudent(char search[])
// Check for readret in not -1 or EOF
//    if(readret > 0)
//    {
//        int i = 0;
//        for(; i < 10; i++)
//        {
//             if(newStudent[i].surname == "search" )
//             {
//                 printf("%s %s is Available ....\n",myUserInfo.name, myUserInfo.surname);
//                  printf("Person Index: %d \n", (i+1));
////             printf("Name: %s  \n",   newStudent[i].name);
//               printf("Name: %s  \n",   myUserInfo.name);
//               printf("Surname: %s  \n",   myUserInfo.surname);
////             printf("Age: %s  \n",   newStudent[i].age);
////             printf("Tel: %s  \n\n",   newStudent[i].telephone);
//             }
//      }
//   }

目前它不起作用...循环失败

int main()
{
    char test;
    loadPeopleFromFile();

    do
    {
        printf( "Number of People In Database... %d \n", peopleInDatabase);
        printf( "MENU\n");

        printf("1. Add Student\n");
        printf( "2. Show All Students\n");
        printf("3. Save Student to database... \n");
        printf( "4. Load Students from file/db...\n");
        printf( "5. Search Student from file/db database\n");
        printf( "6. Remove Student from file/db database..\n");


        test = getchar();

        switch(test)
        {
        case '1':
            addPerson();
            break;
        case '2':
             showPeople();
             break;
        case '3':
            savePeopleToFile();
            break;
        case '4':
            loadPeopleFromFile();
            break;
        case '5':
            searchDatabase();
            break;
        case '6':
            removePersonFromDatabase();
            break;
        }

        requireEntered();
        system("cls");
    } while(test != 27);

    return 0;
}
void requireEntered()
{
        printf("Click enter to continue.....");
        while(getch() != 13);
}

这是 main 中的实现....根据要求.. 如果我的意思是失败...我可以获得我保存的实际记录数,除非我为循环添加初始化和更大的整数..假设我保存了 5 条记录..我写

readret = read(fd, &myUserInfo , sizeof(myUserInfo));
if(readret > 0)
   {
       int i = 0;
       for(; i < 10; i++)
       {
             printf("Person Index: %d \n", (i+1));
             printf("Name: %s  \n",   newStudent[i].name);
             printf("Name: %s  \n",   myUserInfo.name);
             printf("Surname: %s  \n",   myUserInfo.surname);
             printf("Age: %s  \n",   newStudent[i].age);
             printf("Tel: %s  \n\n",   newStudent[i].telephone);

            if(newStudent[i].surname == "Midel" )
            {
                printf("%s %s is Available ....\n",myUserInfo.name, myUserInfo.surname);
            }
        }
     }

//NB I only use 
readret = read(fd, &myUserInfo, sizeof(myUserInfo) != EOF); //for the while loop
 while (readret = read(fd, &myUserInfo , sizeof(people) != EOF))
    {
           printf("Person Index: %d \n", (i+1));
           printf("Name: %s  \n",   myUserInfo.name);
           printf("Surname: %s  \n",   myUserInfo.surname);
           printf("Age: %s  \n",   myUserInfo.age);
           printf("Tel: %s  \n\n",  myUserInfo.telephone);
    };

任何关于获取我保存的确切数量以便我可以使用 for 循环的帮助都非常感谢... 假设我检索到 int studentsInDb 的通行证,然后我可以 if i < studentsInDb.. 谢谢

您的添加函数读入单个学生记录,但从不更新学生数组。您应该使用数组中学生人数的索引并直接读入下一个空闲元素:

struct Student newStudent[500];
int studentInDatabase;

现在读起来像:

    printf("Type Student Name: ");
    scanf("%s",  newStudent[studentInDatabase].name );
    //...
    studentInDatabase++;

showStudents 相同,注释掉的代码似乎是正确的。等等,对于你所有的其他功能。

注:if(newStudent[i].surname == "search" ):使用strcmp()比较字符串,所以if (strcmp(newStudent[i].surname, "search")==0 )

您的代码有几个问题。

此答案仅解决数据的保存和加载问题。

我假设记录的数量足够小,可以将所有数据读取到内存中的数组中,并使用该数组在内存中执行所有操作,如 adding/searching/removing 记录。当然,在任何修改之后,数据都必须写回到文件中。由于这种方法,文件打开时使用 O_TRUNC 而不是 O_APPEND.

(直接在文件上操作是可以的,但是这样的解决方案实现起来会比较困难。将记录附加到文件中已有的数据很容易,从文件中读取数据的同时搜索也很容易没问题,但是从文件中删除记录会很困难。您要么必须将记录标记为已删除,要么移动已删除记录之后的所有数据。在文件中移动数据将很困难。)

我假设 studentInDatabase 初始化为 0 并为每个新记录递增 addStudent()

这意味着您应该使用

short studentInDatabase = 0;

savePeopleToFile()中,我建议编写整个结构而不是单个字段。请注意,写入二进制数据是特定于平台的。

void savePeopleToFile()
{
    int  fd, sz, i;

    fd = open(fn, O_WRONLY| O_CREAT | O_TRUNC ); /* not O_APPEND because we want to overwrite the file */
    if(fd < 0 )
    {
        perror("open write() error");
        fprintf(stderr, "Error Creating File\n");
        return;
    }

    printf("Open File Successfully......%d\n\n", fd);

//        printf("People in Database......%d\n", psz);
    /* you could write the number of persons to the file if you want to have a cross-check */
    for(int i = 0; i < peopleInDatabase; i++)
    {

        sz = write(fd, &newStudent[i] , sizeof(newStudent[0]));

        /* TODO error handling if sz < 0 or handling of partial write if sz != sizeof(newStudent[0]) */

        printf("Size for person......%d\n", sz);

    }
    if(close(fd) < 0)
    {
        perror("close() error");
        fprintf(stderr, "Error Closing File\n");
    }
}

注意:此代码未经测试。

读取数据时,您有两种选择。如果你已经将人数写入文件,你可以先读取这个数字,然后使用 for 循环。否则使用 while 循环每个周期读取一条记录直到 EOF 并计算记录数。

使用 while 循环的解决方案:

void loadStudentFromFile()
{
    int readret;
    int  fd;

    if((fd = open(fn, O_RDONLY )) < 0)
    {
        perror("open() error");
        fprintf(stderr, "Error Opening File\n");
        return;
    }

    peopleInDatabase = 0;

    do
    {
        /* you could read directly to newStudent[peopleInDatabase], but I use
           myUserInfo for easier access to the fields for printing */
        readret = read(fd, &myUserInfo , sizeof(myUserInfo));

        /* TODO handle errors and partial reads */

        if(readret > 0)
        {
            printf("Person Index: %d \n", peopleInDatabase);
            printf("Name: %s  \n",   myUserInfo.name);
            printf("Surname: %s  \n",   myUserInfo.surname);
            printf("Age: %s  \n",   myUserInfo.age);
            printf("Tel: %s  \n\n",  myUserInfo.telephone);

            newStudent[peopleInDatabase] = myUserInfo;
            peopleInDatabase++
        }
    } while(readret > 0);

    /* readret == 0 means EOF */
    if(readret < 0)
    {
        perror("read() error");
        fprintf(stderr, "Error Reading File\n");
    }

    if(close(fd) < 0)
    {
        perror("close() error");
        fprintf(stderr, "Error Closing File\n");
    }
}

注意:此代码未经测试。

关于搜索和删除功能的备注

我不清楚菜单项 5. Search Student from file/db database6. Remove Student from file/db database..,特别是术语 "from file"。

如果您使用 4. Load Students from file/db... 将文件加载到内存中,您可以通过访问数据结构数组在内存中执行 5 和 6 的操作,并在修改后使用 [=23 将数据保存到文件中=].

或者您是否应该自动 read/write 5 和 6 的文件?