【问题标题】:Unwanted characters when writing to file in C在 C 中写入文件时不需要的字符
【发布时间】:2015-09-15 17:16:34
【问题描述】:

程序要求用户输入并将其写入 .dat 文件。输入是指定数量学生的姓名、ID、出生日期、性别和婚姻状况。数据必须作为单独的字段写入文件,以便以后可以从文件中读取。

假设这是来自终端的输入:

学生 1
输入姓名:John Doe
输入 ID:1234
输入出生日期:01/01/90
输入性别:男
输入婚姻状况:单身

对于学生 2
输入姓名:简·史密斯
输入 ID:5678
输入出生日期:09/08/92
输入性别:女
输入婚姻状况:单身

这是文件中的输出。

John Doe\00\00\00\00\00\00\00\00\00\00\001234\00\00\00\00\00\0001/01/90\00\C2Male \00单人\00\FF\FF\FF简·史密斯\00\C2\FF\00\00\00\00\00\005678\00\00\00\00\00\0009/08/92\00女\00单人\ 00\C2\FF

我猜出现\00等字符是因为,对于每个数组元素,我向文件写入的字节数比数组元素包含的要多;但我需要文件中的每个数据都是固定大小的,以便以后可以从文件中单独读取,对吧?请问我该怎么做?

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(){
    int fd, i = 0;
    char name[2][20], id[2][10], dob[2][10], gender[2][7], status[2][10];
    fd = open("file.dat", O_WRONLY|O_CREAT); //open file.dat for writing; if it does not exist, create it.
    //get input from user
    for (i = 0; i < 2; i++){
        printf("\nFor student %d\n", (i + 1));
        printf("Enter name: ");
        scanf("%[^\n]%*c", &name[i][20]); //%[^\n]%*c - read everything up to (excluding) new line character
        printf("Enter ID: ");
        scanf("%s", &id[i][10]);
        printf("Enter date of birth: ");
        scanf("%s", &dob[i][10]);
        printf("Enter gender: ");
        scanf("%s", &gender[i][7]);
        printf("Enter marital status: ");
        scanf("%s", &status[i][10]);
        getchar();
    }

    for (i = 0; i < 2; i ++){
        write(fd, (void*)&name[i][20], 20);
        write(fd, (void*)&id[i][10], 10);
        write(fd, (void*)&dob[i][10], 10);
        write(fd, (void*)&gender[i][7], 7);
        write(fd, (void*)&status[i][10], 10);
    }
}

【问题讨论】:

  • 你应该写strlen(&amp;name[i][20])字节而不是固定值。 20 应该是 0
  • 您不清楚文件的格式。向你自己描述你想要的内容是什么(以及如何读回它),然后你就可以弄清楚如何编写它

标签: c file


【解决方案1】:

为什么不写下每个以 '\n' 或任何其他分隔符结尾的数据的确切长度,当您必须读取文件时,您读取所有文件,然后将读取的数据拆分为所选分隔符,或者你每次读完分隔符就拆分它?

您不会知道要阅读的确切长度,但不会有不需要的字符。您只需循环读取,直到到达文件末尾。

【讨论】:

    【解决方案2】:
     scanf("%s", &id[i][10]); //you want to store string but id[i][10] can store single char at index [i][10].
    

    这句话应该是-

     scanf("%9s",id[i]);
    

    这些scanf 的相似之处

                                       // CORRECTIONS 
     scanf("%[^\n]%*c", &name[i][20])  //->   scanf("%19[^\n]%*c",name[i])
     ...
     scanf("%s", &dob[i][10]);         //->   scanf("%9s", dob[i]);
     ...
     scanf("%s", &gender[i][7]);       // ->  scanf("%6s", gender[i]); 
     ...
     scanf("%s", &status[i][10]);      //->   scanf("%9s", status[i]);
    

    write 语句应该是这样的 -

    write(fd, (void*)&id[i][10], 10);   //-> write(fd,id[i],sizeof id[i]);
    

    其他语句也是如此。

    【讨论】:

      【解决方案3】:

      您没有正确读取和写入字段。

      例如,当你在name阅读时:

      scanf("%[^\n]%*c", &name[i][20]);
      

      您实际上是在传递数组中最后一个字符之后的一个字符的地址,而不是第一个字符的地址。这样做是这样的:

      scanf("%[^\n]%*c", name[i]);
      

      write 呼叫也是如此:

      write(fd, (void*)&name[i][20], 20);
      

      你想传入数组第一个字符的地址。此外,您使用 sizeof 运算符来传递每个数组的大小,而不是使用数字文字:

      write(fd, name[i], sizeof(name[i]));
      

      对所有其他字段执行相同操作。

      您将写入每个数组的完整大小,无论那里是否有有用的数据,但这没关系。您只需以类似的方式阅读完整的数组即可。此外,由于每个元素都是固定大小的,因此更容易跳转到特定记录。如果记录在数据文件中是可变大小的,您将无法做到这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-15
        • 2011-11-09
        • 1970-01-01
        • 1970-01-01
        • 2019-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多