#Reading and parsing the contents of the given input stream
57 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
#include "customparser.h"
#include <iostream>
#include <sstream>
using namespace std;
const char* error_msg_1 = "Cannot read integer n";
const char* error_msg_2 = "Error in content parsing";
const char* error_msg_3 = "Error in user parsing";
// To Do - Complete this function
void CustomFormatParser::parse(std::istream& is, std::vector<Content*>& content, std::vector<User*>& users)
{
// Erase any old contents
content.clear();
users.clear();
// TO DO - Add your code below.
int n;
if(!(is >> n))
throw ParserError(error_msg_1);
for(int i = 0; i < n; i++)
{
int id, type, reviews, stars, rating ;
std::string name;
is >> id >> type;
cout << id << " " << type;
if(is.fail())
throw ParserError(error_msg_2);
std::getline(is >> std::ws, name);
if(!(is >> reviews >> stars >> rating))
throw ParserError(error_msg_2);
std::string viewerLine;
std::getline(is >> std::ws, viewerLine);
std::istringstream viewerStream(viewerLine);
std::string viewer;
std::vector<std::string> viewers;
while(viewerStream >> viewer)
viewers.push_back(viewer);
if(type == 0)
{
content.push_back(new Movie(id, name, reviews, stars, rating));
}
else if(type == 1)
{
int episodes;
if(!(is >> episodes))
throw ParserError(error_msg_2);
content.push_back(new Series(id, name, reviews, stars, rating, episodes));
}
else
{
throw ParserError(error_msg_2);
}
}```
while(std::getline(is >> std::ws, userLine))
{
if(userLine.empty())
break;
std::istringstream userStream(userLine);
std::string username;
int ratingLimit;
if(!(userStream >> username >> ratingLimit))
throw ParserError(error_msg_3);
std::string historyLine;
std::getline(is >> std::ws, historyLine);
std::istringstream historyStream(historyLine);
int contentID;
std::vector<int> history;
while(historyStream >> contentID)
{
history.push_back(contentID);
}
users.push_back(new User(username, ratingLimit));
}
}```
This is my code
Here is the .cus file for input:
3
0 0
Black Panther: Wakanda Forever
4
18
3
user2 user3
1 1
Stranger Things 1
3
13
3
8
user1 user2
2 1
Stranger Things 2
2
5
4
9
user2 user3
user1 3
1
user2 4
0 1 2
user3 4
0 2
You've commented out the code that reads into type but you're still using type
When it's uncommented the issue is still there, my bad
The file for input doesn't match what you're reading tho
Like where is the leading 'n'
Also your didn't say what error is being given. But it'd be simplest for you to just debug and look at variable values close to where it's going wrong
I did the with 3 hidden inside, my bad again 😭
This was the error I was given:
Parsing data1.cus with your custom parser should not throw. It does.
cusparse-gtest.cpp:389: Failure
Value of: compareContents(expContent, actContent, expContentTypes)
Actual: false (Expected parsed Content pointer vector size to be 3 but actual size was 1
Look at how many type numbers you handle
Oh nm, I got type and id mixed up
Not sure just from looking at. You should debug
I don't think your episode parsing and viewers parsing are ordered correctly
What do you mean?
How do I loop through the viewers after parsing episodes?
I might be getting the names wrong, but on the first movie you need to read those three numbers 4 18 3.
For the stranger things chunk you should read 4 numbers but you only read 3
I see, I think I should have given the .json file instead 😭
"content" : [
{
"id" : 0,
"type" : 0,
"name" : "Black Panther: Wakanda Forever",
"reviews" : 4,
"stars" : 18,
"rating" : 3,
"viewers" : ["user2", "user3"]
},
{
"id" : 1,
"type" : 1,
"name" : "Stranger Things 1",
"reviews" : 3,
"stars" : 13,
"rating" : 3,
"episodes" : 8,
"viewers" : ["user1", "user2"]
},
{
"id" : 2,
"type" : 1,
"name" : "Stranger Things 2",
"reviews" : 2,
"stars" : 5,
"rating" : 4,
"episodes" : 9,
"viewers" : ["user2", "user3"]
}
],
"users" : [
{
"uname" : "user1",
"limit" : 3,
"viewed" : [1]
},
{
"uname" : "user2",
"limit" : 4,
"viewed" : [0, 1, 2]
},
{
"uname" : "user3",
"limit" : 4,
"viewed" : [0, 2]
}
]
}
It shows like where each content is being read into
But 3 would be correct
Not for episodes
The first content is Black Panther and it's a movie, so 4 18 3 would be right because there are no episodes in a movie
Yeah, but you do the same thing for the TV show
And the next line you try to read as viewers
But it's the episode number
The only thing different about the movie and series is that series has episodes
So that's why I read episodes right before pushing back the content
But it's not the right order
The Movie and Series objects don't have viewers inside of them though
So?
{
public:
/**
* @brief Construct a new Movie object
*
* @param id Content ID
* @param name Content name (spaces are fine)
* @param nr Number of reviews
* @param ts Total stars of all reviews
* @param rating Parental control rating
*/
Movie(int id, std::string name, int nr, int ts, int rating);
/**
* @brief Destroy the Movie object
*
*/
~Movie();
/// Add an override of the Content::display function,
/// if you deem it necessary
protected:
// Do not alter this line
const char** ratingStrings() const;
private:
// Add more data members if you deem it necessary
};
class Series : public Content {
public:
/**
* @brief Construct a new Series object
*
* @param id Content ID
* @param name Content name (spaces are fine)
* @param nr Number of reviews
* @param ts Total stars of all reviews
* @param rating Parental control rating
* @param numEpisode Numer of episodes in the series
*/
Series(int id, std::string name, int nr, int ts, int rating, int numEpisodes);
/**
* @brief Destroy the Series object
*
*/
~Series();
/**
* @brief Accessor / getter to return the number of episodes in the series
*
* @return int
*/
int numEpisodes() const;
/// Add an override of the Content::display function,
/// if you deem it necessary
virtual void display(std::ostream& ostr) const override;
protected:
// Do not alter this line
const char** ratingStrings() const;
private:
// Add data members as needed
int numEpisodes_;
};```
You still need to find the correct data in the file for 'episodes'
Ok, but do you know why it might throw before that because I've commented out everything but the if(!(is >> id >> type)... throw, and it throws from there even though they are being read in correctly?
If you just randomly comment out things then it will break more, yes
I commented out everything after that throw and ended the for loop, I used the test we were given and received the same error as I am now, which is that the vector size is incorrect
I don't know how many different ways to say you're reading the data in the wrong order
std::getline(is >> std::ws, viewerLine);
std::istringstream viewerStream(viewerLine);
std::string viewer;
std::vector<std::string> viewers;
while(viewerStream >> viewer)
viewers.push_back(viewer);```
So this block of code, it should go after I read episodes?
Yes. But reading episodes is conditional.
So after the if statements?
I'll leave you to think about it
There is an alternative way to write this - make a separate parse function for movie/TV then you don't have if checks all over the place
I'm not allowed to do that for this assignment
Ok thank you for your help
Now I just have to figure out the wrong content values parsed lol
You're not allowed to make your own functions?
Yeah 😭
Are you sure you're just not allowed to change the interface?
We're only supposed to use the functions they give us in the skeleton code
Well at least you're allowed to use vector
True
@ashen urchin Has your question been resolved? If so, type !solved :)
!solved