2
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <process.h>
using namespace std;

int main(){
    system("cls");
    char mline[75];
    int lc=0;
    ofstream fout("out.txt",ios::out);
    ifstream fin("data.txt",ios::in);
    if(!fin){
        cerr<<"Failed to open file !";
        exit(1);
    }
    while(1){
        fin.getline(mline,75,'.');
        if(fin.eof()){break;}
        lc++;
        fout<<lc<<". "<<mline<<"\n";
    }
    fin.close();
    fout.close();
    cout<<"Output "<<lc<<" records"<<endl;
    return 0;
}

The above code is supposed to read from the file "data.txt" the following text

"The default behaviour of ifstream type stream (upon opening files ) allows users to read contents from the file. if the file mode is ios::in only then reading is performed on a text file and if the file mode also includes ios::binary along with ios::in then, reading is performed in binary mode. No transformation of characters takes place in binary mode whereas specific transformations take place in text mode."

and create a file out.txt , in which the same text is stored using line numbers ( A line can have 75 characters or ends at '.' - whichever occurs earlier ).

Whenever I run the program, it just gets stuck at the console - which doesnt respond upon pressing any keys whatsoever.

Can someone tell me what's going on in here ?

Monk
  • 181
  • 1
  • 3
  • 11

1 Answers1

5

If any one of the attempted reads in the file is longer than 74 characters, getline will set the failbit for fin, and you will never reach the end of the file. Change your code to the following:

for (; fin; ++lc) {
  fin.getline(mline,75,'.');
  if (!fin.eof() && !fin.bad())
    fin.clear();
  fout<<lc<<". "<<mline<<"\n";
}

This will break your loop if you reach the end of the file or if something catastrophic happens to the stream. You'll also need to think about handling the extra read that is performed if the file ends with a period.

Consider switching to std::string.

#include <iostream>
#include <fstream>
#include <string>

int main()
{
  int lc = 0;
  std::ofstream fout("out.txt");
  std::ifstream fin("data.txt");

  for (std::string line; getline(fin, line, '.'); )
    fout << ++lc << ". " << line << "\n";

  std::cout << "Output " << lc << " records\n";
}
user657267
  • 20,568
  • 5
  • 58
  • 77
  • Well, the previous error was solved (by making the changes you suggested). But, the I opened the output file - and it was empty ! – Monk Sep 04 '14 at 05:26
  • 1
    Works fine for me, something may be preventing access to your output file. – user657267 Sep 04 '14 at 05:27
  • @Monk you can't just output from mline... it's not guaranteed to be NUL terminated... you should use `fout.write(mline, fin.gcount());` – Tony Delroy Sep 04 '14 at 05:33
  • @TonyD [`istream::getline`](http://en.cppreference.com/w/cpp/io/basic_istream/getline) reads at most count - 1 characters and then appends a null char. – user657267 Sep 04 '14 at 05:36
  • @user657267: ah yeah - I'll go back to sleep... sorry. Might be good to add an `if (!fout) ...` check though - perhaps it wasn't opened properly - can lose the `out` parameter too - `ofstream` takes care of that. And in your original code the last line wouldn't be written because of the `eof()` test after input and before output - you aren't still doing something like that? – Tony Delroy Sep 04 '14 at 05:40
  • @Monk Check to see if the output file is opening correctly like you do with the input, it's probably locked by another process. – user657267 Sep 04 '14 at 05:42
  • @user657267 I just did an output from inside the while loop (1st line after while starts ) - and it didn't give the output on the console . So the control doesn't even enter the while loop ? – Monk Sep 04 '14 at 05:44
  • @Monk Updated the solution, but please consider switching to the `string` version as it's far easier to use. – user657267 Sep 04 '14 at 05:49
  • @user657267 Thanks ! That works perfectly well ! But could you just explain what you did in there ? what would while(fin) mean ? also what does fin.clear() do ? – Monk Sep 04 '14 at 05:54
  • @Monk [`while(fin)`](http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool), [`fin.clear()`](http://en.cppreference.com/w/cpp/io/basic_ios/clear). – user657267 Sep 04 '14 at 05:55
  • @user657267 I can't seem to figure out why u wrote if(!fin && !fin.eof()){ fin.clear();} Could you please explain ? when I don't include this piece of code I get only 1 line of output, and if I do include it, I get 8 lines(i,e, the correct one) . – Monk Sep 04 '14 at 06:09
  • @Monk I've changed it a little since the !fin wasn't necessary but to be on the safe side you need to consider `badbit` too. Basically the stream error is reset if only `failbit` is set, any other read error (such as `eof`) will break the loop. – user657267 Sep 04 '14 at 06:11
  • Could you suggest a good place for reading up on File I/O Errors in C++ ? I can't seem to be able to understand. – Monk Sep 04 '14 at 06:29
  • @Monk One of the beginner books [here](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) should have what you need. – user657267 Sep 04 '14 at 06:32