23

this function should read a file word by word and it does work till the last word, where the run stops

void readFile(  )
{
    ifstream file;
    file.open ("program.txt");
    string word;
    char x ;
    word.clear();

    while ( ! file.eof() )
    {
        x = file.get();

        while ( x != ' ' )
        {
            word = word + x;
            x = file.get();
        }

            cout<< word <<endl;
            word.clear();

    }
}

any one see what is the problem and how it can be solved??

M.Tamimi
  • 375
  • 2
  • 3
  • 8

6 Answers6

59

First of all, don't loop while (!eof()), it will not work as you expect it to because the eofbit will not be set until after a failed read due to end of file.

Secondly, the normal input operator >> separates on whitespace and so can be used to read "words":

std::string word;
while (file >> word)
{
    ...
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Instead of eof what should one use? It would be better if you had also mentioned it. – BoraKurucu Oct 13 '20 at 12:18
  • Yes, it has been a few days I have seen the use of (!eof()) cause problem and in my case I change it to this code -> if(eof()) then break. but I am not sure if it's a good idea or not. – meysamimani Nov 27 '21 at 16:24
  • check this link to see why it cause problem https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons – meysamimani Nov 27 '21 at 16:25
11

I have edited the function for you,

void readFile()
{
    ifstream file;
    file.open ("program.txt");
    if (!file.is_open()) return;

    string word;
    while (file >> word)
    {
        cout<< word << '\n';
    }
}
Deidrei
  • 2,125
  • 1
  • 14
  • 14
2

what you are doing here is reading one character at a time from the input stream and assume that all the characters between " " represent a word. BUT it's unlikely to be a " " after the last word, so that's probably why it does not work:

"word1 word2 word2EOF"
Pandrei
  • 4,843
  • 3
  • 27
  • 44
2

As others have said, you are likely reading past the end of the file as you're only checking for x != ' '. Instead you also have to check for EOF in the inner loop (but in this case don't use a char, but a sufficiently large type):

while ( ! file.eof() )
{
    std::ifstream::int_type x = file.get();

    while ( x != ' ' && x != std::ifstream::traits_type::eof() )
    {
        word += static_cast<char>(x);
        x = file.get();
    }
    std::cout << word << '\n';
    word.clear();
}

But then again, you can just employ the stream's streaming operators, which already separate at whitespace (and better account for multiple spaces and other kinds of whitepsace):

void readFile(  )
{
    std::ifstream file("program.txt");
    for(std::string word; file >> word; )
        std::cout << word << '\n';
}

And even further, you can employ a standard algorithm to get rid of the manual loop altogether:

#include <algorithm>
#include <iterator>

void readFile(  )
{
    std::ifstream file("program.txt");
    std::copy(std::istream_iterator<std::string>(file), 
              std::istream_itetator<std::string>(), 
              std::ostream_iterator<std::string>(std::cout, "\n"));
}
Christian Rau
  • 45,360
  • 10
  • 108
  • 185
2

If I may I could give you some new code for the same task, in my code you can create a so called 'document'(not really)and it is saved, and can be opened up again. It is also stored as a string file though(not a document). Here is the code:

#include "iostream"

#include "windows.h"

#include "string"

#include "fstream"

using namespace std;

int main() {

string saveload;


cout << "---------------------------" << endl;
cout << "|enter 'text' to write your document    |" << endl;
cout << "|enter 'open file' to open the document |" << endl;
cout << "----------------------------------------" << endl;
while (true){
    getline(cin, saveload);

    if (saveload == "open file"){
        string filenamet;
        cout << "file name? " << endl;
        getline(cin, filenamet, '*');
        ifstream loadFile;

        loadFile.open(filenamet, ifstream::in);

        cout << "the text you entered was: ";

        while (loadFile.good()){

            cout << (char)loadFile.get();

            Sleep(100);
        }

        cout << "" << endl;

        loadFile.close();

    }

    if (saveload == "text") {
        string filename;
        cout << "file name: " << endl;
        getline(cin, filename,'*');
        string textToSave;
        cout << "Enter your text: " << endl;
        getline(cin, textToSave,'*');

        ofstream saveFile(filename);

        saveFile << textToSave;

        saveFile.close();

    }
}
return 0;
}

Just take this code and change it to serve your purpose. DREAM BIG,THINK BIG, DO BIG

Phi
  • 224
  • 2
  • 9
2

text file :

enter image description here

code :

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


using namespace std;
int main()
{

ifstream file("DB_name_age.txt");
int index;
string name;
int age;

if(file.is_open()) 
{
    while(file  >>index >> name >>age)  
    {
        cout << index <<" "<<name <<" "<<age << endl;
    }


   }else{
    cout<< "file open fail" <<endl;
  }
  return 0;
 }

visual explanation: enter image description here

Zrn-dev
  • 99
  • 5