简体   繁体   English

用C写入文件时不需要的字符

[英]Unwanted characters when writing to file in C

The program asks for input from the user and writes it to a .dat file. 该程序要求用户输入并将其写入.dat文件。 The input is the name, ID, date of birth, gender and marital status of a specified number of students. 输入的是指定数目学生的姓名,ID,出生日期,性别和婚姻状况。 The data must be written as individual fields to the file so that the it can be read from the file later on. 数据必须作为单独的字段写入文件,以便以后可以从文件中读取。

Say this is the input from the terminal: 说这是来自终端的输入:

For student 1 对于学生1
Enter name: John Doe 输入姓名:John Doe
Enter ID: 1234 输入ID:1234
Enter date of birth: 01/01/90 输入出生日期:01/01/90
Enter gender: Male 输入性别:男
Enter marital status: Single 输入婚姻状况:单身

For student 2 对于学生2
Enter name: Jane Smith 输入名称:Jane Smith
Enter ID: 5678 输入ID:5678
Enter date of birth: 09/08/92 输入生日:09/08/92
Enter gender: Female 输入性别:女
Enter marital status: Single 输入婚姻状况:单身

This is the output in the file. 这是文件中的输出。

John Doe\\00\\00\\00\\00\\00\\00\\00\\00\\00\\00\\001234\\00\\00\\00\\00\\00\\0001/01/90\\00\\C2Male\\00Single\\00\\FF\\FF\\FFJane Smith\\00\\C2\\FF\\00\\00\\00\\00\\00\\005678\\00\\00\\00\\00\\00\\0009/08/92\\00Female\\00Single\\00\\C2\\FF 约翰·多伊(John Doe)\\ 00 \\ 00 \\ 00 \\ 00 \\ 00 \\ 00 \\ 00 \\ 00 \\ 00 \\ 00 \\ 00 \\ 001234 \\ 00 \\ 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

I guess the characters such as \\00, etc. appear because, for each array element, I am writing more bytes to the file than the array element contains; 我猜出现了诸如\\ 00之类的字符,因为对于每个数组元素,我向文件中写入的字节数比数组元素包含的字节数多。 but I need each data in the file to be of fixed size so that it can be read individually from the file later on, right? 但是我需要文件中的每个数据都具有固定大小,以便以后可以从文件中单独读取,对吗? How can I do this, please? 请问我该怎么做?

#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);
    }
}
 scanf("%s", &id[i][10]); //you want to store string but id[i][10] can store single char at index [i][10].

This statement should be - 该声明应为-

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

Similare for these scanf 's 这些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]);

And the write statement's should be like this - write语句应该是这样的-

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

Similarly for other statements. 其他语句也是如此。

Why don't you write the exact length of each data terminated by '\\n' or any other separator and when you have to read the file you read all of it and then split the data read around the chosen separator, or you split it every time you have read the separator? 为什么不写以'\\ n'或任何其他分隔符结尾的每个数据的确切长度,当您必须读取文件时,先读取所有文件,然后将读取的数据拆分为选定的分隔符,或者拆分每次阅读分隔符时?

You won't know the exact length to read but you won't have unwanted character. 您将不知道要读取的确切长度,但不会有多余的字符。 You just have to read in a loop until you reach the end of the file. 您只需要循环阅读,直到到达文件末尾。

You're not reading and writing the fields properly. 您没有正确读写字段。

For example, when you're reading in name : 例如,当您以name阅读时:

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

You're actually passing in the address of one character past the last character in the array, not the address of the first character. 实际上,您传入的是一个字符的地址,而不是第一个字符的地址。 That's done like this: 这样完成:

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

Similarly for the write call: 对于write调用类似:

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

You want to pass in the address of the first character of the array. 您要传递数组第一个字符的地址。 Also, you use the sizeof operator to pass in the size of each array rather than using numeric literals: 另外,您可以使用sizeof运算符来传递每个数组的大小,而不是使用数字文字:

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

Do the same for all other fields. 对所有其他字段执行相同的操作。

You'll be writing the full size of each array, whether or not there's useful data there, but that's OK. 无论那里是否有有用的数据,您都将写出每个数组的完整大小,但这没关系。 You would just read it the full array in a similar manner. 您将以类似的方式读取整个阵列。 Also, since each element is a fixed size, it makes it easier to jump to a specific record. 此外,由于每个元素的大小都是固定的,因此可以轻松跳转到特定记录。 You wouldn't be able to do that if the records were a variable size in the data file. 如果记录是数据文件中的可变大小,则您将无法执行此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM