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.

4
  • Neither of the two suggested duplicates addressed the actual problem here. Commented Jul 1, 2022 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. Commented Jul 1, 2022 at 10:08
  • Unfortunatlly I dont know how to use vector😂 tnak you for the comment I should study that Commented Jul 1, 2022 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 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. Commented Jul 1, 2022 at 10:22

3 Answers 3

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).
Sign up to request clarification or add additional context in comments.

2 Comments

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!
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 stackoverflow.com/questions/12657811 -- my favourite is Mat6 :)
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];

6 Comments

Wasn't me, but I would guess it's because of the raw pointer.
@anastaciu But that is in the OP's code. It's fine to make suggestions to improve code, but it is not obligatory.
I agree, but you know how things are around here. Anyway, it's just me guessing.
Thank you for your solution, I reckon had this problem too, but it still doesn't work for put values into the array😂
@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.
|
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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.