提问人:Chemical Brewster 提问时间:2/20/2023 最后编辑:John BollingerChemical Brewster 更新时间:2/20/2023 访问量:124
理解 C 语言中的 fseek()
Understanding fseek() in C
问:
我正在用 C 语言学习文件 I/O,并有兴趣使用它通过 和 函数将结构读取和写入文件,现在在我的代码成功运行后,我想知道我是否可以从结构数组中读取特定结构并将其放在某个给定的结构中。fwrite()
fread()
这是我的尝试
#include <stdio.h>
#include <stdlib.h>
typedef struct tools {
int recordno;
char toolname[50];
int quantity;
float cost;
} tools;
void recordprinter(tools a) {
printf("%d %s %d %f\n", a.recordno, a.toolname, a.quantity, a.cost);
}
int main() {
FILE * fp;
fp = fopen("file.txt", "rb+");
tools * a = (tools * ) malloc(100 * sizeof(tools));
for (int i = 0; i < 100; i++) {
a[i].cost = 0;
a[i].toolname[0] = 'a';
a[i].toolname[1] = '\0';
a[i].quantity = 0;
a[i].recordno = i + 1;
}
for (int i = 0; i < 100; i++) {
fwrite(a + i, sizeof(tools), 1, fp);
fseek(fp, sizeof(tools), SEEK_CUR);
// I used fseek here just because fwrite doesnot move the cursor when\
it writes something to the file.(and fwrite(a + i, sizeof(tools), 100, fp) gives weird gliches)
}
fseek(fp, 0, SEEK_SET); // to bring cursor back to start of the file.
fread(a, sizeof(tools), 1, fp);
fseek(fp, sizeof(tools) * 50, SEEK_SET); // now I expect the cursor to be at 51th structure.
fread(a + 3, sizeof(tools), 1, fp); // I am now writing the 51th structure in a[3]
recordprinter(a[3]);
// this gives output 26 and not 51
return 0;
}
现在,当我运行我期望的输出程序时,
但令我惊讶的是,它正在捡起第 26 个结构并将其放入 [3]
任何帮助都将得到应用!!51 a 0 0.00000
答:
1赞
atl
2/20/2023
#1
尝试更改为使用而不是fopen
w+
rb+
此外,如前所述,在创建文件时删除 肯定会在写入数据后推进文件偏移量(前提是确实写入数据)。fseek
fwrite
fwrite
以下是使用下面修改后的代码观察到的输出。
gcc main.c
./a.out
51 a 0 0.000000
// main.c
#include <stdio.h>
#include <stdlib.h>
typedef struct tools {
int recordno;
char toolname[50];
int quantity;
float cost;
} tools;
void recordprinter(tools a) {
printf("%d %s %d %f\n", a.recordno, a.toolname, a.quantity, a.cost);
}
int main() {
FILE * fp;
// recommend for this example using w+
// w because it creates the file if the file doesn't exist
// r fails if the file doesn't exist (and that doesn't seem useful here)
// + because you are reading and writing
// avoiding b and choosing POSIX - linux
// may be wrong, if libc docs says b is needed then use b
// my doc "man fopen" says b is ignored
fp = fopen("file.txt", "w+");
// check return values, file pointer exist? fail if not
if (fp==NULL) { printf( "oops file not opened\n" ); return 1; }
tools * a = (tools * ) malloc(100 * sizeof(tools));
for (int i = 0; i < 100; i++) {
a[i].cost = 0;
a[i].toolname[0] = 'a';
a[i].toolname[1] = '\0';
a[i].quantity = 0;
a[i].recordno = i + 1;
}
// alternative way to save 100 objects
// if ( fwrite(a, sizeof(tools), 100, fp) != 100 )
// {
// printf( "oops 100 objects not written to file\n" );
// return 1;
// }
for (int i = 0; i < 100; i++) {
fwrite(a + i, sizeof(tools), 1, fp);
// remove fseek, not needed, fwrite does what is needed here
//fseek(fp, sizeof(tools), SEEK_CUR);
// I used fseek here just because fwrite doesnot move the cursor when
// it writes something to the file.(and fwrite(a + i, sizeof(tools), 100, fp) gives weird gliches)
}
// no review after this line, it seems to do what author intends
fseek(fp, 0, SEEK_SET); // to bring cursor back to start of the file.
fread(a, sizeof(tools), 1, fp);
fseek(fp, sizeof(tools) * 50, SEEK_SET); // now I expect the cursor to be at 51th structure.
fread(a + 3, sizeof(tools), 1, fp); // I am now writing the 51th structure in a[3]
recordprinter(a[3]);
// this gives output 51 as desired
return 0;
}
评论
1赞
John Bollinger
2/20/2023
关于您为什么建议这些更改的一些评论将是有序的。
0赞
John Bollinger
2/20/2023
此外,将文件作为文本文件打开似乎不合适 ()。某些实现没有有意义地区分文本和二进制模式,但其他实现可以,在这些实现上,应用程序使用并且通常需要二进制模式。也许,那么。w+
fread()
fwrite()
wb+
0赞
Chemical Brewster
2/20/2023
wb+
似乎是一个不错的选择,谢谢@atl
0赞
atl
2/20/2023
@JohnBollinger,同意 - 添加了一些关于我为什么选择上面列出的内容的解释
1赞
John Bollinger
2/20/2023
@atl,为什么选择一种语义上更正确且适用于所有实现的替代方案如此容易,为什么还要选择仅适用于某些实现的替代方案呢?
评论
fwrite
确实应该移动“游标”,所以连续两次调用要写入一个文件,应该先后写入两个不同的位置。与 相同。fwrite
fread
fwrite
移动光标,句号。fwrite
fseek()