2

So me and my groupmates suddenly have some clutchwork at hand. I was assigned of making an import function that reads through a textfile that looks like this, and store it to a 2D array: enter image description here

The columns are Tab-separated. As this suddenly came up, dont have the entire project file with me and I am nowhere near my old reliables, I tried conjuring this up in the most generic way possible:

void signal::import_data(string filename){
    ifstream file;

    file.open(filename.c_str());

    if(file.fail()){
        cerr << "file open fail" << endl;
    }else{
        while(!file.eof)
        {
            for(int j = 0; j < NumCols; j++){
                for(int i = 0; i < NumRows; i++){
                    file >> _data[j][i];
                }
            }
        }
    }
    file.close();
}

Am I doing this correct? Im not so sure if streaming like this can bypass tabs, or can it?

Caesar
  • 9,483
  • 8
  • 40
  • 66
Erasmus
  • 427
  • 2
  • 10
  • 23
  • Avoid this : `while(!file.eof)`,and read as `if ( !(file >> _data[j][i])) break;` – Nawaz Jan 26 '13 at 16:55
  • Understood! But is the rest of the code alright? Also, honestly? I dont really know why while(!file.eof) is a viable option, just wondering if you can tell me why – Erasmus Jan 26 '13 at 16:58
  • @Erasmus: I believe you should avoid `while (!file.eof())` because if the token read from the input stream when doing `file >> ...` cannot be parsed into an integer, then the input iterator will not advance. If that's the case, you may never reach the end of the file. – Andy Prowl Jan 26 '13 at 17:01

1 Answers1

3

I think this code:

while(!file.eof)
{
   for(int j = 0; j < NumCols; j++){
       for(int i = 0; i < NumRows; i++){
              file >> _data[j][i];
      }
   }
}

should be replaced with this:

for(int j = 0; j < NumCols; j++)
{
   for(int i = 0; i < NumRows; i++)
   {
         if ( !(file >> _data[j][i]) ) 
         {
             std::cerr << "error while reading file";
             break;
         }
   }
   if ( !file ) break;
}

That is, if you expect NumCols * NumRows entries to be there in the file, why explicitly check for end of file? Let it read till you read NumCols * NumRows entries is read. Once it read, it will automatically exit from the loop.

But you must check if the file ends before NumCols * NumRows entries is read, which is why I'm doing this:

if ( !(file >> _data[j][i]) ) 
{
    std::cerr << "error while reading file";
    break;
}

If the file reaches eof character, OR some other read-failure before it finishes reading NumCols * NumRows entries, then the condition in the if would evaluate to true and it will print the error message and break the loop, it will break outer loop also, as the expression !file will evaluate to true.

For a detail explanation as to HOW TO read files using C++ streams, read the answers from these topics:

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851