我只是在第一次运行程序时才读书

时间:2015-03-21 19:04:51

标签: c arrays struct fwrite fread

当我第一次运行时,我会添加3条记录,这给我一个3的计数。然后我fwrite计数到一个bin文件,并将记录转换成bin文件,然后我关闭程序。 / p>

当我重新打开它然后我fread时,它会给我3条记录和3条计数。但是从那里开始,无论我是否备份或者在我读书时,都会给我同样计数3和3记录,但由于计数没有更新,这可能是fread只在第一次记录中读取的原因。

我不知道为什么计数器没有更新。 freadfwrite都返回=成功,所以我不确定是什么。

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!");
}

2 个答案:

答案 0 :(得分:1)

我在你的程序中看到很多错误。

首先,您将长整数和PAYROLL结构直接写入文件。你永远不应该这样做,因为结构和整数具有依赖于机器的表示,如果你在一台机器上写文件(比如32位机器)并在另一台机器上读取它们(让我们说64位机器)那么你可能会遇到问题。

其次,您没有检查fread()的返回值。应该经常检查。

第三,您将fread()的返回值分配给errno_t。你确定你真的想这么做吗?

如果您想获得实际问题的答案,请考虑更新源代码以修复我指出的错误,并考虑改进您的问题中的英语。此外,您应该提供一个完整的示例,即包含PAYROLL定义的示例。当您知道fread()的实际返回值时,可能会更容易追踪问题。

答案 1 :(得分:1)

将最突出的评论转移到答案中。

Weathervane commented

  

您如何知道freadfwrite正在回归"成功"当你还没有检查他们的返回值时?

Jude评论道:

  

我查看调试器并进入函数,结果是给我成功返回值(如果它是如何工作的那样)。

Weathervane commented

  

你仍然需要在程序中。如果没有那种检查,你的代码就会被一阵风吹过。

Dmitri正确observed

  

看起来你在追加模式中打开的所有地方" a + b"你可能应该使用别的东西(" rb"在upload()和" wb"在backUp()中可能?)

Jude评论道:

  

我不明白,是否有特定的错误检查功能?因为我一直认为错误检查只是看结果的价值,然后我可以去检查一下这个值意味着什么?

查看fread()的规范 fwrite()。它们返回写入或读取的记录数,可能少于请求的数量。如果你得到一个简短的写,那么你有一个问题 - 可能没有磁盘空间。如果你得到一个简短的阅读,可能是你要求100条记录,但只有1或10或99可供阅读(或有错误)。如果您没有捕获并检查返回值,您就不知道发生了什么。

Jude评论道:

  

我看到他们读写1,但它仍然存储了我的struct数组的前3个元素。我认为它是一个因为它只编写我的数组?

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是一个后备,但我并不特别喜欢它的格式化。)