Reputation: 3
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,"%d\n",&p->video.videoID),
fscanf(infile,"%s\n",p->video.movieTitle.c_str()),
fscanf(infile,"%s\n",p->video.movieGenre.c_str()),
fscanf(infile,"%s\n",p->video.movieProduction.c_str()),
fscanf(infile,"%d\n",&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
Upvotes: 0
Views: 86
Reputation: 2225
Setup and test input
#include <sstream>
#include <iostream>
using namespace std; // For readability on so
// Your example input
const char* testString = R"_(
101
Raya and the Last Dragon
Animation
Walt Disney Studio
6
102
Captain America: The First Avenger
Adventure
Marvel
1
)_";
How to read a single non empty line
namespace {
// Read a single non empty line
// return "" if file is not good anymore
std::string line(std::istream &stream) {
if (stream) {
string s;
while (stream && s.empty()) { // Skip empty lines
getline(stream, s);
}
return s;
}
return {};
}
} // namespace
Then use it in your function like this
int main(int, char**) {
auto file = istringstream{testString}; // example
// auto file = ifstream{filename} // real implementation, use this
// Loop as long as you can get
for (auto s = line(file); !s.empty(); s = line(file)) {
auto videoId = stoi(s); // convert string to int
auto title = line(file);
auto genre = line(file);
auto production = line(file);
auto copies = stoi(line(file));
// Verify output
cout << videoId << ", "
<< title << ", "
<< genre << ", "
<< production << ", "
<< copies << "\n";
}
}
Upvotes: 0
Reputation: 490098
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.
Upvotes: 3