如何在C中编辑文件中的记录?

How to edit a record in a file in C?

我用过下面的代码。 's' 是结构体的一个变量。有人能告诉我 fseek 的正确用法吗,因为这段代码不会替换,而是会在文件中添加编辑的部分。

文件名'g'的模式为r+

哈哈

在输出部分,每当滚动不匹配时,它一次显示 2 行并且不等待输入。

您要更改名称吗? (y/n) 您要更改 class 吗? (y/n)

void edit()
{
int x;
char ch,c;
printf("\nEnter roll no. \n");
scanf("%d", &x);
rewind(g);
while(!feof(g))
{
    fscanf(g, "%d %s %d %s %s", &s.roll, s.name, &s.standard, s.sub, s.address);
    if(s.roll==x)
    {
        printf("\nDo you want to change the name? (y/n)\n");
        scanf("%c",&ch);
        if(ch=='y')
        {
            printf("\nEnter new name\n");
            scanf("%s", s.name);
        }
        printf("\nDo you want to change the class? (y/n)\n");
        scanf("%c",&ch);
        if(ch=='y')
        {
            printf("\nEnter new class\n");
            scanf("%d",&s.standard);
        }
        printf("\nDo you want to change the subject? (y/n)\n");
        scanf("%c", &ch);
        if(ch=='y')
        {
            printf("\nEnter new subject\n");
            scanf("%s", s.sub);
        }
        printf("\nDo you want to change the address? (y/n)\n");
        scanf("%c", &ch);
        if(ch=='y')
        {
            printf("\nEnter new address\n");
            scanf("%s", s.address);
        }
        fseek(g,sizeof(struct student) ,SEEK_SET);
        fprintf(g,"%d %s %d %s %s",s.roll, s.name, s.standard, s.sub, s.address);
    }
}
fclose(g);

}

据我所知,您有两种选择:一种是以二进制模式打开文件,read/write 结构按原样。另一种是继续使用具有可变长度记录的文本文件。解决方案在很大程度上取决于您在此选择后如何继续。我将为两者提供示例代码。


首先是读写整个结构的二进制解决方案。

为此你可以这样做:

// Open the file for reading and writing, in binary mode
// Initial position is at the beginning of the file
g = fopen("some path to the file", "r+b");

...

// While we can read one structure
while (fread(&s, sizeof(s), 1, g) == 1)
{
    // Your code to update the structure...

    // Seek backwards in the file from the current position
    // So when we write we will overwrite the structure we just read
    fseek(g, -sizeof(s), SEEK_CUR);

    // Write out the structure again, overwriting the previous data
    fwrite(&s, sizeof(s), 1, g);
}

处理文本文件中可变长度记录的代码要难得多,因为这样你就不能实际替换文件中的内容"in place",你必须写入一个临时文件,你完成后重命名为原始文件。

// Open the input file in read-only text mode
g = fopen("some path to the file", "r");
t = fopen("some path to the file.tmp", "w");
...

// Buffer where we read each line of the input file into
char line[256];

// Loop while we can read a line
while (fgets(line, sizeof(line), g) != NULL)
{
    sscanf(line, "%d %29[^1234567890] %d %19[^1234567890] %99[^\n]%*c",
           &s.roll, s.name, &s.standard, s.sub, s.address);

    // Your existing code to update the structure...

    // Write to the temporary file
    fprintf(t, "%d %s %d %s %s\n",
            s.roll, s.name, s.standard, s.sub, s.address);
}

// Close the files
fclose(t);
fclose(g);

// Rename the files, overwriting the old original file
// with the temporary file
rename("some path to the file.tmp", "some path to the file");

这两种解决方案都各有利弊。对于第一个解决方案,专业人士认为它显然更容易和更简单。缺点是文本编辑器无法真正读取它,并且您不能简单地将文件复制到具有不同 endianness.

的平台

使用文本文件的优点是您可以在几乎任何程序(如简单的文本编辑器)中阅读和编辑该文件。缺点是它更难,需要更多代码。


当您使用 scanf 读取用户的输入时,您读取的是单个字符。当您输入单个字符时,您会写下字符,然后按 Enter 键,对吗?字符 Enter 键都将被放入输入缓冲区。 scanf 调用读取输入但保留 Enter 键,因此下次尝试读取输入时 scanf 将看到由 Enter 键添加的换行符。

您可以通过在格式中添加一个 space 来解决这个问题,例如

scanf(" %c",&ch);
//    ^
//    |
// Note space here

额外的前导 space 将告诉 scanf 读取并丢弃任何白色-space。

数字和字符串格式不需要,它们会自动跳过前导 space,只有 "%c""%[" 格式需要。