I'm curious of the implementation of std::getline() - c++

I'm reading a .txt file with using std::getline.
I coded like this, and I became so much curious of the return value of std::getline().
(file is an ifstream variable.)
while(!file.eof())
{
string line;
getline(file, line);
cout<<line<<endl;
}
So, what I want to know is why getline can get all lines in the file.
Does getline have an iterator?
I want to know how it's file cursor moves.

After reading your question for the second time I think i know what the question is about (..maybe...)
getline doesnt know where you are in the file, thats the streams job. getline just reads from the current position until it encouters the delimiter. getline does not need to keep track of the current position in the file, because that bookkeeping is done by the ifstream.

Related

How to promt the user correctly? [duplicate]

Here is the code:
string str;
cin>>str;
cout<<"first input:"<<str<<endl;
getline(cin, str);
cout<<"line input:"<<str<<endl;
The result is that getline never pauses for user input, therefore the second output is always empty.
After spending some time on it, I realized after the first call "cin>>str", it seems '\n' is still stored in cin (using cin.peek() to check), which ends getline immediately. The solution will be adding one more line between the first usage and the second one:
cin.ignore(numeric_limits::max(), '\n');
However, I still don't understand, why is '\n' left there after the first call? What does istream& operator>> really do?
The \n is left in the input stream as per the way operator>> is defined for std::string. The std::string is filled with characters from the input stream until a whitespace character is found (in this case \n), at which point the filling stops and the whitespace is now the next character in the input stream.
You can also remove the \n by calling cin.get() immediately after cin>>str. There are many, many different ways of skinning this particular I/O cat, however. (Perhaps a good question in and of itself?)
By default, the stream insertion operator reads until it sees whitespace. Your first call isn't returning until it sees a space, tab, newline, etc. Then the next character needs to be consumed so that you can get to the next one.
I generally recommend only doing line-oriented input from std::cin. So, your code could look something like this:
string str;
int val;
// Read an entire line and parse an integer from it
{
string line;
getline(cin, line);
istringstream iss(line);
iss >> val;
}
cout<<"first input:"<<val<<endl;
getline(cin, str);
cout<<"line input:"<<str<<endl;
Be sure to add error checking too.
The getline-only approach avoids having to think about line buffering of the input, of clearing the input, etc. If you directly read something with >>, the input does not terminate if the user hits enter instead of inputting what is required, but instead continues until a token is input (this behavior is usually not wanted).
As others have said, th problem is that the newline is left from the first extraction. One solution I do is to discard all the left characters in the stream:
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
Good writeup that explains some of the reasons why you are running into this issue, primarily due to the behavior of the input types and that you are mixing them
Also was searching for most suitable solution. Implementation of this operator could produce problems. And not always is acceptable to read entire line, or not mix different types in one input line.
To solve problem, when you want to read some data from cin, and don't know if whitespaces was correctly extracted after last input operation, you can do like this:
std::string str;
std::cin >> std::ws >> str;
But you can't use this to clear trailing newline symbol after last input operation from cin to do not affect new input, because std::ws will consume all whitespaces and will not return control until first non-ws character or EOF will be found, so pressing enter will not finish input process.
In this case should be used
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
which is more flexible.
P.S. If got errors with max() function such as "identifier expected", it could be caused by max macros defined in some header (for example, by Microsoft); this could be fixed by using
#undef max

Reading a text file from the first line multiple times (C++)

I'm using "getline" to read some lines in a text file. It works as it should, but I'm calling the method multiple times.
while(getline(file, line))
{
//Do something
}
//More code in between
while(getline(file, line))
{
//Do something else
}
The problem is that when I call "getline" the second time it starts reading from where it previously finished (e.g. If the first while loop ends at the second line then the next loop starts at the third line). How can I ensure that my program reads the file from the first line every time?
If you need that same first line multiple times I think you should reconsider your strategy.
Just read the line once.
Save it in a variable (or just keep it in the variable "line" you already have).
Close the file.
You would avoid a lot of not necessary I/O operations...
Nonetheless as other people suggested if by any reason you want to procede with this approach you need to insert:
myinputstream.clear(); //clear the buffer
myinputstream.seekg(0, ios::beg); //reset the reading position to beginning
between each attempt to read the same file.
And do not forget to close it eventually.
myinputstream.close();
There's a seekg() function that should help
http://www.cplusplus.com/reference/istream/istream/seekg/
iostream::seekg (0, iostream::beg);
will move you at the beggining of the stream

Why doesn't std::getline block?

I have this code in an Objective-C class (in an Objective-C++ file):
+(NSString *)readString
{
string res;
std::getline(cin, res);
return [NSString stringWithCString:res.c_str() encoding:NSASCIIStringEncoding];
}
When I run it, I get a zero-length string, Every time. Never given the chance to type at the command line. Nothing. When I copy this code verbatim into main(), it works. I have ARC on under Build Settings. I have no clue what it going on. OSX 10.7.4, Xcode 4.3.2.
It is a console application.
It means there is input waiting to be read on the input. You can empty the input:
cin.ignore(std::numeric_limits<std::streamsize>::max();
std::getline(cin, res);
If this is happening it means you did not read all the data off the input stream in a previous read. The above code will trash any user input before trying to read more.
This probably means that you are mixing operator>> with std::getline() for reading user input. You should probably pick one technique and use that (std::getline()) throughout your application ( you can mix them you just have to be more careful and remove the '\n' after using operator>> to make sure any subsequent std::getline() is not confused..
If you want to read a number read the line then parse the number out of the line:
std::getline(cin, line);
std::stringstream linestream(line);
linestream >> value;
You can simply do:
cin.ignore();
or use
cin.clear();
cin.sync();
before using getline()

How do you get input until a newline in C++?

I'm reading input using cin. If I leave the input blank (and just hit enter), the cursor moves to a new line and asks for input again. Is there any way to make cin or scanf just return an empty string in this case?
Instead of operator>>, use getline.
std::string data;
std::getline(std::cin, data);
Side note: There's no recursion involved here. Recursion is when a function calls itself, that's not happening here.

How to detect end-of-file when using getline?

while(getline(fileIn,line))
{
fileOut <<line<<endl;
}
while(getline(fileIn,line))
{
if(fileIn.eof())
break;
fileOut <<line<<endl;
}
I have tried both these pieces of code and the second one also reads past end-of-file and does not break. Can anyone tell me why?
I am just reading from a file and writing the lines out.
The getline function returns a reference to the stream you're reading. It evaluates to false if you try to read past EOF. The stream is still in a good state when you read the last line of the file. So you'll never reach the if-test in your second block of code.
Is that a comma between "fileIn" and "eof()"??? (second example)
One thing I like to do, is enable exceptions on my fstreams. YMMV:
ifstream file;
file.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit);
The first code is correct and it certainly does end the loop after no data is left in the file.