How to use std::istream correctly - c++

I want to do the following:
// I want 'is' to be either opened file or stringstream ...
void ParseTokens(const std::istream &is, std::vector<TokenClass> &vToks)
{
char ch;
...
is >> ch;
...
}
The compiler complains:
error: ambiguous overload for ‘operator>>’ in ‘is >> ch’
What do I need to do to make this work?
[edit]Just a caveat: operator>> gives formatted output - it loses white-space characters (tabs, newlines, etc). To access all the characters, you need to use get().

Since is >> ch; extracts characters from is, it modifies the stream. Therefore, it can't be const in the function signature, which can cause seemingly irrelevant errors because there's no exact match. Change the function to take a std::istream &.

Related

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, ';');
}

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.

Difference between istream::get(char&) and operator>> (char&)

My question seems to be the same as this one, but I didn't find an answer since the original question seems to ask something more specific.
In C++98, what is the difference between
char c;
cin.get(c);
and
char c;
cin >> c;
?
I've checked the cplusplus reference for get and operator>>, and they look the same to me.
I've tried above code and they seem to behave the same when I input a char.
The difference depends on when there is a whitespace character on the stream buffer.
Consider the input ' foo'
char c;
cin.get(c);
Will store ' ' in c
However
char c;
cin >> c;
Will skip the whitespace and store 'f' in c
In addition to what's already been said, std::istream::get() is also an unformatted input function so the gcount() of the stream is affected, unlike the formatted extractor. Most of the overloads of get() and getline() have mostly been made obselete by the introduction of std::string, its stream extractors, and std::getline(). I'd say to use std::istream::get() whenever you need a single, unformatted character straight from the buffer (by using its single or zero argument overload). It's certainly quicker than turning off the skipping of whitespace first before using the formatted extractor. Also use std::string instead of raw character buffers and is >> str for formatted data or std::getline(is, str) for unformatted data.

how this function read text into a struct?

I am trying to understand what exactly the following function is doing. It is used to read a text file into a struct, called AEntry, which only contains four ints.
The file contains a list of lines. Each line holds four ints delimited with spaces (or tab).
when this function is called, a line of istream and a AEntry struct are passed in.
My question is how the delimitors, spacess or tabs, are filtered out? or my understanding is wrong.
istream& operator>>( istream &stream, AEntry& val )
{
stream >> val.kv;
stream >> val.col;
stream >> val.bo;
stream >> val.Offset;
return stream;
}
They're filtered out because that's the behavior of the default overloads of istream::operator>>. They stop at whitespace and discard it instead of incorporating it into the extracted output.

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.