How to overload cin and use getline - c++

I am trying to finish my lab, however I don't know how to allocate memory to a string. So I keep getting the error
warning: ‘_name’ is used uninitialized in this function [-Wuninitialized]
I don't also understand if my getline line is correct.
std::istream& operator>>(std::istream& is, Grade& RO){
int _mark;
char* _name;
std::cout<<"Subject name: ";
is.ignore();
is.getline(_name, (strlen(_name) + 1));
std::cout<<"Mark :";
is>> _mark;
RO=Grade(_name, _mark);
return is;
}

Ok #Jessica, (to general question and few info) I guess,
Grade is a class with two data members: int mark and string name. And you want to overload the insertion operator >> to populate these values.
(I recommend you leave all the cout expression outside this function). Here is one possible implementation:
istream& operator>> (istream& is, Grade& RO){
// declare local variables to insert the input values
int mark;
string name;
// extract values from input stream
is >> mark >> name;
// assuming you have member functions that set values for the object RO
RO.set_mark(mark);
RO.set_name(name);
return is;
}

Related

Reading File with Strings using overloaded input stream operator>>

I'm trying to get inputs from a file by overloading the istream operator. For that, I declared it as friend of a class. Then, I take as input that same class like this:
file >> *(class pointer);
When I'm trying to debug the part of my code that need this to work, it goes as expected into this:
istream& operator>> (istream& in, MYCLASS& n)
{
string buffer;
while (!in.eof()) { // input is a file
in >> buffer;
// do stuff
}
return in;
}
The problem is that the buffer stays empty ("") and does not take what it's suppose to be taking from the file. Normally, the format of the file should not be a problem since I'm using a similar method elsewhere in my code without a problem, but here it is in case:
* Name Age
* Name Age
* Name Age
...
What should I put inside my istream overload function so i get inputs as intended?
This...
while (!in.eof()) {
...is broken. You should attempt to read and parse data into your variables, then check for failure/eof. Do not assume that you'll necessarily be at the end of file after reading the last MYCLASS. Instead:
string name;
int age;
while (in >> name >> age)
...do stuff...
If you've really got some kind of leading dot on each line, add a char and read into it too:
char dot;
string name;
int age;
while (in >> dot && dot == '.' && in >> name >> age)
...do stuff...
More generally, it's not a very scalable model to assume the rest of the input stream will contain one MYCLASS object. You could instead have a delimiter (e.g. when the first word on a line is not a name, but <END>), that terminates the loop.

Using getline in an overloaded input operator

Book.h:
#ifndef BOOKDATE
#define BOOKDATE
#include <iostream>
#include <string>
class Book{
friend std::istream& operator>>(std::istream&, Book&);
private:
std::string title, author;
int number;
};
std::istream& operator>>(std::istream&, Book&);
#endif // BOOKDATE
Book.cpp:
#include "BookDate.h"
using namespace std;
istream& operator>>(istream& is, Book& rhs){
getline(is, rhs.title);
getline(is, rhs.author);
is >> rhs.number;
if(!is)
rhs = Book();
return is;
}
I was wondering how exactly I should approach creating the input operator for the Book class. The title and author will be more than one word, so it fits that I need to use getline to receive that data. The issue then with getline is that it may pick up any '\n' left in the stream since cin was last used. For instance;
int x;
cin >> x; //newline is not extracted and left behind
Book a;
cin >> a; //"title" is automatically made empty!
I could instead use cin.ignore(256, '\n') but whose responsibility, the user's or class author's, is it to use this? Does the user use .ignore before he inputs a Book object or does the class author put .ignore at the beginning of the input operation?
It seems that in the former case the user would have to understand an .ignore method is needed but in doing so has to understand the implementation of the Book's input operator, which is not desirable. In the latter case, putting .ignore in the operator means my operator may not adapt to certain circumstances, since it always expects to encounter a newline before processing. For instance reading from an input file with data such as:
book1
author1
1
book2
author2
2
Means book1 gets ignored by cin.ignore(256,'\n').
To make your operator>> behave more like the operators for the built in types, you can use the ws manipulator to skip whitespace before you read your input.
Just use
is >> ws;
at the beginning of your input operator, and the stream will be positioned at the first non-whitespace character after the current position.
To overload the extraction operator properly you can change your input format to be a sequence of three variables that you want to populate, namely:
(title, author, number)
and modify your operator>> to:
istream& operator>>(istream& is, Book& rhs){
// just a suggestion: it is better if there is no input to do nothing
if(!is) return is;
string title, author;
int number;
char par1, comma, par2;
cin >> skipws >> par1 >> title >> comma >> author>> comma >> number >> par2;
if (par1 != '(' || comma != ',' || par1 != ')'){
// set failbit to indicate invalid input format
is.clear(ios_base::failbit);
}
rhs(title, author, number);
return is;
}
put is.ignore(); before getline(is, rhs.title);

Parsing text file, same field has either 1 or 2 names

I have a text file of NFL teams. I am having a problem when parsing through the string when it comes to teams with 2 names and not one. (i.e. New England and Pittsburgh) the next item in the file is an int. I also have to read these values into a linked list.
infile >> t.date // t is a team struct which contains char name and ints
>> t.name
>> t.W
>> t.L
>> t.T
Can I just use an if else statement between the name and Wins to check if the next char is a char? And then if it is a char it could just save the next word, "England" for the second half of New England's name in the same name field, and if its an int it will move on to the Wins field.
txt file ex
New England 2 4 0
Pittsburgh 1 6 0
the code above was what I was trying to use to assign the name to the team struct
struct team
{
public:
team& do_input(std::istream& is);
std::string date, name, name2;
int wins,
losses,
ties;
std::string perc,
home,
road,
div,
conf;
int league;
};
infile >>t.date;
while (infile >> t)
{
t.do_input(infile) ;
//cout << t.date << t.name;
L.push_back(t);
t.name2 = " ";
}
Let's start by maintaining your code. The first thing I would do is create an overload of operator >> that takes an input stream and a team object.
std::istream& operator >>(std::istream& is, team& t);
This function should delegate the operation of extracting the input to a method called do_input():
std::istream& operator >>(std::istream& is, team& t)
{
if (is.good())
t.do_input(is);
return is;
}
do_input should read objects of type char into the respective string objects in your team class. Speaking of your team class, it's much better to use std::string for representation of string values:
struct team
{
...
std::string date;
std::string name;
int W, L, T;
};
This way the string can be as large enough as we need it. We no longer have to worry about a potential buffer overflow (i.e reading a string larger than 10 bytes). We can also use the convenient methods that std::string provides.
It's further recommended that you use good variable names so that maintainers of your code can know at a glance what it means. For instance, try these:
int wins, losses, ties;
Now it is clear to me (and to others) what these names imply.
So team::do_input is a member function that reads in the strings and integers from the file to the data members of the instance from which it is being called. Here's a full implementation:
struct team
{
public:
team& do_input(std::istream&);
private:
std::string date, name;
int wins, losses, ties;
};
team& team::do_input(std::istream& is)
{
std::getline((is >> date).ignore(), name);
is >> wins >> losses >> ties;
return *this;
}
Error reporting has been left out to keep the example concise. I hope this helped.

getline and passing input streams inside class functions, primary-expression error

I have a file called grades.txt with some lines of text and integers on it that i want to read into an already defined class ive created called Assignment.
int main()
{
ifstream input_file("grades.txt");
Assignment assignment;
input_file >> assignment;
return 0;
}
Above is my main function that will read input_file into the created class assignment.
friend istream& operator >> (istream& is, Assignment& assignment)
{ // function to read in data to class variables
string line;
getline(*****, line);
// to be able to operate on strings
istringstream iss(line);
// set values read in from input file.
iss >> assignment.Assignment_type;
iss >> assignment.Date;
iss >> assignment.Max_score;
iss >> assignment.Actual_score;
// sometimes Assignment Name will have spaces, have to use getline()
getline(is, assignment.Assignment_name);
return is;
}
Heres the class function that will overload the >> operator to read into each of the variables in assignment. the group of stars is what im having problems with, i dont know what to pass to it. I've tried ifstream and ofstream thinking it was that easy but they return the same error code
P01.cpp:34:21: error: expected primary-expression before ‘,’ token
I guess, you defined these operator >> inside the class Assignment. Only declare it as friend, but put the definition somewhere out: it is not a member of Assignment. The error is telling you that Operator >> take only one argument when defined as a member (the right operand, becouse the link is this).
Als "namespace" or global function it accept two arguments: link and right.

Returning a reference to istream in C++

I read this on Accelerated C++. Here is a simplified version.
istream& read_hw(istream& in, Student_info& s)
{
in >> s.name >> s.midterm >> s.final;
return in;
}
Then, we can call the function as:
Student_info s;
read_hw(cin, s);
My question is,
What's the point of returning the reference to istream? Since both the two parameters are passed by reference;
While calling the function, we don't seem to care about the returning value
You should read the next paragraph:
Returning the stream allows our caller to write
if (read_hw(cin, homework)){/*...*/}
as an abbreviation for
read_hw(cin, homework);
if (cin) {/*...*/}
Returning the reference to istream enables cascading. For example:
int i, j;
std::cin >> i >> j;
// Equivalent to std::cin.operator>>(i).operator>>(j);
istream::operator>>() returns istream& so that the cascaded >> works.