6

Like the title says I'm trying to read an unknown number of integers from a file and place them in a 2d array.

#include <iostream>
#include <fstream>
using namespace std;
int main()
{

fstream f;int i,j,n,a[20][20];char ch;

i=0;j=0;n=0;
f.open("array.txt", ios::in);
while(!f.eof())
{
    i++;
    n++;
    do
    {
        f>>a[i][j];
        j++;
        f>>ch;
    }
    while(ch!='\n');
}

for(i=1;i<=n;i++)
{
    for(j=1;j<=n;j++)
        cout<<a[i][j]<<endl;
    cout<<endl;
}
return 0;

}

and my "array.txt" file :

1 1 1
2 2 2
3 3 3

After compiling the program, it prints this

enter image description here

NacRonDX
  • 63
  • 9
  • 1
    Are you sure you don't mean `while(ch!='\n')`? Edit: Also, you may want to flip the order of the `f>>ch` and `f>>a[i][j]`. – forkrul Dec 14 '15 at 18:45
  • Welcome to Stack Overflow. Don't post links to output, post the actual output. Try something simpler first: reading to a simple (1D) array. Don't use `while(!f.eof())`. – Beta Dec 14 '15 at 18:45
  • I will try your suggestions. Edit : It doesn't return anything. – NacRonDX Dec 14 '15 at 18:49
  • 1
    `std::vector` seems to be right tool for the job. – GingerPlusPlus Dec 14 '15 at 18:49
  • You are going to have issues because the `operator>>` appears to discard whitespace by default. Try using `getline(file_descriptor, cpp_string)`. – forkrul Dec 14 '15 at 19:03
  • @forkrul sry to annoy you , but can you be a little more specific , I'm really nothing more that an amateur at c++; – NacRonDX Dec 14 '15 at 19:12
  • @FalconLover see my answer for what I mean. – forkrul Dec 14 '15 at 19:18

3 Answers3

4

As your input file is line oriented, you should use getline (C++ equivalent or C fgets) to read a line, then an istringstream to parse the line into integers. And as you do not know a priori the size, you should use vectors, and consistently control that all lines have same size, and that the number of lines is the same as the number of columns.

Last but not least, you should test eof immediately after a read and not on beginning of loop.

Code becomes:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
int main()
{

    fstream f;
    int i=0, j=0, n=0;
    string line;
    vector<vector<int>> a;
    f.open("array.txt", ios::in);
    for(;;)
    {
        std::getline(f, line);
        if (! f) break; // test eof after read
        a.push_back(vector<int>());
        std::istringstream fline(line);
        j = 0;
        for(;;) {
            int val;
            fline >> val;
            if (!fline) break;
            a[i].push_back(val);
            j++;
        }
        i++;
        if (n == 0) n = j;
        else if (n != j) {
            cerr << "Error line " << i << " - " << j << " values instead of " << n << endl;
        }
    }
    if (i != n) {
        cerr << "Error " << i << " lines instead of " << n << endl;
    }

    for(vector<vector<int>>::const_iterator it = a.begin(); it != a.end(); it++) {
        for (vector<int>::const_iterator jt = it->begin(); jt != it->end(); jt++) {
            cout << " " << *jt;
        }
        cout << endl;
    }
    return 0;
}
Serge Ballesta
  • 121,548
  • 10
  • 94
  • 199
1

You may want to look into using a vector so you can have a dynamic array.

Ken Rea
  • 67
  • 8
0

Try:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
int main() {
  fstream f;
  int i, j, n, a[20][20];
  string buf;

  i = 0;
  j = 0;
  n = 0;
  f.open("array.txt", ios::in);
  while (1) {
    getline(f, buf);
    if (f.eof()) break;
    stringstream buf_stream(buf);
    j = 0;
    do {
      buf_stream >> a[i][j];
      j++;
    } while (!buf_stream.eof());
    i++;
    n++;
  }

  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) cout << a[i][j] << " ";
    cout << endl;
  }
  return 0;
}

Also, if you really want to read arbitrarily large arrays, then you should use std::vector or some such other container, not raw arrays.

forkrul
  • 524
  • 1
  • 4
  • 9
  • 1
    Recommend a tweak: `while (getline(f, buf))` in place of `while(1)`, the separate `getline` and the `if` and `break`. Also prevents the admittedly rare case of stream error in `getline` without eof resulting in undefined contents in `buf`. – user4581301 Dec 14 '15 at 19:29