-1

I wish to read a text file such as

4
2
3
4 3
2 1
5 4
8 4

The first line being the first dimension of a 2D array and the second line being the second dimension of a 2D array and the third line being a value. Upon reading and storing the first three values into the variables n,m,k i would like to initialize the 2D int array int x[n][m].

#include <iostream>
#include <fstream>
#include <string>
#include <math.h>

using namespace std;

int n,m,k;

int main()
{
    ifstream File;
    File.open("text.txt");

    if (File.fail()) {
        cout << "error opening file";
    }

    while (!File.eof())
    {
            File >> n;
            File >> m;
            File >> k;

            int x[n][m];

            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 5; j++) {
                    File >> x[i][j];
                }
            }

    }
    return 0;
}

However, I cannot initialize the array as it appears the expression n and m do not have constant values. If i were to set the variables to const int n,m,k, i would not be able to read them from the file using >>. How can i read the array sizing values, use them to create the array, and then store the values in them?

edit:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <math.h>

using namespace std;
std::vector < std::vector <int>> x;

int n,m,k;

int main()
{
    ifstream File;
    File.open("test.txt");

    if (File.fail()) {
        cout << "error opening file";
    }

    while (!File.eof())
    {
            File >> n;
            File >> m;
            File >> k;

            for (int i = 0; i < n; i++) {
                vector <int> row;
                for (int j = 0; j < m; j++) {
                    int readFromFile = 0;
                    File >> readFromFile;
                    row.push_back(readFromFile);
                }
                x.push_back(row);
            }

    }

    cout << n;
    cout << "\n";
    cout << m;
    cout << "\n";
    cout << k;
    cout << "\n";

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cout << x[i][j];
            cout << " ";
        }
        cout << "\n";
    }
    return 0;

}
Xenos
  • 19
  • 5
  • 3
    "`int x[n][m];`" there is no such thing as variable length arrays in C++. Use `std::vector`! Also: [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – Swordfish Sep 30 '18 at 03:54
  • Also keep in mind that the scope of your array x is limited to the while loop - x doesn't exist outside the while. – atru Sep 30 '18 at 04:00
  • Ah i see. I was also wondering, do you know if its possible to read the value directly into the array instead of storing them into a variable and then assigning the variables in the array declaration? Thanks for the good link too. – Xenos Sep 30 '18 at 04:03
  • Also good point atru. – Xenos Sep 30 '18 at 04:06
  • As @Swordfish wrote, you may want to consider switching to `std::vector` instead of using plain (C) arrays. There are many reasons to do so, including that you can determine the size of the container at runtime in a straightforward way. If you switch, [this post](https://stackoverflow.com/a/32177226/2763915) is an example of how to read a two column file into a "2D" vector - i.e. vector of vectors of doubles - ints in your case. – atru Sep 30 '18 at 04:22

1 Answers1

2
#include <cstdlib>  // EXIT_FAILURE
#include <vector>
#include <fstream>
#include <iostream>

int main()
{
    char const * file_name{ "test.txt" };
    std::ifstream is{ file_name };

    if (!is.is_open()) {  // exit if the file couldn't be opened.
        std::cerr << "Couldn't open \"" << file_name << "\" for reading!\n\n";
        return EXIT_FAILURE;
    }

    int m, n, k;
    if (!(is >> m >> n >> k)) {  // whatever k might be.
        std::cerr << "Data error!\n\n";
        return EXIT_FAILURE;
    }

    std::vector<std::vector<int>> data(m, std::vector<int>(n)); // m rows, n cols

    for (int row = 0; row < m; ++row) {
        for (int col = 0; col < n; ++col) {
            if (!(is >> data[row][col])) {  // try to extract an integer
                std::cerr << "Data error!\n\n";  // give an error message and
                return EXIT_FAILURE;             // exit if it fails
            }
        }
    }

    for (auto const &row : data) {
        for (auto const &col : row) {
            std::cout << col << ' ';
        }
        std::cout.put('\n');
    }
}

Output:

4 3
2 1
5 4
8 4
Swordfish
  • 12,971
  • 3
  • 21
  • 43
  • Thank you kind soul, I fixed my original code by switching to std vector. I will definitely make use of some things you have provided, including a fix to !File.eof(). – Xenos Sep 30 '18 at 04:39
  • Potential tweak: `std::vector> data(m, std::vector(n));`. Eliminates the need for `data[row].resize(n);` Maybe there's some room for optimization in there, maybe not. – user4581301 Sep 30 '18 at 04:53
  • @user4581301 Memory allocation vs. file-io? I don't wanna bet. Changed anyway. – Swordfish Sep 30 '18 at 04:57