-1

This is my code

#include<bits/stdc++.h>
using namespace std;

int main()
{
    char arr1[10][10];
    cout << "Reading Start" << endl;
    ifstream rfile("test.txt");
    rfile.getline(arr1[10], 10);
    int i, j;
    for (i = 0; i < 6; i++)
    {
        for (j = 0; i < 6; j++)
        {
            cout << arr1[i][j];
        }
    }
    cout << "\nRead Done" << endl << endl;
    rfile.close();
}

This is my test.txt file

0 4 7 0 0 0
4 0 0 5 3 0
7 0 0 0 6 0
0 5 3 0 0 2
0 3 4 0 0 2
0 0 0 2 2 0

I want to read this matrix but when using the above code then it shows core dumped output, can anyone give me a better solution to do this thing?

mch
  • 9,424
  • 2
  • 28
  • 42
Sana Mev
  • 111
  • 8
  • refer here:https://stackoverflow.com/questions/36708370/reading-from-txt-file-into-two-dimensional-array-in-c – gretal Dec 13 '21 at 05:22
  • Why do you define a 2D array for your data, then (attempt to) read only one line? You might have a severe misunderstanding of how [`getline`](https://en.cppreference.com/w/cpp/io/basic_istream/getline) works. – JaMiT Dec 13 '21 at 05:37

3 Answers3

2

can anyone give me a better solution to do this thing?

A better alternative would be to use a 2D vector as shown below. The advantage of using a vector over an array is that you don't need to specify(know) the rows and columns beforehand. That is, the text input file can have as many rows and columns and there is no need to ask the user(or preallocate) how many rows and columns does the file have. std::vector will take care of it as shown below.

The below program uses a 2D std::vector for storing information(like integers values in this case) in 2D manner. After reading all the values from the file you can process the vector according to your needs. The program shown reads data(int values) from input.txt and store those in a 2D vector. Also, this program works even if there are uneven number of columns. You can use the below program as a reference(starting point).

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include<fstream>
int main() {
    std::string line;
    int word;
    
    std::ifstream inFile("input.txt");
    
    //create/use a std::vector instead of builit in array 
    std::vector<std::vector<int>> vec;
    
    if(inFile)
    {
        while(getline(inFile, line, '\n'))        
        {
            //create a temporary vector that will contain all the columns
            std::vector<int> tempVec;
            
            std::istringstream ss(line);
            
            //read word by word(or int by int) 
            while(ss >> word)
            {
                //std::cout<<"word:"<<word<<std::endl;
                //add the word to the temporary vector 
                tempVec.push_back(word);
            }      
            //now all the words from the current line has been added to the temporary vector 
            vec.emplace_back(tempVec);
        }    
    }
    else 
    {
        std::cout<<"file cannot be opened"<<std::endl;
    }
    
    inFile.close();
    //now you can do the whatever processing you want on the vector

    //lets check out the elements of the 2D vector so the we can confirm if it contains all the right elements(rows and columns)
    for(std::vector<int> &newvec: vec)
    {
        for(const int &elem: newvec)
        {
            std::cout<<elem<<" ";
        }
        std::cout<<std::endl;
    }
    return 0;
}

The output of the above program can be seen here. The input file through which int values are read is also given at the above mentioned link.

Advantages of using vector

  1. You don't need to ask the user for the number of rows and columns in the input file. That is you don't have to fix(hardcode) the size of your array.

  2. The above program works even if there are uneven entries in any particular row.

  3. std::vector takes care of memory management for you. So you don't have to use new and delete by yourself which needs more attention/care.(in case you're thinking of creating array on heap)

Jason
  • 36,170
  • 5
  • 26
  • 60
  • This is a nice solution no doubt, but doing it with vectors is a whole different thing. anyways nice solution – Lalit Kumar Dec 13 '21 at 06:07
  • @LalitKumar What do you mean by a whole different thing? The OP asked for a better solution and *Anoop* provided it. Also, `std::vector` is better suited for OP's purpose(what OP is looking for) than using built in array. Obviously i agree with you that this is a nice solution. – Jason Dec 13 '21 at 06:18
  • @JasonLiam Vectors in general perform differently compared to arrays. – Lalit Kumar Dec 13 '21 at 06:19
1

Because there are so many possible solutions, let us just show some of them.

The basic difference is:

  • If we know the dimensions of the array at compile time, so, if there are compile time constants, then we can still use a C-Style array, or better, a std::array.
  • If we do not know the dimensions of the source data array, then we need a dynamic container that can grow, for example a std::vector.

In all cases, we can use the index operator [] with a standard for loop or a range based for loop with references. There is no difference.


Examples:

C-Style array with standard for loops and index based access

#include <iostream>
#include <fstream>

constexpr int NumberOfRows = 6;
constexpr int NumberOfColumns = 6;

int main() {

    // Open the sourcefile
    std::ifstream sourceFileStream{ "test.txt" };

    // And check, if it could be opened
    if (sourceFileStream) {

        // Define 2D array to hold all data and initialize it with all 0
        char array2D[NumberOfRows][NumberOfColumns]{};

        // Read the rows and columns from the source file
        for (int row = 0; row < NumberOfRows; ++row)
            for (int col = 0; col < NumberOfColumns; ++col)
                sourceFileStream >> array2D[row][col];

        // Debug output
        for (int row = 0; row < NumberOfRows; ++row) {
            for (int col = 0; col < NumberOfColumns; ++col)  std::cout << array2D[row][col] << ' ';
            std::cout << '\n';
        }
    }
    else std::cerr << "\nError: Could not open source file\n\n";
}

C-Style array with range based for loop and reference access

#include <iostream>
#include <fstream>

constexpr int NumberOfRows = 6;
constexpr int NumberOfColumns = 6;

int main() {

    // Open the sourcefile
    std::ifstream sourceFileStream{ "test.txt" };

    // And check, if it could be opened
    if (sourceFileStream) {

        // Define 2D array to hold all data and initialize it with all 0
        char array2D[NumberOfRows][NumberOfColumns]{};

        // Read the rows and columns from the source file
        for (auto& row : array2D)
            for (auto& col : row)
                sourceFileStream >> col;

        // Debug output
        for (const auto& row : array2D) {
            for (const auto& col : row) std::cout << col << ' ';
            std::cout << '\n';
        }
    }
    else std::cerr << "\nError: Could not open source file\n\n";
}

C++ std::array with range based for loop

#include <iostream>
#include <fstream>
#include <array>

constexpr int NumberOfRows = 6;
constexpr int NumberOfColumns = 6;

int main() {

    // Open the sourcefile
    std::ifstream sourceFileStream{ "test.txt" };

    // And check, if it could be opened
    if (sourceFileStream) {

        // Define 2D array toholdall data and initialize it with all 0
        std::array<std::array<char, NumberOfColumns>, NumberOfRows> array2D{};

        // Read the rows and columns from the source file
        for (auto& row : array2D)
            for (auto& col : row)
                sourceFileStream >> col;

        // Debug output
        for (const auto& row : array2D) {
            for (const auto& col : row) std::cout << col << ' ';
            std::cout << '\n';
        }
    }
    else std::cerr << "\nError: Could not open source file\n\n";
}

Dynamic solution, with a std::vector

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

int main() {

    // Open the sourcefile
    std::ifstream sourceFileStream{ "test.txt" };

    // And check, if it could be opened
    if (sourceFileStream) {

        // Define 2D array to hold all data and initialize it with all 0
        std::vector<std::vector<char>> array2D{};

        // Read the rows and columns from the source file
        std::string line{};
        while (std::getline(sourceFileStream, line)) {

            // Add a new row to our matrix
            array2D.push_back(std::vector<char>{});

            // Read all column data
            char c{};
            for (std::istringstream iss(line); iss >> c; array2D.back().push_back(c))
                ;
        }
        // Debug output
        for (const auto& row : array2D) {
            for (const auto& col : row) std::cout << col << ' ';
            std::cout << '\n';
        }
    }
    else std::cerr << "\nError: Could not open source file\n\n";
}

More modern and compact C++ solution

#include <vector>
#include <string>
#include <iterator>

int main() {

    // Open the sourcefile and check, if it could be opened
    if (std::ifstream sourceFileStream{ "test.txt"}; sourceFileStream) {
    
        // Define 2D array to hold all data and initialize it with all 0
        std::vector<std::vector<char>> array2D{};

        // Read the rows and columns from the source file
        for (std::string line{}; std::getline(sourceFileStream, line);) {

            std::istringstream iss(line);
            array2D.push_back({ std::istream_iterator<char>(iss), {} });
        }


        // Debug output
        for (const auto& row : array2D) {
            for (const auto& col : row) std::cout << col << ' ';
            std::cout << '\n';
        }
    }
    else std::cerr << "\nError: Could not open source file\n\n";
}

And now, we imagine that we do not have any vector or even a string.

For that, we build a small class "DynamicArray" with some functions and an iterator. This can easily be extended.

And the result will be that in main, only one small statement, sourceFileStream >> dada; will read all the data into a 2d array.

Please note. We are only using stream functions for stream io, nothing more.

Cool . . .

#include <iostream>
#include <sstream>
#include <fstream>

// The Dynamic Array has an initial capacity. 
// If more elements will be added, there will be a reallocation with doublecapacity
constexpr unsigned int InitialCapacity{ 4 };

// Definition of simple dynamic array class
template <typename T>
class DynamicArray {

protected:
    // Internal data ------------------------------------------------------------------------------
    T* data{};                                 // Dynamic Storage for Data
    unsigned int numberOfElements{};           // Number oe elements currently in the container
    unsigned int capacity{ InitialCapacity };  // Current maximum capacity of the container

public:
    // Construction and Destruction ---------------------------------------------------------------
    DynamicArray() { data = new T[capacity]; } // Default constructor. Allocate new memory

    DynamicArray(const DynamicArray& other) {  // Copy constructor. Make a deep copy
        capacity = numberOfElements = other.numberOfElements;
        data = new T[capacity];                // Get memory, same size as other container
        for (size_t k = 0; k < other.numberOfElements; ++k)
            data[k] = other.data[k];          // Copy data
    }
    ~DynamicArray() { delete[] data; }         // Destructor: Release previously allocated memory

    bool empty() { return numberOfElements == 0; }

    void clear() { numberOfElements = 0; };    // Clear will not delete anything. Just set element count to 0

    void push_back(const T& d) {               // Add a new element at the end
        if (numberOfElements >= capacity) {    // Check, if capacity of this dynamic array is big enough
            capacity *= 2;                     // Obviously not, we will double the capacity
            T* temp = new T[capacity];         // Allocate new and more memory
            for (unsigned int k = 0; k < numberOfElements; ++k)
                temp[k] = data[k];             // Copy data from old memory to new memory
            delete[] data;                     // Release old memory
            data = temp;                       // And assign newly allocated memory to old pointer
        }
        data[numberOfElements++] = d;          // And finally, stor the given fata at the end of the container
    }

    // Add iterator properties to class ---------------------------------------------------------------
    // Local class for iterator
    class iterator{
        T* iter{};                             // This will be the iterator 
    public:                                    // Define alias names necessary for the iterator functionality
        using iterator_category = std::input_iterator_tag;
        using difference_type = std::ptrdiff_t;
        using value_type = T;
        using pointer = T*;
        using reference = T&;

        explicit iterator(T* i) : iter(i) {};  // Default constructor for the iterator
        T operator *() const { return *iter; } // Dereferencing
        iterator& operator ++() { ++iter; return *this; } // Pre-Increment
        bool operator != (const iterator& other) { return iter != other.iter; }  // Comparison
    };

    // Begin and end function to initiliaze an iterator
    iterator begin() const { return iterator(data); }
    iterator end() const { return iterator (data + numberOfElements); }

    // Operators for class------------------------ ---------------------------------------------------------------

    T& operator[] (const size_t i) { return data[i]; }           // Index operator, get data at given index. No boundary chek

    DynamicArray& operator=(const DynamicArray& other) {         // Assignment operator. Make a deep copy
        if (this != &other) {                                    // Prevent self-assignment
            delete[] data;                                       // Release any previosly existing memory
            capacity = numberOfElements = other.numberOfElements;// Take over capacity and number of elements from other container
            data = new int[capacity];                            // Get new memory, depending on size of other 
            for (unsigned int k = 0; k < numberOfElements; ++k)  // Copy other data
                data[k] = other.data[k];
        }
        return *this;
    }

    // Extractor and Inserter ------------------------ ---------------------------------------------------------------
    friend std::istream& operator >> (std::istream& is, DynamicArray& d) {
        std::stringstream ss{};
        for (char c{}; (is.get(c) and c != '\n'); ss << c);      // Read one line until newline into a stringstream
        for (T x{}; ss >> x; d.push_back(x));                    // Now extract the data from there
        return is;
    }
    friend std::ostream& operator << (std::ostream& os, const DynamicArray& d) {
        for (unsigned int k = 0; k < d.numberOfElements; ++k)    // Ultra simple output
            os << d.data[k] << ' ';
        return os;
    }
};

// -----------------------------------------------------------------------------------------------------------
// Very simple 2d array. Derived from standard dynamic array and just defining differen input and output
template <typename T>
class Dynamic2dArray : public DynamicArray<DynamicArray<T>> {

public:
    friend std::istream& operator >> (std::istream& is, Dynamic2dArray& d) {
        for (DynamicArray<T> temp{}; is >> temp; d.push_back(temp), temp.clear());
        return is;
    }
    friend std::ostream& operator << (std::ostream& os, const Dynamic2dArray& d) {
        for (unsigned int k = 0; k < d.numberOfElements; ++k) 
            os << d.data[k] << '\n';
        return os;
    }
};

// -----------------------------------------------------------------------------------------------------------
int main() {

    // Open the sourcefile and check, if it could be opened
    if (std::ifstream sourceFileStream{ "test.txt" }; sourceFileStream) {

        // Define 2D array to hold all data and initialize it with all 0
        Dynamic2dArray<int> dada;

        // Read complete matrix from file
        sourceFileStream >> dada;

        // Debug output. Show complete Matrix
        std::cout << dada;
    }
    else std::cerr << "\n\nError. Could not open source file\n\n";
}

Basically, everything is the same, somehow . . .

A M
  • 14,694
  • 5
  • 19
  • 44
0

There are a lot of other ways to perform the specific task, but i guess your method is not wrong, and you have just made a simple typing mistake in your second for loop condition. so ill just fix your code for you. and also you could just input single values at a time as u go.

#include<bits/stdc++.h>
using namespace std;
int main()
{
    char arr1[10][10];
    cout <<"Reading Start" <<endl;
    ifstream rfile("test.txt");
    int i,j;
    for(i=0;i<6;i++){
        for(j=0;j<6;j++){
            rfile >> arr1[i][j];
            cout << arr1[i][j] << " ";
        }
        cout << endl;
    }

    cout <<"\nRead Done" <<endl<<endl;
    rfile.close();
}

Output : enter image description here

Lalit Kumar
  • 134
  • 1
  • 9
  • This is not a better solution that the OP is looking for. In your program you have hardcoded the size of the array which is not desirable in any real/practical program. – Jason Dec 13 '21 at 06:25
  • but i think if you look into properties of array, @JasonLiam you cant ever perform a matrix without knowing its size. as he have tagged his question with arrays i am not trying to use vector. sorry i know vectors are good but he have tagged arrays. – Lalit Kumar Dec 13 '21 at 06:27
  • @JasonLiam [link](https://stackoverflow.com/help/tagging) – Lalit Kumar Dec 13 '21 at 06:33
  • Note that the OP has asked for a better solution. The OP may not be aware of `vector`. So he/she was not able to tag `vector`. – Jason Dec 13 '21 at 06:36