用C读写二进制文件

时间:2020-05-22 14:44:50

标签: c pointers scanf binaryfiles file-pointer

这些是2个单独的应用程序。

  • 在第一个例子中,我试图将员工的详细信息(例如姓名,年龄和薪水)存储在名为emp.bin的二进制文件中。
  • 在第二个应用程序中,我尝试查看文件的内容,但是代替名称,仅出现第一个字符。

我尝试单独打印每个字符,结果发现名称中每个字母后面有3个空字符'\ n',这就是为什么它不打印第一个字符之后的原因。

“写入”应用程序代码:

//Receives records from keyboard and writes them to a file in binary mode
#include <stdio.h>

int main()
{
    FILE *fp;
    char another = 'Y';
    struct emp
    {
        char name[40];
        int age;
        float bs;
    };
    struct emp e;
    fp = fopen("emp.bin", "wb");
    if (fp == NULL)
    {
        puts("Cannot open the file.");
        return 1;
    }
    while(another == 'Y')
    {
        printf("Enter the employee name, age and salary: ");
        scanf("%S %d %f", e.name, &e.age, &e.bs);
        while(getchar() != '\n');
        fwrite(&e, sizeof(e), 1, fp);
        printf("Add another record? (Y/N)");

        another = getchar();
    }
    fclose(fp);
    return 0;
}

“读取”应用程序代码:

//Read records from binary file and displays them on VDU
#include <stdio.h>
#include <ctype.h>

int main()
{
    FILE *fp;
    struct emp
    {
        char name[40];
        int age;
        float bs;
    } e;
    fp = fopen("emp.bin", "rb");
    if (fp == NULL)
    {
        puts("Cannot open the file.");
        return 1;
    }
    while (fread(&e, sizeof(e), 1, fp) == 1)
    {
        printf("\n%s \t %d \t $%.2f\n", e.name, e.age, e.bs);
    }
    fclose(fp);
}

这是输入和输出:

enter image description here enter image description here

我该如何更正此代码以使其打印出全名?

2 个答案:

答案 0 :(得分:3)

即使在执行实际写入之前,问题出在“ writer” 应用程序中。

当您从用户那里获取数据时

scanf("%S %d %f", e.name, &e.age, &e.bs);

您使用格式%S(大写字母“ S”。格式说明符区分大小写!)。正如我们在printf man page

中所读

S
(不是在C99中,而是在SUSv2中。)ls的同义词。不要用

这导致我们进入%ls格式说明符,该说明符的描述方式如下

s
[...]如果存在l修饰符:const wchar_t *参数应该是指向宽字符数组的指针。数组中的宽字符将转换为多字节字符

关于Windows source,我们有:

S
相反大小的字符串,最多第一个空格字符(空格,制表符或换行符)。 [...]
scanf函数一起使用时,表示宽字符数组;与wscanf函数一起使用时,表示单字节字符数组[...]

因此,基本上,您是从 stdin 中读取字符并将其转换为宽字符。在这种情况下,每个字符都占sizeof(wchar_t)。在您的系统中,此大小可能是4。


您需要的只是%s格式说明符。而且由于您的name数组的大小为40,所以建议使用

scanf("%39s", e.name );

从用户那里获取名称。这样,最多可以写入39个字符,这是字符串终止符 '\0'保留的第40个字符。

答案 1 :(得分:0)

罗伯托在回答中指出,问题在于%S转换说明符,这是一个错字,您应该使用%s

但是请注意,还有其他问题可能会引起问题:

  • 您应该告诉scanf()读取雇员姓名的最大字符数,否则如果输入太长,scanf()可能会写到目标数组末尾。

  • 如果两个程序都在具有不同字节序的单独系统上运行,则数字在接收端将不正确,因为它们的字节将以相反的顺序存储。因此,应在二进制文件中指定字节序并进行显式处理。文本格式通常是数据传输的首选。

这是修改后的版本:

//Receives records from keyboard and writes them to a file in binary mode
#include <stdio.h>

int main() {
    FILE *fp;
    char another = 'Y';
    struct emp {
        char name[40];
        int age;
        float bs;
    } e;
    int c;

    fp = fopen("emp.bin", "wb");
    if (fp == NULL) {
        puts("Cannot open the file.");
        return 1;
    }
    while (another == 'Y') {
        printf("Enter the employee name, age and salary: ");
        if (scanf("%39s %d %f", e.name, &e.age, &e.bs) != 3)
            break;
        while ((c = getchar()) != EOF && c != '\n')
            continue;
        if (fwrite(&e, sizeof(e), 1, fp) != 1)
            break;
        printf("Add another record? (Y/N)");
        another = getchar();
    }
    fclose(fp);
    return 0;
}

“读取”应用程序代码:

//Read records from binary file and displays them on VDU
#include <stdio.h>
#include <ctype.h>

int main() {
    FILE *fp;
    struct emp {
        char name[40];
        int age;
        float bs;
    } e;
    fp = fopen("emp.bin", "rb");
    if (fp == NULL) {
        puts("Cannot open the file.");
        return 1;
    }
    while (fread(&e, sizeof(e), 1, fp) == 1) {
        printf("\n%s \t %d \t $%.2f\n", e.name, e.age, e.bs);
    }
    fclose(fp);
    return 0;
}