Trouble reading from file using getline() c++ - c++

This code always prints the last line of the file. I expected it to print all the text, one line at a time, from the file. Any idea why it doesn't work?
string filename;
cout << "File to read: ";
cin >> filename;
ifstream afile;
afile.open(filename.c_str());
string line;
while(!afile.eof()) {
getline(afile, line);
cout << line;
}
afile.close();
Trying it this way does the same thing:
for (string line; getline(afile, line);) {
cout << line;
}
Maybe this is an issue with my terminal? This works...
for (string line; getline(afile, line);) {
cout << line << endl;
}

The problem is that only the last line is printed. Correct?
I suggest that you add std::endl in your while loop. It can make the issue more clear. Sometimes the output can be confusing.
You can also check the line-delimiting character in your input file. '\n' is the default delimiter for getline. If a different character is used, specify it as getline's 3rd parameter.

From cplusplus.com:
If the delimiter is found, it is extracted and discarded, i.e. it is
not stored and the next input operation will begin after it.
Since your original code snippet doesn't insert any extra newlines itself, there is nothing making the output to the terminal go to the next line. When the output runs out of horizontal space what happens next is up to the terminal. I'm not sure what terminal you're using but in your case, it just wraps the cursor back to the first character on that line without a linefeed. On a windows command shell, it just wraps around to the next line.
Also note that:
while(!afile.eof()) {
getline(afile, line);
cout << line;
}
is a common antipattern. As already pointed out, more appropriate would be:
while(getline(afile, line)) {
cout << line << '\n';
}
The file stream only becomes false after you've reached eof and try to read from it.

Related

Streaming in and out a text file in C++

Basically, I'm trying to stream in a text file and stream out THE SAME information to another text file.
However, it's giving me weird new lines.
Example txt to test:
testing this is a test to see if this actually works
hopefully!
test
test
test
This is the output it gives me after testing:
testing this is a test to see if this actually works
hopefully!test
test
test
I want the output to be the same as the input. But I'm not sure what I'm doing wrong. Been stuck on this for a few hours now, lol.
Here is my code:
string input, name, content;
cout << "Enter input name and extension (Example: hi.txt)\n";
cin >> input;
ifstream file (input.c_str());
if (file.is_open()) {
cout << "Enter output name and extension (Example: hi2.txt)\n";
cin >> name;
ofstream output(name.c_str());
while (getline(file, content)) {
output << content;
if (content == "") {
output << "\n";
}
}
}
std::getline ignores the delimiter, which by default is \n when it reads a line. So, when it reads
testing this is a test to see if this actually works\n
content will actually be
testing this is a test to see if this actually works
Note the missing newline. That's why there is one new line missing after every line :)
You have to add that discarded delimiter:
output << content << '\n'; //Adds the discarded '\n' delimiter

Reading text file containing mixed data in C++

suppose I have a text file that have text data like:
I am reading this file in c++ like,
ifstream file("book_inventory.txt");
string content;
int i=0;
while(file >> content) {
cout << content << ' ';
}
but it display all output on a single line without showing any new line .
Read the whole line using e.g. std::getline then use a std::istringstream to parse out first the three numbers. Then it gets a little harder. If the name (like e.g. "James Pilgrim") is always two "words" then you can use normal input operator >> to get the names, and then std::getline again to get the last part.
If the name can be one, two or more words, then it's actually impossible to say when the person names ends and the title begins.
On the other hand, if you don't want to actually parse the contents, and just print the lines then just read line by line using std::getline, and remember to print a newline.
You can try the below code to read a file line by line as it is or using endl instead of ' ' in your code
ifstream myfile("book_inventory.txt");
string line;
if (myfile.is_open())
{
while (getline(myfile, line))
{
cout << line << '\n';
}
myfile.close();
}

C++: Why won't getline() print the last word of the input string?

i'm trying to get my program to read a string and then output each word on an individual line. When I call this function it is not printing the last word of the sentence. I have not been able to find an answer to this problem.
For example:
Input:
Hello there my friend
Output:
Hello
there
my
Here is my code:
istream& operator >> (istream& in, FlexString& input) {
std::string content;
while (std::getline (in,content,' ')) {
cout << content << endl;
}
return in;
}
I'm new to C++ so this may be dumb, but I tried adding another cout call to print content on the next line after the while loop but it won't print it for some reason.
getline didn't skip the last word. It's still waiting for you to finish it. You selected the space character (' ') as the delimiter, so getline is going to read until if finds a space (not a tab or a newline), or until the input stream ends. Your loop isn't going to stop at the end of the line either, like you seem to be expecting. It is going to keep reading until the stream ends.
If you want to read a single line, and then separate the line word by word, then just call getline once, with the \n delimiter (which is the default). Then use an istringstream to separate the resulting string word by word.
std::string line;
std::getline(in, line);
std::istringstreaam iss(line);
std::string content;
while (iss >> content)
std::cout << content << std::endl;

How to check if stringstream>>string will put nothing on the string?

For example, when parsing a text file, some times this file have stuff like this:
keyword a string here
keyword another string
keyword
keyword again a string
Note that the 3th line have an empty string (nothing or white spaces).. The thing is that when you do stringstream>>laststring, and stringstream have an empty string (null or just white space), it will not overwrite the "laststring", it will do nothing. Theres anyway to check this situation before hand? I dont want to create a temp empty string just to check it is still empty after stringstream>>, seems lame.
When you cannot read from stream - its state changes, so when casting to bool, it returns false:
bool read = static_cast<bool>(ss >> laststring);
Or - in if-expr:
if (ss >> laststring)
cout << "Just read: " << laststring;
See example
You can only know after trying to read whether there was something or not. What you might be able to do is to skip whitespace and see if there is a non-space in the next location:
if ((in >> std::ws).peek() != std::char_traits<char>::eof()) {
...
}
Given that empty strings are cheap to create, I wouldn't bother and try read the string. Note, however, that reading from streams isn't line based, i.e., in your case above you need to split the lines first or use something like std::getline() to read the second part of line.
You can use getline, to read a line from the file. Then, copy the line into a string stream and read words from the string stream one at a time. The streams will automatically stop reading when they run out of lines / words.
// open file
std::ifstream fin("text.txt");
// 'iterate' through all the lines in the file
unsigned lineCount = 1;
std::string line;
while (std::getline(fin, line))
{
// print the line number for debugging
std::cout << "Line " << lineCount << '\n';
// copy line into another stream
std::stringstream lineStream(line);
// 'iterate' through all the words in the line
unsigned wordCount = 1;
std::string word;
while (lineStream >> word)
{
// print the words for debugging
std::cout << '\t' << wordCount++ << ' ' << word << '\n';
}
}
You need to include iostream, fstream, sstream and string.
For checking if string is empty, use foo.size() == 0.
For checking if string stream is empty fooStream.rdbuf()->in_avail() == 0

C++: Using ifstream with getline();

Check this program
ifstream filein("Hey.txt");
filein.getline(line,99);
cout<<line<<endl;
filein.getline(line,99);
cout<<line<<endl;
filein.close();
The file Hey.txt has alot of characters in it. Well over a 1000
But my question is
Why in the second time i try to print line. It doesnt get print?
The idiomatic way to read lines from a stream is this:
std::ifstream filein("Hey.txt");
for (std::string line; std::getline(filein, line); )
{
std::cout << line << std::endl;
}
Notes:
No close(). C++ takes care of resource management for you when used idiomatically.
Use the free std::getline, not the stream member function.
According to the C++ reference (here) getline sets the ios::fail when count-1 characters have been extracted. You would have to call filein.clear(); in between the getline() calls.
#include<iostream>
using namespace std;
int main()
{
ifstream in;
string lastLine1;
string lastLine2;
in.open("input.txt");
while(in.good()){
getline(in,lastLine1);
getline(in,lastLine2);
}
in.close();
if(lastLine2=="")
cout<<lastLine1<<endl;
else
cout<<lastLine2<<endl;
return 0;
}
As Kerrek SB said correctly There is 2 possibilities:
1) Second line is an empty line
2) there is no second line and all more than 1000 character is in one line, so second getline has nothing to get.
An easier way to get a line is to use the extractor operator of ifstream
string result;
//line counter
int line=1;
ifstream filein("Hey.txt");
while(filein >> result)
{
//display the line number and the result string of reading the line
cout << line << result << endl;
++line;
}
One problem here though is that it won't work when the line have a space ' ' because it is considered a field delimiter in ifstream. If you want to implement this kind of solution change your field delimiter to e.g. - / or any other field delimiter you like.
If you know how many spaces there is you can eat all the spaces by using other variables in the extractor operator of ifstream. Consider the file has contents of first name last name.
//file content is: FirstName LastName
int line=1;
ifstream filein("Hey.txt");
string firstName;
string lastName;
while(filein>>firstName>>lastName)
{
cout << line << firstName << lastName << endl;
}