-1

Ok more code as asked.

int serialize_students(const Student *studArray, const int arrLength)
{
    FILE *ptr_file;
    int i=0;

    ptr_file =fopen("output.txt", "w");

    if (!ptr_file)
        return -1;

    for (i=0; i<arrLength; i++)
    {
        fprintf(ptr_file,"%d\n", studArray[i].id);
        fprintf(ptr_file,"%s\n", studArray[i].name);
        fprintf(ptr_file,"%d\n", studArray[i].gender);

    }

    fclose(ptr_file);
    return 0;
}

int deserialize_students(Student *dest, const int destCapacityMax)
{
    FILE *ptr_file;
    int i=0;


    ptr_file =fopen("output.txt","r");
    if (!ptr_file)
        return -1;

    if(destCapacityMax==0)
        return -2;

    while (!feof (ptr_file))
    {  
        fscanf (ptr_file, "%d", &dest[i].id);    
        fscanf (ptr_file, "%s",  dest[i].name);     
        fscanf (ptr_file, "%d", &dest[i].gender);      
        i++;

        if(i==destCapacityMax)
            return 0;

    }


    fclose(ptr_file);
    return 0;
}

void print_student(Student student)
{
    printf("id: %d\n", student.id);
    printf("name: %s\n", student.name);
    printf("gender: %d\n", student.gender);
}

void print_students(const Student *studArray, const int arrLength)
{
    int i = 0;
    for(i =0; i<5;i++)
    {
        print_student(studArray[i]);
    }
}

main

typedef struct student
{
    int id;
    char name[100];
    int gender;
}Student;

int main()
{
    int i = 0;
    Student dest[5];
    Student students[5];
    memset(dest,0,sizeof(dest));
    memset(students,0,sizeof(students));


    /* Initialize students */
    /*for(i = 0; i<5; i++)
    {
        students[i].id = i;
        strcpy(students[i].name,arr[i]);
        students[i].gender = MALE;
    }*/

    /*Serialize*/
    serialize_students(students,5);

    /* Reconstruct student array from file */
    deserialize_students(dest, 5);

    /* Print reconstructed array of students */
    print_students(dest,5);

    return 0;

}

My question is: see how the data is written in file, and see how it is printed on console? Why they differ? Why only first three values of name show 0? but other two empty?

This is how file looked like

enter image description here

This is console output:

enter image description here

2 Answers2

0

To simply answer your question "Does fscanf return ASCII '0' when reading empty string?", no, it does not return ASCII zero. It returns the number of fields successfuly read (or EOF in the case of a read error or end-of-file). Since it didn't read any fields from an empty string, it returns integer 0.

For your other question parts I need the print function. But probably, you forget to skip the terminating whitespace (\n) after reading a field.

EDIT: Funny....I copied your source into my VC2008 and it ran pefectly. I did not add spaces to the format specifications (which would skip newlines and other whitespace) and fscanf just ignored the newlines. I checked the Microsoft documentation and it didn't say anything about that - it shouldnt skip the newlines, but it did. I added a space before and later also after each format specifier to ignore whitespace still in the buffer and that didn't make any difference. I dumped the output and there were neat 0x0D, 0x0A CR/LF pairs terminating each line. Anyone any suggestions? Or is this a Microsoft anomaly?

EDIT: User Freenode-Boston Seb quotes a scanf manual from IEEE stating "Input white-space characters (as specified by isspace) shall be skipped, unless the conversion specification includes a [, c, C, or n conversion specifier." That holds here, so according to this manual your code is fine.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
  • It returns the number of fields successfuly read (or `EOF` in the case of a read error or end-of-file). – autistic Aug 21 '15 at 09:44
  • In your posted code, you commented out the initialization. I put it back in for my testing and the results are fine. If you don't have a proper `output.txt` file anymore, then the results you read will be wrong and so your new `ouput.txt` and console output too. – Paul Ogilvie Aug 22 '15 at 16:00
0

According to the scanf/fscanf manual,

Input white-space characters (as specified by isspace) shall be skipped, unless the conversion specification includes a [, c, C, or n conversion specifier.

In other words, prior to your %d and %s reads, as much whitespace will be read and discarded as possible.

It's important to realise that these do not read empty fields! The empty fields that you perceive will be discarded as they are parts of streams of whitespace.

scanf and fscanf aren't really ideal for line-by-line input. They're more suitable for field-by-field input, %s denoting a word that is separated by whitespace (and isn't empty) and %d denoting a sequence of decimal digit characters, possibly with a leading sign character (and isn't empty).

This will explain why you see string fields that contain 0, 1, 42 or whatever other decimal digit sequences you intended to fall into the int variables.

Perhaps, if you would spend more time reading and understanding the manuals for functions before you use them, you might have this particular kind of problem, relating to guessing how a function is used, less often in the future...

P.S. Don't forget to check the return value.

autistic
  • 1
  • 3
  • 35
  • 80
  • @userq The ten fields in the file are all 0, "0", 0, 0, "0", 0, 0, "0", 0, 0... I'm not sure how I can more clearly explain this: *`%s` does not read blank fields; it **skips** them*! This is consistent with `%d`, too; `%s` skips all leading whitespace before reading a *non-blank* field! In fact, for that reason you don't need the `\n` directive in this code. – autistic Aug 21 '15 at 11:24
  • @userq Question: What if you use 42 in place of 0? What happens, then? Feel free to try it and see... – autistic Aug 21 '15 at 11:52
  • @userq What makes you think I was *shout*ing? If I were so angry as to *shout*, for a start you're not in my immediate vicinity so you probably wouldn't hear me... Additionally, I wouldn't bother leading you in a positive direction; I'd probably insult and swear at you. I would suggest that like most people (myself included), you aren't so good at inferring emotions from text (hence why I don't do it). Please stop inventing your own emotional tone from my writings, or I might have to demonstrate how annoying that can be by inventing emotional tone from your writings. Doesn't that seem fair? – autistic Sep 01 '15 at 14:18