Infinite loop with get function - c++

Can Anyone tell me that what's wrong with using get function here instead of getline. Get works perfectly in reading a single line without any loop. Why it isn't working here. It results in infinite loop.
int main() {
ofstream outfile;
outfile.open("Myfile.txt", ios::trunc);
outfile <<"aabc"<<endl;
outfile <<"Hello Helloo"<<endl;
outfile <<"3abc"<<endl;
outfile <<"Somee text here "<<endl;
outfile.close();
ifstream infile;
infile.open("Myfile.txt");
char ch[20];
while(!infile.eof()) {
infile.get(ch,20);
cout<<ch;
}
infile.close();
return 0;
}

When called with a char*, as in your get(ch,20), the get method will read up to 19 characters or until it reaches a delimiter (\n by default).
The delimiting character is explicitly not read, so it's still the next character. So when you call it a second time, without having done anything to read that character, it immediately returns the 0-length string up to that same delimiter, over and over again.
Since that behavior is the key difference between get and getline, if it's not the behavior you want, just don't use it.

Related

Error while using getline() in c++

I am using getline to read strings and print but while using that I am unable to give input so I used ignore()
Code
int t;
cin>>t;
string str;
for(int i=0;i<t;i++)
{ cin.ignore();
getline (cin, str);//reading string
cout << str << endl;
}
return 0;
When using that while printing output every first character from second line of output are missing?
The std::getline function reads (but doesn't store) the newline, so in the second (and every following) iteration of the loop your call to ignore will read the first character of that line.
You should move the ignore call to before the loop.

using getline() while separating comma didn't work

I have read a CSV file that has line ending character as '\r', the reading operation done successfully, but the problem started when i pass the read line in to the while(getline(ss,arr2,',')) for separating comma..it does work properly for the first line but all the next iterations are empty(i.e)it has been failing to separate the comma in the string.
int main()
{
cout<<"Enter the file path :";
string filename;
cin>>filename;
ifstream file;
vector<string>arr;
string line,var;
stringstream content;
file.open(filename.c_str(),ios::in );
line.assign((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
file.close();
string arr2;
stringstream ss;
content<<line;
//sqlite3 *db;int rc;sqlite3_stmt * stmt;
int i=0;
while (getline(content,var,'\r'))
{
ss.str(var);//for each read the ss contains single line which i could print it out.
cout<<ss.str()<<endl;
while(getline(ss,arr2,','))//here the first line is neatly separated and pushed into vector but it fail to separate second and further lines i was really puzzled about this behaviour.
{
arr.push_back(arr2);
}
ss.str("");
var="";
arr2="";
for(int i=0;i<arr.size();i++)
{
cout<<arr[i]<<endl;
}
arr.clear();
}
getch();
}
what went wrong in the above...I see nothing right now:(
The stringstream::str method does not reset / clear the internal state of the stream. After the first line, the internal state of ss is EOF (ss.eof() returns true).
Either use a local variable inside the while loop:
while (getline(content,var,'\r'))
{
stringstream ss(var);
Or clear the stream before ss.str:
ss.clear();
ss.str(var);

How to read substitution char with ifstream in C++ ? (SUB in ASCII)

I am having a hard time finding out why I can't read all characters with fstream get function.
My code is the following :
ifstream input_stream(input_filename.c_str(), ios::in);
string input;
if(input_stream)
{
char character;
while(input_stream.get(character))
{
input += character;
}
input_stream.close();
}
else
cerr << "Error" << endl;
By testing a little, I found out that I get a problem when character = 26 (SUB in ASCII) because input_stream.get(26) return false and I get out of my while loop.
I would like to put in my string input all characters from the file including SUB.
I tryed with getline function at first and I got a similar problem.
Could you help me please ?
You need to read a binary stream, not a textual one (since SUB i.e. '0x1a' (that is 26) is a control character in ASCII or UTF8, not a printable one) Use ios::binary at opening time:
ifstream input_stream(input_filename.c_str(), ios::in | ios::binary);
Maybe you would then code
do {
int c= input_stream.get();
if (c==std::char_traits::eof()) break;
input += (char)c;
} while (!input_stream.fail());
Did you consider using std::getline to read an entire line, assuming the input file is still organized in ('\n' terminated) lines?

Write a C++ pgm to read from a file "input.txt" , whenever a period is encountered insert newline and write modified content to "output.txt"

Question: Write a program in C++ to read from a file "input.txt" and whenever a period is encountered in the file "input.txt" insert a newline character and then write the modified contents to a new file "output.txt" and save it. Finally print the number of periods encountered.
I wrote the following program however this program compiles fine but it doesn't execute so please help me out. Thanks and regards.
#include<iostream>
#include<fstream>
using namespace std;
int main(){
int count = 0;
ofstream myFile;
char ch;
myFile.open("D:\\Files\\input.txt");
myFile<<"Hi this is Yogish. I'm from Bengaluru, India. And you are ??"<<endl;
myFile.close();
ofstream myHandler;
myHandler.open("D:\\Files\\output.txt");
fstream handler;
handler.open("D:\\Files\\input.txt");
if(handler.is_open()){
while(!handler.eof()){
handler>>ch;
if(ch != '.'){
handler<<ch;
}
else{
myHandler<<ch<<'\n';
handler<<'.'<<'\n';
count++;
}
}
}
cout<<"The number of periods : "<<count++<<endl;
system("pause");
}
I assume the question means that you only have to write the modified contents to the new file output.txt. At present you are trying to write into input file as well.
You should read the entire line in one string and then use std::replace_if algorithm from the <algorithm> header.
Also, in general, you should avoid the check for termination condition as file.eof() since it is only set after the read operation. Hence, there is a possibility that the eof() bit is set after you read a character, which means that the last character read is invalid and you would output this invalid character to the file.
It will result in undefined behaviour.
Instead you should try something like:
bool isDot( const char& character ) {
return character == '.';
}
And in your main function:
std::string newLine;
// enter the loop only if the read operation is successful
while ( getline( handler, newLine ) ) {
count += std::count_if( newLine.begin(), newLine.end(), isDot );
std::replace_if( newLine.begin(), newLine.end(), isDot, '\n' );
myHandler << newLine;
}

Why using while(!input.eof()) loop twice not working? [duplicate]

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 9 years ago.
On the following lines of code is intended to put every words in the input text file(words are separated by new lines) to a vector of strings, then to turn each word inside out, and to see if this turned word is contained in the list of words in the input file.
I believe my binary search function and wordTurn function works fine.
I did several simple tests on my code, and I found out using while(!myFile.eof()) loop twice might be the cause for my code not working. By not working I mean I get the output file("pairs.txt") as an empty document(it is supposed to be a list of pairs of words).
That is, when I put some simple print code in the second while(!myFile.eof()) loop body, it did not get printed out, from which I concluded this loop is not reached. This is more likely, since it printed when I commented out the first while(!myFile.eof()) loop. I originally placed the first while loop at the else body, but this made no difference.
What do you think is the problem?
I tried combining those two loop body into the second loop, and it produces something in the output file, but this was not what this code was supposed to do, and this was logically not correct.
Any words of advice would be greatly appreciated.
int main(int argc, char* argv[]) {
vector<string> words;
ifstream myFile(argv[1]);
ofstream outputFile("pairs.txt");
string vocab;
string s;
int count;
while(!myFile.eof()) { //first while(!myFile.eof()) loop
getline(myFile, s);
words.push_back(s);
}
if(argc != 2) {
cout << "Usage: provide the name of one input file after the dictlookupHN executable file." << endl;
return (1);
}
else {
if(!myFile.is_open()) {
cerr << "Error: unable to open file " << argv[1] << endl;
return (1);
}
else {
while(!myFile.eof()) { //second while(!myFile.eof()) loop
getline(myFile, vocab);
string turnedWord = wordTurn(vocab);
if(binsearch(words, turnedWord) != "") {
outputFile << vocab << ":" << turnedWord << endl;
count++;
}
}
}
}
myFile.close();
outputFile.close();
return 0;
}
The ifstream class maintains an internal offset into the stream data, keeping track where it has to read from, for the next operation.
When this offset reaches the end, it stops the first loop, (eof() returns false). You need to reset this internal position back to the beginning of the file, before reading again.
You do that by saying:
myFile.clear(); // clear stream flags and error state
myFile.seekg(0, ios::beg); // reset read position
before the second loop.
Edit: Added call to clear().
What is happening is that the seek pointer for the file is at the end of the file when you complete the first run through the file. If you want to seek through the file again, you will need to reset the file pointer using myFile.seekg(0, ios::beg); before the second while loop. Something like this:
...
else {
myFile.seekg(0, ios::beg);
while(!myFile.eof()) { //second while(!myFile.eof()) loop
...
That should fix the problem.
If you want to read the file again [once you have read the entire file to the end] you will need to reset the bad/fail bits, and also seek to the start. End of file is a permanent state unless something is done to reset it.
So, you need myFile.clear(); and myFile.seekg(0, ios_base::beg);
Although I have a feeling you actually want to open a different file in this particular case, in which case, I would recommend closing the current one, and using a different variable - they aren't very expensive, and it makes the code clearer [particularly if you call it something sensible, e.g. vocabFile instead of myFile]
To read from the beginning of your file again, use:
myFile.seekg(0, ios::beg);
But note, that this is not a good way of reading from a file:
string vocab;
while(!myFile.eof()) {
getline(myFile, vocab);
...
}
This is how it should look like:
string vocab;
while(getline(myFile, vocab)) {
if (vocab.empty())
continue; // empty line might be read
...
}
Have a look at: Why does my input seem to process past the end of file?
The first loop reaches the end of file, and you're not resetting before the second read. You need to seek to the start of the file after the first loop: myFile.seekg (0, ios::beg); will do this for you.
the first loop reached EOF, thats the position of "read marker", so the second EOF is readed as first in the second loop.
As simple, try to close and open file between loop.
Better idea is to use seekg to read from top again.
Thank you everyone for all of these words of good advice.
They really helped me understand how the ifstream and eof work.
My TA's advice was to use for loop instead of the second while(!myFile.eof()) loop. I might be using this option, but your answers will be of great help when I have to use eof twice.
Thank you!
while(!myFile.eof()) {
string s;
getline(myFile, s);
words.push_back(s);
}
for(int i=0; i<words.size(); i++) {
//LOOP INV:
string vocab = words.at(i);
string turnedWord = wordTurn(vocab);
if(binsearch(words, turnedWord) == 1 && turnedWord.length() > 3) {
outputFile << vocab << ":" << turnedWord << endl;
count++;
}