从c ++中的txt文件读取二维数组

Read 2d array from txt file in c++

这是我的代码

#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();
}

这是我的 test.txt 文件

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

我想阅读这个矩阵,但是当使用上面的代码时它显示核心转储输出,谁能给我一个更好的解决方案来做这件事?

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

更好 的替代方法是使用 2D vector,如下所示。在数组上使用 vector 优点 是您 不需要 预先指定(知道)行和列.也就是说,文本输入文件可以有任意多的行和列,并且不需要询问用户(或预先分配)文件有多少行和列。 std::vector 照料 它,如下所示。

下面的程序使用 2D std::vector 以二维方式存储信息(如本例中的整数值)。从文件中读取所有值后,您可以根据需要处理向量。显示的程序从 input.txt 读取数据(int 值)并将这些数据存储在二维 vector 中。此外,该程序 即使 列数不均匀也能正常工作。您可以使用以下程序作为参考(起点)。

#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;
}

上面程序的输出可见here。上面提到的 link.

也给出了读取 int 值的输入文件

使用矢量的优势

  1. 您不需要向用户询问输入文件中的行数和列数。那就是您不必固定(硬编码)数组的大小。

  2. 即使在任何特定行中存在不均匀的条目,上述程序也能正常工作。

  3. std::vector 为您负责内存管理。所以你不必自己使用 newdelete 需要更多 attention/care。(如果你想在 heap[=48 上创建数组=])

还有很多其他方法可以执行特定任务,但我猜你的方法没有错,你只是在第二个 for 循环条件中犯了一个简单的输入错误。所以生病只是为你修复你的代码。 而且你也可以一次只输入一个值。

#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();
}

输出:

因为有很多可能的解决方案,所以我们只展示其中的一些。

基本区别是:

  • 如果我们在编译时知道数组的维度,那么,如果有编译时常量,那么我们仍然可以使用 C 风格数组,或者更好的是 std::array.
  • 如果我们不知道源数据数组的维度,那么我们需要一个可以增长的动态容器,例如std::vector.

在所有情况下,我们都可以将索引运算符 [] 与标准 for 循环或基于范围的 for 循环与引用一起使用。没有区别。


示例:

具有标准 for 循环和基于索引的访问的 C 风格数组

#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";
}

具有基于范围的 for 循环和引用访问的 C 样式数组

#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 带有基于范围的 for 循环

#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";
}

动态解决方案,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";
}

更现代、更紧凑的 C++ 解决方案

#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";
}

而现在,我们想象我们没有任何 vector 甚至 string

为此,我们构建了一个带有一些函数和迭代器的小型 class“DynamicArray”。这可以很容易地扩展。

结果将是在 main 中,只有一个小语句,sourceFileStream >> dada; 会将所有数据读入一个二维数组。

请注意。我们只对流 io 使用流函数,仅此而已。

酷。 . .

#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";
}

基本上,不知何故,一切都是一样的。 . .