Sion
Sion

Reputation: 36

How to get 2 dimensional array from file (C++)

I'd like to input 2 dimensional array from text file. But my code doesn't work..

#pragma disable (warnning:c4996)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<fstream>
#include<conio.h>
int main()
{
    std::ifstream arrival; std::ifstream departure;
    arrival.open("arrival.txt"); departure.open("departure.txt");

    int i, j, l = 0;
    char temp;

    if (arrival.is_open() && departure.is_open()) {
        temp = arrival.get();
        while (temp != EOF) {
            if (temp == '\n')
                l++;
            temp = arrival.get();
        }
    }
    else
        printf("error");
    // file read


    int** arr = new int*[l];


    for (i = 0; i < l; i++)
        arr[i] = new int[3];

    for (i = 0; i < l; i++) {
        for (j = 0; j < 3; j++)
            arrival >> arr[i][j];
    }

    for (i = 0; i < l; i++) {
        for (j = 0; j < 3; j++)
            printf("%d ", (int)arr[i][j]);
    }

    _getch();
    delete[] arr;
    arrival.close();
    departure.close();
    return 0;
}

this is my code, and

arrival

2018 01 05
2018 02 03
2019 04 03
2019 08 08
2020 07 08
2018 03 28
2018 05 04
2018 08 30
2019 01 06
2019 09 21
2020 02 18

this is the text file.

I surmise in

arrival >> arr[i][j];

this part, it doesn't get value from the file. I have no idea how to solve this problem.

Upvotes: 0

Views: 150

Answers (3)

alle_meije
alle_meije

Reputation: 2480

This is what you can do with the 4 'basic' libraries vector, string, fstream and iostream. It is an example for "arrivals.txt" only:

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

int main() {

  std::ifstream arrivals;                // open the file
  arrivals.open("arrivals.txt");

  std::vector<std::vector<int>> matrix;  // 2D container

  int l=0;
  std::string unused;
  while (std::getline(arrivals,unused))  // count the lines
    ++l;

  arrivals.clear();                      // go back to start
  arrivals.seekg(0);

  matrix.resize(l);                      // resizing matrix
  for (int i=0; i<l; i++) {              // fill the matrix
    matrix[i].resize(3);                 // resizing row
    for (int j=0; j<3; j++)
      arrivals >> matrix[i][j];
  }

  arrivals.close();                      // close the file
 
  for (int i=0; i<l; i++) {              // print the matrix
    for (int j=0; j<3; j++)
      printf("%02d ",matrix[i][j]);
    printf("\n");
  }

}

The most important things to remember are

  • to resize the vector before filling out a new element (easier than dynamic allocation!)
  • to go back to the start of the text file after counting the lines (you could if you want, also close the file and open again for reading).

Upvotes: 1

rturrado
rturrado

Reputation: 8064

Here's a different solution using:

  • std::vector and std::array for holding the list of values read from the file.
  • std::istringstream to parse each file line into an array of values.
  • fmt::print to print each array of values.

You can just substitute the example's std::istringstream arrival for a std::ifstream arrival; they are both input streams.

By using std::vector, which you can grow dynamically, you don't need to read the input stream twice. Instead, just push_back each line read from the input stream into the vector.

[Demo]

#include <array>
#include <fmt/ranges.h>
#include <sstream>  // istringstream
#include <vector>

int main() {
    std::istringstream arrival{
        "2018 01 05\n"
        "2018 02 03\n"
        "2019 04 03\n"
        "2019 08 08\n"
        "2020 07 08\n"
        "2018 03 28\n"
        "2018 05 04\n"
        "2018 08 30\n"
        "2019 01 06\n"
        "2019 09 21\n"
        "2020 02 18"
    };
    std::vector<std::array<int, 3>> lines{};
    for (std::string current_line{}; std::getline(arrival, current_line);) {
        std::istringstream iss{current_line};
        std::array<int, 3> current_line_numbers{};
        iss >> current_line_numbers[0]
            >> current_line_numbers[1]
            >> current_line_numbers[2];
        lines.push_back(current_line_numbers);
    }
    for (auto&& line : lines) {
        fmt::print("{}\n", fmt::join(line, " "));
    }
}

// Outputs:
//
//   2018 1 5
//   2018 2 3
//   2019 4 3
//   2019 8 8
//   2020 7 8
//   2018 3 28
//   2018 5 4
//   2018 8 30
//   2019 1 6
//   2019 9 21
//   2020 2 18

Upvotes: 1

john
john

Reputation: 87959

So the problem is that you read to the end of the file looking for newlines. Then you start to read your data. The problem is that you are still at the end of the file, so there is no data.

You need to rewind the file before you start reading the data.

// file read
arrival.seekg(0); // rewind the input file back to the start
int** arr = new int*[l];

Upvotes: 1

Related Questions