Reading a file and ignoring whitespace

how can you able to convert video.movieTitle, video.movieGenre and video.movieProduction into a string. I test my program but it only reads the line and ignore whitespace.

while((infile,"%dn",&p->video.videoID),
    fscanf(infile,"%sn",p->video.movieTitle.c_str()),
    fscanf(infile,"%sn",p->video.movieGenre.c_str()),
    fscanf(infile,"%sn",p->video.movieProduction.c_str()),
    fscanf(infile,"%dn",&p->video.numberOfCopies))

my file contains:

101

Raya and the Last Dragon

Animation

Walt Disney Studio

6

102

Captain America: The First Avenger

Adventure 

Marvel

1

Answer

As others have commented, fscanf is the wrong tool for this job. Even in C, using fscanf with the %s conversion would still be the wrong tool1.

As it stands now, your first fscanf will read and convert the first number (the video ID) correctly. But fscanf‘s %s conversion reads only a single, white-space delimited string, so the first one reads Raya and puts that into the video title. The second reads and, and puts that into the video genre. The third reads “the” and puts that into the production. Then the last tries to read the number of copies, but what it sees in the input buffer is Last, which won’t convert to a number–so conversion fails. From there, nothing else stands any chance of working at all.

In this case, each of the strings occupies an entire line (with possible embedded spaces) so we want to read an entire line, not a single white-space delimited string. In C, we’d typically use fgets instead of fscanf for this job, and in C++ we normally want to use std::getline (though you can use fscanf with the scanset conversion like %[^n], if you really want to).

There is one more bit that gets a little clumsy with a file format like this that has numbers mixed in with character strings. If you get a little careless about how you read the numbers, you can end up reading the number itself, but leaving the new-line immediately following the number in the input buffer. Then when you try to read the string on the next line, you actually end up reading an empty string at the end of the line that had the number on it. Then your code gets out of sync with the actual file, and doesn’t work.

As a rule, I tend to deal with this by always reading an entire line at a time for the input file, then where I need a number, taking the string I read, and converting it to a number. This makes it much easier to assure that your reading stays in sync with the file format.


1. Note that `fscanf` using `%s` without specifying a maximum string length is inherently dangerous as well–if you’re going to use it at all, at bare minimum you need to specify a maximum length. You also need to read into a normal array of char, not directly into a string (thus the advice to just avoid it completely in C++).