fread 只从我第一次 运行 开始阅读程序
fread only reading in from the first time I ran the program
当我第一次 运行 我会添加 3 条记录,这给了我 3 的计数。然后我 fwrite
将计数存入一个 bin 文件,然后将记录存入一个 bin 文件,然后我关闭程序。
当我重新打开它然后我 fread
进去时,它会给我 3 条记录和 3 的计数。但是从那以后,无论我备份还是读入,它将给我相同的计数 3 和 3 记录,但由于计数未更新,这可能是 fread
仅读取第一次记录的原因。
我不确定为什么计数器没有更新。 fread
和 fwrite
都返回 = 成功所以我不确定发生了什么。
void backUp(PAYROLL employee[], long int *pCounter)
{
FILE *counter;
errno_t result1 = fopen_s(&counter, "c:\myFiles\counter.bin", "a+b");
if (result1 == 0){
fwrite(pCounter, sizeof(long int), 1, counter);
fclose(counter);
}
else
printf("Back up of counter failed! error:%d",result1);
FILE *record;
errno_t result2 = fopen_s(&record, "c:\myFiles\record.bin", "a+b");
if (result2 == 0){
fwrite(employee, *pCounter *sizeof(PAYROLL), 1, record);
fclose(record);
}
else
printf("Back up of record failed! error:%d", result2);
}
void upload(PAYROLL employee[], long int *pCounter)
{
FILE *counter;
errno_t result1 = fopen_s(&counter, "c:\myFiles\counter.bin", "a+b");
if (result1 == 0){
result = fread(pCounter, sizeof(long int), 1, counter);
fclose(counter);
printf("Counter:%d", *pCounter);
}
else
printf("Upload up of counter failed!");
FILE *record;
errno_t result2 = fopen_s(&record, "c:\myFiles\record.bin", "r+b");
if (result2 == 0)
{
result2 = fread(employee, *pCounter *sizeof(PAYROLL), 1, record);
printf("Upload successful!\n");
fclose(record);
}
else
printf("Error opening file!");
}
我看到你的程序有很多错误。
首先,您将长整数和 PAYROLL 结构直接写入文件。你永远不应该这样做,因为结构和整数具有依赖于机器的表示,如果你在一台机器(比如 32 位机器)上写入文件并在另一台机器(比如 64 位机器)上读取它们,那么你可能运行 遇到问题。
其次,您没有检查 fread() 的 return 值。应该经常检查。
第三,您将 fread() 的 return 值分配给 errno_t。您确定要这样做吗?
如果您想得到实际问题的答案,请考虑更新源代码以修复我指出的错误,并考虑改进您问题中的英语。此外,您应该提供一个完整的示例,即包含 PAYROLL 定义的示例。当您知道 fread() 的实际 return 值时,也许问题会更容易追踪。
将最突出的评论转化为答案。
How do you know that fread
and fwrite
are returning "success" when you have not checked their return value?
Jude评论:
I look through the debugger and step in to the function, result is giving me their success return values (if that's how it works).
You still need that in the program. Without that sort of checking, your code will be blown over by a puff of wind.
Dmitri correctly :
Looks like everywhere you open in append mode "a+b" you should probably be using something else ("rb" in upload() and "wb" in backUp() possibly?)
Jude评论:
I don't understand, is there a specific function for error checking? As I had always thought that error checking was just looking at what goes in the value of result and then I can go check what the value means?
查看 fread()
的规格和
fwrite()
。它们 return 写入或读取的记录数,可能少于请求的数量。如果你得到一个短写,那么你就有问题了——可能是磁盘不足 space。如果您读取的内容很短,则可能是您请求了 100 条记录,但只有 1、10 或 99 条记录可供读取(或者出现错误)。如果您不捕获并检查 return 值,您将不知道发生了什么。
Jude评论:
I see they read and write 1, but it still stores the first 3 elements of my struct array. I assume it's one because it's only writing my array?
fread()
(以及 fwrite()
也)为您提供了相当大的灵活性,因为您可以分别提供项目的大小和项目的数量。您使用:
result2 = fread(employee, *pCounter *sizeof(PAYROLL), 1, record);
这告诉 fread()
读取 1
个大小为 *pCounter * sizeof(PAYROLL)
的项目。您将得到 1
(成功)或 0
(失败)的结果。您可以指定:
result2 = fread(employee, sizeof(PAYROLL), *pCounter, record);
这会告诉您读取了多少条大小为 sizeof(PAYROLL)
的记录,最多为 *pCounter
中的最大值。您可能会得到 0 或 1 或……
这里有一些可行的代码,它们或多或少地完成了所需的工作。 main()
程序演示了处理 1、2 和 3 条记录(名字是英国的几位国王和王后,以及他们登基的年份作为他们的员工 ID 号)。我不得不创建一个最小的工资单结构,因为问题没有提供。
#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct PAYROLL
{
long emp_id;
char emp_name[32];
} PAYROLL;
static const char counter_bin[] = "counter.bin";
static const char records_bin[] = "records.bin";
static
void backUp(PAYROLL employee[], long int *pCounter)
{
FILE *counter = fopen(counter_bin, "wb");
if (counter != 0){
fwrite(pCounter, sizeof(long int), 1, counter);
fclose(counter);
}
else
fprintf(stderr, "Back up of counter failed! error: %d %s\n", errno, strerror(errno));
FILE *record = fopen(records_bin, "wb");
if (record != 0){
fwrite(employee, *pCounter *sizeof(PAYROLL), 1, record);
fclose(record);
}
else
fprintf(stderr, "Back up of records failed! error: %d %s\n", errno, strerror(errno));
}
static
void upload(PAYROLL employee[], long int *pCounter)
{
FILE *counter = fopen(counter_bin, "rb");
if (counter != 0){
size_t result = fread(pCounter, sizeof(long int), 1, counter);
fclose(counter);
if (result != 0)
printf("Counter: %ld\n", *pCounter);
else
fprintf(stderr, "Failed to read counter\n");
}
else
fprintf(stderr, "Upload up of counter failed!\n");
FILE *record = fopen(records_bin, "r+b");
if (record != 0)
{
size_t result2 = fread(employee, *pCounter * sizeof(PAYROLL), 1, record);
if (result2 == 1)
printf("Upload successful!\n");
else
fprintf(stderr, "Failed to read records!\n");
fclose(record);
}
else
fprintf(stderr, "Error opening file!");
}
int main(void)
{
PAYROLL emps[] =
{
{ 1066, "William the Conqueror" },
{ 1819, "Victoria" },
{ 1689, "William and Mary" },
};
for (int i = 1; i <= 3; i++)
{
long emp_count = i;
printf("Employee count = %ld\n", emp_count);
backUp(emps, &emp_count);
upload(emps, &emp_count);
for (int j = 0; j < emp_count; j++)
printf("%4ld: %s\n", emps[j].emp_id, emps[j].emp_name);
}
return 0;
}
请注意,我已经分解出文件名,这样您只需更改一行即可更改使用的文件。示例输出:
$ Employee count = 1
Counter: 1
Upload successful!
1066: William the Conqueror
Employee count = 2
Counter: 2
Upload successful!
1066: William the Conqueror
1819: Victoria
Employee count = 3
Counter: 3
Upload successful!
1066: William the Conqueror
1819: Victoria
1689: William and Mary
$ odx counter.bin
0x0000: 03 00 00 00 00 00 00 00 ........
0x0008:
$ odx records.bin
0x0000: 2A 04 00 00 00 00 00 00 57 69 6C 6C 69 61 6D 20 *.......William
0x0010: 74 68 65 20 43 6F 6E 71 75 65 72 6F 72 00 00 00 the Conqueror...
0x0020: 00 00 00 00 00 00 00 00 1B 07 00 00 00 00 00 00 ................
0x0030: 56 69 63 74 6F 72 69 61 00 00 00 00 00 00 00 00 Victoria........
0x0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0050: 99 06 00 00 00 00 00 00 57 69 6C 6C 69 61 6D 20 ........William
0x0060: 61 6E 64 20 4D 61 72 79 00 00 00 00 00 00 00 00 and Mary........
0x0070: 00 00 00 00 00 00 00 00 ........
0x0078:
$
(odx
只是一个十六进制转储程序。选择你自己的程序来做同样的工作——od -c
是一个后备方案,虽然我不是特别喜欢它的格式。)
当我第一次 运行 我会添加 3 条记录,这给了我 3 的计数。然后我 fwrite
将计数存入一个 bin 文件,然后将记录存入一个 bin 文件,然后我关闭程序。
当我重新打开它然后我 fread
进去时,它会给我 3 条记录和 3 的计数。但是从那以后,无论我备份还是读入,它将给我相同的计数 3 和 3 记录,但由于计数未更新,这可能是 fread
仅读取第一次记录的原因。
我不确定为什么计数器没有更新。 fread
和 fwrite
都返回 = 成功所以我不确定发生了什么。
void backUp(PAYROLL employee[], long int *pCounter)
{
FILE *counter;
errno_t result1 = fopen_s(&counter, "c:\myFiles\counter.bin", "a+b");
if (result1 == 0){
fwrite(pCounter, sizeof(long int), 1, counter);
fclose(counter);
}
else
printf("Back up of counter failed! error:%d",result1);
FILE *record;
errno_t result2 = fopen_s(&record, "c:\myFiles\record.bin", "a+b");
if (result2 == 0){
fwrite(employee, *pCounter *sizeof(PAYROLL), 1, record);
fclose(record);
}
else
printf("Back up of record failed! error:%d", result2);
}
void upload(PAYROLL employee[], long int *pCounter)
{
FILE *counter;
errno_t result1 = fopen_s(&counter, "c:\myFiles\counter.bin", "a+b");
if (result1 == 0){
result = fread(pCounter, sizeof(long int), 1, counter);
fclose(counter);
printf("Counter:%d", *pCounter);
}
else
printf("Upload up of counter failed!");
FILE *record;
errno_t result2 = fopen_s(&record, "c:\myFiles\record.bin", "r+b");
if (result2 == 0)
{
result2 = fread(employee, *pCounter *sizeof(PAYROLL), 1, record);
printf("Upload successful!\n");
fclose(record);
}
else
printf("Error opening file!");
}
我看到你的程序有很多错误。
首先,您将长整数和 PAYROLL 结构直接写入文件。你永远不应该这样做,因为结构和整数具有依赖于机器的表示,如果你在一台机器(比如 32 位机器)上写入文件并在另一台机器(比如 64 位机器)上读取它们,那么你可能运行 遇到问题。
其次,您没有检查 fread() 的 return 值。应该经常检查。
第三,您将 fread() 的 return 值分配给 errno_t。您确定要这样做吗?
如果您想得到实际问题的答案,请考虑更新源代码以修复我指出的错误,并考虑改进您问题中的英语。此外,您应该提供一个完整的示例,即包含 PAYROLL 定义的示例。当您知道 fread() 的实际 return 值时,也许问题会更容易追踪。
将最突出的评论转化为答案。
How do you know that
fread
andfwrite
are returning "success" when you have not checked their return value?
Jude评论:
I look through the debugger and step in to the function, result is giving me their success return values (if that's how it works).
You still need that in the program. Without that sort of checking, your code will be blown over by a puff of wind.
Dmitri correctly
Looks like everywhere you open in append mode "a+b" you should probably be using something else ("rb" in upload() and "wb" in backUp() possibly?)
Jude评论:
I don't understand, is there a specific function for error checking? As I had always thought that error checking was just looking at what goes in the value of result and then I can go check what the value means?
查看 fread()
的规格和
fwrite()
。它们 return 写入或读取的记录数,可能少于请求的数量。如果你得到一个短写,那么你就有问题了——可能是磁盘不足 space。如果您读取的内容很短,则可能是您请求了 100 条记录,但只有 1、10 或 99 条记录可供读取(或者出现错误)。如果您不捕获并检查 return 值,您将不知道发生了什么。
Jude评论:
I see they read and write 1, but it still stores the first 3 elements of my struct array. I assume it's one because it's only writing my array?
fread()
(以及 fwrite()
也)为您提供了相当大的灵活性,因为您可以分别提供项目的大小和项目的数量。您使用:
result2 = fread(employee, *pCounter *sizeof(PAYROLL), 1, record);
这告诉 fread()
读取 1
个大小为 *pCounter * sizeof(PAYROLL)
的项目。您将得到 1
(成功)或 0
(失败)的结果。您可以指定:
result2 = fread(employee, sizeof(PAYROLL), *pCounter, record);
这会告诉您读取了多少条大小为 sizeof(PAYROLL)
的记录,最多为 *pCounter
中的最大值。您可能会得到 0 或 1 或……
这里有一些可行的代码,它们或多或少地完成了所需的工作。 main()
程序演示了处理 1、2 和 3 条记录(名字是英国的几位国王和王后,以及他们登基的年份作为他们的员工 ID 号)。我不得不创建一个最小的工资单结构,因为问题没有提供。
#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct PAYROLL
{
long emp_id;
char emp_name[32];
} PAYROLL;
static const char counter_bin[] = "counter.bin";
static const char records_bin[] = "records.bin";
static
void backUp(PAYROLL employee[], long int *pCounter)
{
FILE *counter = fopen(counter_bin, "wb");
if (counter != 0){
fwrite(pCounter, sizeof(long int), 1, counter);
fclose(counter);
}
else
fprintf(stderr, "Back up of counter failed! error: %d %s\n", errno, strerror(errno));
FILE *record = fopen(records_bin, "wb");
if (record != 0){
fwrite(employee, *pCounter *sizeof(PAYROLL), 1, record);
fclose(record);
}
else
fprintf(stderr, "Back up of records failed! error: %d %s\n", errno, strerror(errno));
}
static
void upload(PAYROLL employee[], long int *pCounter)
{
FILE *counter = fopen(counter_bin, "rb");
if (counter != 0){
size_t result = fread(pCounter, sizeof(long int), 1, counter);
fclose(counter);
if (result != 0)
printf("Counter: %ld\n", *pCounter);
else
fprintf(stderr, "Failed to read counter\n");
}
else
fprintf(stderr, "Upload up of counter failed!\n");
FILE *record = fopen(records_bin, "r+b");
if (record != 0)
{
size_t result2 = fread(employee, *pCounter * sizeof(PAYROLL), 1, record);
if (result2 == 1)
printf("Upload successful!\n");
else
fprintf(stderr, "Failed to read records!\n");
fclose(record);
}
else
fprintf(stderr, "Error opening file!");
}
int main(void)
{
PAYROLL emps[] =
{
{ 1066, "William the Conqueror" },
{ 1819, "Victoria" },
{ 1689, "William and Mary" },
};
for (int i = 1; i <= 3; i++)
{
long emp_count = i;
printf("Employee count = %ld\n", emp_count);
backUp(emps, &emp_count);
upload(emps, &emp_count);
for (int j = 0; j < emp_count; j++)
printf("%4ld: %s\n", emps[j].emp_id, emps[j].emp_name);
}
return 0;
}
请注意,我已经分解出文件名,这样您只需更改一行即可更改使用的文件。示例输出:
$ Employee count = 1
Counter: 1
Upload successful!
1066: William the Conqueror
Employee count = 2
Counter: 2
Upload successful!
1066: William the Conqueror
1819: Victoria
Employee count = 3
Counter: 3
Upload successful!
1066: William the Conqueror
1819: Victoria
1689: William and Mary
$ odx counter.bin
0x0000: 03 00 00 00 00 00 00 00 ........
0x0008:
$ odx records.bin
0x0000: 2A 04 00 00 00 00 00 00 57 69 6C 6C 69 61 6D 20 *.......William
0x0010: 74 68 65 20 43 6F 6E 71 75 65 72 6F 72 00 00 00 the Conqueror...
0x0020: 00 00 00 00 00 00 00 00 1B 07 00 00 00 00 00 00 ................
0x0030: 56 69 63 74 6F 72 69 61 00 00 00 00 00 00 00 00 Victoria........
0x0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0050: 99 06 00 00 00 00 00 00 57 69 6C 6C 69 61 6D 20 ........William
0x0060: 61 6E 64 20 4D 61 72 79 00 00 00 00 00 00 00 00 and Mary........
0x0070: 00 00 00 00 00 00 00 00 ........
0x0078:
$
(odx
只是一个十六进制转储程序。选择你自己的程序来做同样的工作——od -c
是一个后备方案,虽然我不是特别喜欢它的格式。)