0

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.

halfer
  • 19,824
  • 17
  • 99
  • 186
Sion
  • 36
  • 7
  • Neither of the two suggested duplicates addressed the actual problem here. – john Jul 01 '22 at 10:08
  • OT: There are far better tools to use for dynamic arrays, namely `std::vector`, raw pointers can get out of hand fast. – anastaciu Jul 01 '22 at 10:08
  • Unfortunatlly I dont know how to use vector tnak you for the comment I should study that – Sion Jul 01 '22 at 10:13
  • 1
    @Sion, don't let that stop you ;) there are many, many topics around here about this matter, you just have to look here's one https://stackoverflow.com/q/15138785/6865932, now you have 2 options here make a 2D vector, or make a flat vector behave like a 2D vector, again, there are many topics about this here, you'll see that when you learn how to use it, you'll never wan't to use anything else, and you know, an integral part of a programmer's job is to always keep learning. – anastaciu Jul 01 '22 at 10:22

3 Answers3

1

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];
john
  • 85,011
  • 4
  • 57
  • 81
  • Wasn't me, but I would guess it's because of the raw pointer. – anastaciu Jul 01 '22 at 10:10
  • @anastaciu But that is in the OP's code. It's fine to make suggestions to improve code, but it is not obligatory. – john Jul 01 '22 at 10:11
  • I agree, but you know how things are around here. Anyway, it's just me guessing. – anastaciu Jul 01 '22 at 10:12
  • Thank you for your solution, I reckon had this problem too, but it still doesn't work for put values into the array – Sion Jul 02 '22 at 08:05
  • @Sion Try this `arrival.clear(); arrival.seekg(0);` When you get to the end of file in your first pass you put the stream into an error state. You need to clear that state before you continue, that's what `clear` does. – john Jul 02 '22 at 08:14
  • @Sion If that works I'll update the answer. – john Jul 02 '22 at 08:15
1

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
rturrado
  • 7,699
  • 6
  • 42
  • 62
1

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).
alle_meije
  • 2,424
  • 1
  • 19
  • 40
  • Thank you so much! I needed "go back to start" part for solve my problem, and also, I can learn about vector thought this code! – Sion Jul 02 '22 at 08:40
  • Pleased to hear! Good to keep in mind that a vector of vectors is not a *contiguous* container. Every element `matrix[i]` is the start of a vector object which can be anywhere in memory. For a contiguous block of memory for 2D storage, you could try https://stackoverflow.com/questions/12657811 -- my favourite is Mat6 :) – alle_meije Jul 06 '22 at 09:40