C++: Using ifstream with getline(); - c++

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;
}

Related

Sorting function with output to a separate file

I need to sort the input text document and write it into another test document. so that lines with an even number of words delete every second word, and lines with an odd number of words remain unchanged. The sorting should be performed as a function, the first pointer to the input of the string and the second pointer to the output.
I did the input and output, tried to do a sorting to begin with without a function, but nothing worked. can you tell me what I did not do the rule?
Example:
Input.txt
I do not like to go to school or study
I like to play games
Output.txt
I not to to or
I like to play games
string in, out;
cin >> in;
cin >> out;
ifstream input(in);
string str;
ofstream output(out);
string st;
while (getline(input, str))
{
do
{
int i = count(str.cbegin(), str.cend(), ' ');
if (i % 2 == 0)
st.append(str);
else
st.append(" ");
i++;
}
while (input);
output << st << endl;
}
The std::stringstream will be your friend.
Read about it here and especially for the useful std::istringstream here.
What can we do with this thing? We can put a string into it and then use the extraction operator >> like with any other stream.
So, counting words will become very simple. We read a line from the file as a std::string and then put it into a std::istringstream, Then we extract dummy words and increase a counter until the reading fails. Then we have the number of words.
Example:
// We read one line. Count the number of words
// Put the string in a stringstream to easily extract words
std::istringstream iss(line);
// Counter for words
unsigned int wordCount{};
// Dummy word
std::string tempWord{};
// Do the counting
while (iss >> tempWord) ++wordCount;
The stream tries too read until it cannot read any more (the stream is empty) and then sets a failbit. The failure of any stream can be checked with its bool operator or the !-operator. The while loop expects a boolean. And the extraction operation iss >> tempWord will return a reference to the stream and then its bool operator will be called and used as condition.
OK, understood, we can now count words. Next step is to skip words.
This is similar simple. In case of even number of words in a string, we will read always 2 words in a loop and simply throw the second one away.
Like this
std::string usedWord{};
// Read 2 words, ignore the second
while (iss >> usedWord >> tempWord)
result += (usedWord + ' ');
There are of course many other possible ways to solve that, but maybe the below solution can give you an idea.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
int main() {
// First read the input filename
std::cout << "\nPlease enter the path for the input file:\n";
std::string inputFileName{};
std::getline(std::cin, inputFileName);
// next read the output filename
std::cout << "\nPlease enter the path for the output file:\n";
std::string outputFileName{};
std::getline(std::cin, outputFileName);
// Open now both files. If one file cannot be opened, then no need tocontinue
// Open input file and check, if it could be opened
std::ifstream inputFileStream(inputFileName);
if (inputFileStream) {
// Input file could be opened without error.
// Now open output file and check, if it could be opened
std::ofstream outputFileStream(outputFileName);
if (outputFileStream) {
// Now, both input and output file streams are open
// Read lines
std::string line{};
while (std::getline(inputFileStream, line)) {
// We read one line. Count the number of words
// Put the string in a stringstream to easily extract words
std::istringstream iss(line);
// Counter for words
unsigned int wordCount{};
// Dummy word
std::string tempWord{};
// Do the counting
while (iss >> tempWord) ++wordCount;
// if the number of words is even then
if ((wordCount % 2) == 0) {
// Rinitialize stringstream
iss.clear(), iss.str(line);
// Here we store the resulting sentence
std::string result{};
// Now extract the word that we will keep and the other one that we will throw away
std::string usedWord{};
// Read 2 words, ignore the second
while (iss >> usedWord >> tempWord)
result += (usedWord + ' ');
// Write result to output
outputFileStream << result << '\n';
}
else
outputFileStream << line << '\n';
}
}
else std::cerr << "\n*** Error: could not open output file '" << outputFileName << "'\n\n";
}
else std::cerr << "\n*** Error: could not open input file '" << inputFileName << "'\n\n";
}

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();
}

Splitting string into smaller strings from text input

Reading in a text file to a C++ program I'm working on, and storing each string in a node for a double-linked list. Problem is, I don't know how to split up a line into smaller strings, separating them where the space is.
For instance, one input is
"Duck Donald 940-666-5678"
and I'm attempting to split it into a lastname string, a firstname string, and a phnum string at the white space. The result would essentially be:
lastname==Duck
firstname==Donald
phnum==940-666-5678
How would I do this?
Although I not sure how you're extracting this data, I believe you should just be able to use the >> operator.
Example:
string lastname;
string firstname;
string phnum;
ifstream myFile;
myFile.open("example.txt");
myFile >> lastname >> firstname >> phnum;
I am not quite sure how you are reading in from your file, but this bit of code may help you.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
istringstream iss(s);
do
{
string sub;
iss >> sub;
cout << "Substring: " << sub << endl;
} while (iss);
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Make sure to search Stackoverflow/Google before asking because you can find your answer really easily many times (see my resources)
Resources: http://www.cplusplus.com/doc/tutorial/files/, Split a string in C++?

File Line count using boost

If I have a boost::filesystem::path object, how can I get the line count of this file?
I need to compare the line counts of two files as a precondition check.
You can do something like this:
std::ifstream file(path.c_str());
// Number of lines in the file
int n = std::count(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), '\n');
Where path is a boost::filesystem::path. This will count the number of \n in the file so you need to pay attention if there is a \n at the end of the file to get the right number of lines.
You can use ifstream and getline to read file by line, and count it.
std::ifstream filein("aaa.txt");
int count = 0;
std::string line;
while (std::getline(filein, line))
{
count++;
}
std::cout << "file line count is " << count;
With stringstream, I advise to use intermediate string otherwise the streamstring will be consumed during the count and the iterator will not be at the beginning of the string for next getline.
string s = string("1\n2\n3\nlast");
stringstream sstream(s);
int nbOfLines = std::count(s.begin(), s.end(), '\n');
cout << "Nb of lines is: " << nbOfLines << endl;
Result:
Nb of lines is: 3
You can do getline from the beginning.
Or, for better performances (less copy), seek back to the beginning
int nbOfLines = std::count(std::istreambuf_iterator<char>sstream),std::istreambuf_iterator<char>(), '\n');
sstream.seekg(0, ios_base::beg);

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