如何在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"
和 "%["
格式需要。
我用过下面的代码。 '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"
和 "%["
格式需要。