Saiyan
Saiyan

Reputation: 197

Unwanted characters when writing to file in C

The program asks for input from the user and writes it to a .dat file. The input is the name, ID, date of birth, gender and marital status of a specified number of students. 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
Enter name: John Doe
Enter ID: 1234
Enter date of birth: 01/01/90
Enter gender: Male
Enter marital status: Single

For student 2
Enter name: Jane Smith
Enter ID: 5678
Enter date of birth: 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

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

Upvotes: 1

Views: 1742

Answers (3)

ameyCU
ameyCU

Reputation: 16607

 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

                                   // 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(fd, (void*)&id[i][10], 10);   //-> write(fd,id[i],sizeof id[i]);

Similarly for other statements.

Upvotes: 1

dbush
dbush

Reputation: 224892

You're not reading and writing the fields properly.

For example, when you're reading in 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(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:

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.

Upvotes: 0

epicanriome
epicanriome

Reputation: 21

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?

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.

Upvotes: 1

Related Questions