Overloading global function getline in a c++ class - c++

I'm working on a school project to implement a c++ class for polynomials. Something my class is supposed to do is read polynomials from standard in, or from a file. I thought about overloading >> until I read the following on my favorite c++ reference site:
Notice that the istream extraction operations use whitespaces as
separators, therefore this operation will only extract what can be
considered a word from the stream. To extract entire lines of text,
refer to the string overload of global function getline.
This got me all inspired to overload the global function getline for my polynomial class so that it can read whole lines from a file. There are lots of tutorials and articles describing how to overload the stream extraction operator, but I couldn't find any details about getline. Should I just overload it however I want? From the reference this appears to be how it's done.
In some of the overloaded getline functions I've seen (such as at the bottom of the page linked to), I noticed they return something like "basic_istream". Is it enough that I just return istream? What about for "char_type"? Would char suffice?
Basically I want to know: is this one of those anything goes overloads, or is there some finicky detail I should be worried about?
This is the header I've cooked up:
class Polynomial {
public:
friend istream& getline(istream& is, Polynomial & poly);
friend istream& getline(istream& is, Polynomial & poly, char delim);
};
friend istream& getline(istream& is, Polynomial & poly) {
return getline(is, poly, '\n');
}
friend istream& getline(istream& is, Polynomial & poly, char delim) {
// read enough tokens to make a term
// stop when we get to the delimiter
return is;
}
Thanks!

You should still overload operator >>. Within your operator implementation, you can extract as many 'words' as you need (I'm assuming one per coefficient or so). Don't try to overload getline, thats about getting a line not a Polynomial.

Related

C++: Unwanted Conversions between ostream and ofstream

I've been working on a personal dictionary application which can help you remembering words you learnt. It is operated via the CLI (just don't question this, it's kinda just a test and I got a weird passion for CLI apps). So, of course I am using ostreams for writing information on the CLI. I am used to write operator<< overloads (for ostreams) for every class so that I can build up a multi-level output system (basically every object can "speak" for itself).
In order to persist a dictionary object, I wanted to use ofstream and write a file with it. Naturally, I wrote operator<< overloads also for ofstream and in the same "layered" structure.
As a result, I have now two operator<< overloads in every class, like in "Dictionary":
ostream& operator<<(ostream&, const Dictionary&);
ofstream& operator<<(ofstream&, const Dictionary&);
(this is just the declaration in the header file)
Notice that it is very important that these both overloads do different things. I don't want to have some weird persistence-oriented special-format text on the CLI and also not user-friendly plain text in my file.
The problem is that, because of the inheritance structure of ostream and ofstream, ofstream is sometimes implicitely converted to ostream. And when this happens in the middle of my stack full of file output operations, the program suddenly jumps into the wrong overload and prints plain text in the file.
My question is simply: Is there a way to avoid or revert these unwanted implicit conversions in order to let my program jump into the right overloads? Or is there any other good way to fix this problem?
EDIT 1:
Someone pointed out in the comments that this is not an implicit converison. ofstream is sometimes "seen" as its base class ostream. The problem is that at some point the object "forgets" that it is an ofstream and loses all file-related information. From there on it is only an ostream and that's what I meant with the "conversion".
EDIT 2:
The exact point in the program where the "unwanted conversion" happens can be found here:
ofstream& operator<<(ofstream& of, const Section& s) {
return s.print_ofstream(of);
}
So this operator overoad calls "print_ofstream":
ofstream& Section::print_ofstream(ofstream& of) const {
of << "sec" << Util::ID_TO_STRING(section_id) << ":\n";
for (pair<Wordlist, Wordlist> pwl : translations) {
of << '{' << pwl.first << '=' << pwl.second << "}\n";
}
of << "#\n";
return of;
}
Note that "pwl" is a pair of two Wordlists, therefore pwl.first / pwl.second is a Wordlist. So, normally the line of << '{' << pwl.first << '=' << pwl.second << "}\n"; should call the ofstream operator<< overload in Wordlist. But it doesn't. Instead, the other overload method is called:
ostream& operator<<(ostream& o, const Wordlist& wl) {
return wl.print_ostream(o);
}
You have overloaded only the specific operator<< needed for streaming Dictionary, Section, Wordlist, etc objects to a std::ofstream, but std::ofstream inherits MANY other operator<<s from std::ostream, and those operators all take ostream& as input and return ostream& as output. So, for example, of << "sec" will return ostream& even though of is a std::ofstream, and then that ostream& is used for subsequent << calls until ; is reached. Those are the "implicit conversions" you are experiencing.
The real question is, WHY do you want operator<< to output different data depending on the type of std::ostream being written to? That goes against C++'s streaming model. If you really want that, you would have to change print_ofstream(ofstream&) to print_ostream(ostream&) and then dynamically detect the actual std::ostream derived type using dynamic_cast. Same with Wordlist, and any other classes that need it.
A simpler and safer option would be to just store a flag inside of your classes to control how their data should be output, regardless of the type of std::ostream being used. Then you can set that flag as needed. Maybe even define some helper I/O manipulators to set those flags while making << calls.

Whitespace and specific characters when using operator >>

I have a custom String class that contains a char array, and I need to overload the >> operator for this class. For the life of me I can't figure out how to do two things.
1 - Read the user input until a ; is reached
2 - Include whitespace from user input
I cannot use namespace or c++'s built-in string. Unfortunately that rules out the use of getline and any of the convenient find functions (I think it does, anyway?). Some things I have tried:
std::istream& operator >> (std::istream& output, String& input) {
output >> input.str;
return output;}
This works but only up until the first whitespace, after which point it stops reading the user input.
std::istream& operator >> (std::istream& output, String& input) {
while (output != ';') {
output >> input.str;
}
return output;}
An istream I guess isn't equivalent to the user input so you cannot compare it to a char like I tried to in my while loop.
So, my questions are, how does one read input until a specified character is encountered, and how does one include all whitespace when using >> ?
The global operator>> for string/character input stops reading when it encounters whitespace, so it is not worthwhile to implement your custom operator>> in terms of the global operator>>.
You ruled out use of std::getline(), but you can use std::istream::getline() instead. Like std::getline(), it also has an optional delim parameter (the default is '\n'), and will read characters - including whitespace - until the delimiter or EOF is reached.
std::istream& operator >> (std::istream& input, String& output)
{
return input.getline(output.str, yourmaxstrsize, ';');
}

Overloading the input stream operator >> [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am trying to overload the >> operator so that when the user inputs a fraction, cin would store the fraction into an Object of type Fraction.
Excerpt from header file:
// Calculator.h
friend istream &operator>>( istream &, Fraction &);
private:
signed int numo; // fraction numerator
signed int deno; // fraction denomenator
char ch; // the '/' character
Excerpt from Implementation file:
//Calculator.cpp
// insertion operator overloading
istream &operator>>( istream &input, Fraction fraction)
{
input >> fraction.numo;
input >> fraction.ch;
input >>fraction.deno;
return input;
}
When I try to compile Calculator.cpp and compile a driver function inside another file, I run into many errors. Why is this not working? Please explain your answer thoroughly, I would like to learn.
UPDATE:
**Errors: variables, numo deno and ch are 'private'
You have a simple mismatch. The function that's declared as a friend takes a reference to a Fraction as its second parameter. The function you've implemented takes a fraction by value instead, so it's not a friend of the Fraction class. You want the version that takes a reference since when you use the function you normally want to pass a variable, and you want it to modify that variable.
I usually prefer to implement such things in place:
class Fraction {
friend std::istream &operator>>(std::istream &is, Fraction &f) {
return is >> f.numo >> f.ch >> f.deno;
}
// ...
};
Even though its body is inside the class definition, this is still a non-member function simply by virtue of the fact that it's declared as a friend.
Andy in Calculator.h header file, you are using Fraction& (ref type) as function second argument. So in function definition it must be same, (don't use value type).
Prototype:
friend istream& operator>>(istream&, Fraction );
Function definition:
istream& operator>>(istream& input, Fraction& fraction)
{
input >> fraction.numo;
input >> fraction.ch;
input >>fraction.deno;
return input;
}

Overloaded input operator failing automated simple input test

So I'm failing a simple input test for one of assignment questions. I'm to parse two integers separated by a white space. The two integers are used in the private members num and denom of the Rationalnumber type I have defined as a class. Is there something obviously unconventional I am using in or missing from this code? This code works for all my tests.
std::istream &operator>>( std::istream &is, Rationalnumber &r ) {
Rationalnumber::in++; // increment counter
// get the num
string n;
getline(cin,n,' ');
stringstream ssnum(n);
ssnum >> r.num;
// get the denom
string d;
getline(cin,d,'\n');
stringstream ssdenom(d);
ssdenom >> r.denom;
return is;
}
Your code fails in, at least, two obvious ways:
If a different whitespace than space is used, e.g., '\t', it isn't recognized by your code.
The input operator doesn't indicate failure when it is given invalid inputs, e.g., when the input is "a b" rather than numbers.
Conventionally, when input fails, the valuevread remains unchanged. This is also not true for your implementation. To fix things up the code can actually be simplified and made a lot fadter in the process. As this is clearly a homework assignment I don't think it is appropriate to provide the code, though.
This code passes the test!:
std::istream &operator>>( std::istream &is, Rationalnumber &r ) {
Rationalnumber::in++; // increment counter
int in;
is >> in;
r.numerator(in);
is >> in;
r.denominator(in);
return is;
}

Override >> operator like int

this is part of a homework assignment. I don't want an answer just help. I have to make a class called MyInt that can store any sized positive integer. I can only use cstring cctype iomanip and iostream libraries. I really don't understand even where to begin on this.
6) Create an overload of the extraction operator >> for reading integers from an input stream. This operator should ignore any leading white space before the number, then read consecutive digits until a non-digit is encountered (this is the same way that >> for a normal int works, so we want to make ours work the same way). This operator should only extract and store the digits in the object. The "first non-digit" encountered after the number may be part of the next input, so should not be extracted. You may assume that the first non-whitespace character in the input will be a digit. i.e. you do not have to error check for entry of an inappropriate type (like a letter) when you have asked for a number.
Example: Suppose the following code is executed, and the input typed is " 12345 7894H".
MyInt x, y;
char ch;
cin >> x >> y >> ch;
The value of x should now be 12345, the value of y should be 7894 and the value of ch should be 'H'.
The last state of my code is as follows:
istream& operator>>(istream& s, MyInt& N){
N.Resize(5);
N.currentSize=1;
char c;
int i = 0;
s >> c;
N.DigitArray[i++] = C2I(c);
N.currentSize++;
c = s.peek();
while(C2I(c) != -1){
s >> c;
if(N.currentSize >= N.maxSize)
N.Resize(N.maxSize + 5);
N.DigitArray[i] = C2I(c);
i++;
N.currentSize++;
}
}
It almost works! Now it grabs the right number but it doesn't end when I hit enter, I have to enter a letter for it to end.
You can create an operator>> overload for your class this way (as a free function, not inside the class):
std::istream& operator>>(std::istream& lhs, MyInt& rhs) {
// read from lhs into rhs
// then return lhs to allow chaining
return lhs;
}
You can use the members peek and read of istream to read in characters, and isspace to test if a character is a space, and isdigit to check if a character is a number (isspace and isdigit are in the <cctype> header).
First of all, your operator>> should be concerned only with extracting the sequence of chars from the stream and knowing when to stop based on your rules for that. Then, it should defer to a constructor of myInt to actually ingest that string. After all, that class will probably want to expose constructors like:
myInt bigone ("123456123451234123121");
for more general-purpose use, right? And, functions should have a single responsibility.
So your general form will be:
istream& operator>> (istream& is, myInt x)
{
string s = extract_digits_from_stream(is);
x = myInt(s);
return is; // chaining
}
Now how do you extract just digits from a stream and stop at a non-digit? Well, the peek function comes to mind, as does unget. I'd look at source code for the extraction operator for regular integers and see what it does.