簡體   English   中英

從二維整數數組中的文件中讀取

[英]Read from a file in a 2d integer array

我是 C++ 編碼的新手,我需要從這個結構的文件中讀取:

8
1 0 0 0 1
1 1 1 0 0
1 1 0 0 0
1 1 1 1 0
5

我需要將數字讀入 2 個不同的 int 變量(8 和 5),其余的則讀入 2d int 數組。

到目前為止我所擁有的:

#include<fstream>
#include<iostream>
#include<conio.h>

using namespace std;

ifstream fin("f.in");
ofstream gout("g.out");

int a[30][30], n, x;

int main()
{
    fin>>n;

    for(i=1; i<=n; i++)
        for(j=1; j<=n; j++)
        {
            fin>>a[i][j];

        }
    fin>>x; c[1]=x; s[x]=1;
//other function call .....

    for(i=1; i<=n; i++)
        gout<<c[i]<<" ";

    return 0;
}

代碼正在構建和編譯,但是它不會從文件中讀取。

如果你仍然卡住,那么讓我們一步一步來。

首先不要硬編碼文件名 (並且不要使用magic-number ,例如任何卡在代碼中的數字,而不是為其正確定義常量)。 ifstream fin("f.in"); 如果您有另一個要讀取的文件"f.int2"怎么辦? 這就是函數參數的用途。 對於main()你有argc ,告訴你有多少個參數,和argv ,一個指向每個 args 的指針數組(后跟一個終止的NULL指針)。 使用它們。 例如:

int main (int argc, char **argv) {
...
    if (argc < 2) { /* validate 1-argument available for filename */
        std::cerr << "error: insufficnent input\nusage: " << argv[0]
                << " filename\n";
        return 1;
    }

    std::ifstream fin (argv[1]);    /* open filename given by 1st argument */

注意:第一個參數值argv[0]始終是正在運行的可執行文件名稱,因此您必須檢查總共兩個參數以確保argv[1]

接下來驗證文件是否已打開以供讀取,例如

    if (!fin.good()) {  /* validate file open for reading */
        std::cerr << "error: file open failed '" << argv[1] << "'.\n";
        return 1;
    }

現在讓我們開始閱讀您的輸入文件,我將其命名為2dintarr+stuff.txt並將其放在dat子目錄中,例如

示例輸入文件

$ cat dat/2dintarr+stuff.txt
8
1 0 0 0 1
1 1 1 0 0
1 1 0 0 0
1 1 1 1 0
5

"+stuff"85 ,它們與要存儲的二維值數組無關。 85很容易處理,只需將整行讀入一個string ,從該行創建一個stringstream ,然后循環並從 stringstream 中讀取整數,直到讀完數字為止。 如果您在用完數字之前只讀取一個值,那么您可以簡單地將這些值存儲在不是您的數組的地方(例如在名為notarr的向量中)。 如果該行中有多個值,則將所有值存儲在一個向量中,並將該向量添加為向量向量中的一行。

聽起來很復雜,其實不然。 C++ 提供了容器,允許您像處理數組一樣向它們添加和刪除值,但更好的是,容器會自動為您管理內存,根據需要分配更多內存,並在沒有更多引用時釋放內存容器。 其中一個容器是vector ,您可以將其簡單地視為一維數組。 C++ 允許容器包含其他容器。 所以當你需要一個二維數組時,你想要的是一個向量的向量。

在您的情況下,您需要一個string來保存您讀取的每一行數據,您需要您的數組的向量arr向量,然后另一個向量來保存不屬於您的數組的"+stuff" - 稱為notarr . 聲明如下:

#include <string>
#include <vector>
...
    std::string line;                       /* string for reading each line */
    std::vector<std::vector <int>> arr;     /* vector<vector<int>> (2D arr) */
    std::vector<int> notarr;                /* vector to hold single values */

現在剩下的就是讀取每一行,然后從該行創建一個字符串流,這樣您就可以從該行循環讀取整數,直到讀完數字為止。 (您不能只使用fin >> number;在循環中,因為讀取 iostream 將跳過前導空格'\\n'是空格,因此嘗試在文件流本身上使用>> - 您永遠無法知道有多少個值在行中, >>只會跳過'\\n'作為空格。

如何解決? 使用stringstream 基本上,一個字符串流相當於一個可以用作流的緩沖區。 因此,您從文件中讀取一行數據,從中創建一個字符串流,然后循環while (ss >> value)當它到達字符串流(即緩沖區)的末尾時將停止,因為沒有其他內容可以讀取您可以確定原始行中包含多少個值。 (你會一遍又一遍地使用這種技術)

例子:

    while (getline (fin, line)) {  /* read each remaining data line */
        int i;
        std::vector<int> tmp;           /* vector<int> for each line */
        std::stringstream ss (line);    /* stringstream to read from */
        while (ss >> i)                 /* read int from stringstream */
            tmp.push_back(i);           /* add to tmp vector */
        if (tmp.size() == 1)            /* if single value in line */
            notarr.push_back(i);        /* add value to notarr */
        else if (tmp.size() > 1)        /* if multiple values in line */
            arr.push_back(tmp);         /* add tmp vector to arr */
    }

在上面,您只需將每一行讀入line ,創建 stringsteam ss ,然后使用臨時向量tmp ,將每個值加載到臨時向量中。 完成后,您只需檢查tmp向量中有多少元素。 如果是85 ,則將其添加到向量notarr ,如果超過 1,則tmp包含二維數組的一行,因此將其添加到arr 就是這樣。

總而言之,您可以執行以下操作:

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

int main (int argc, char **argv) {

    std::string line;                       /* string for reading each line */
    std::vector<std::vector <int>> arr;     /* vector<vector<int>> (2D arr) */
    std::vector<int> notarr;                /* vector to hold single values */

    if (argc < 2) { /* validate 1-argument available for filename */
        std::cerr << "error: insufficnent input\nusage: " << argv[0]
                << " filename\n";
        return 1;
    }

    std::ifstream fin (argv[1]);    /* open filename given by 1st argument */
    if (!fin.good()) {  /* validate file open for reading */
        std::cerr << "error: file open failed '" << argv[1] << "'.\n";
        return 1;
    }

    while (getline (fin, line)) {  /* read each remaining data line */
        int i;
        std::vector<int> tmp;           /* vector<int> for each line */
        std::stringstream ss (line);    /* stringstream to read from */
        while (ss >> i)                 /* read int from stringstream */
            tmp.push_back(i);           /* add to tmp vector */
        if (tmp.size() == 1)            /* if single value in line */
            notarr.push_back(i);        /* add value to notarr */
        else if (tmp.size() > 1)        /* if multiple values in line */
            arr.push_back(tmp);         /* add tmp vector to arr */
    }

    std::cout << "2D array of values:\n\n";
    for (auto& i : arr) {           /* loop over rows */
        for (auto& j : i)           /* loop over each value in column */
            std::cout << " " << j;  /* output value */
        std::cout << '\n';          /* tidy up with newline */
    }

    std::cout << "\nSingle-values:\n\n";
    for (auto& i: notarr)           /* output values not part of array */
        std::cout << " " << i;      
    std::cout << '\n';              /* tidy up with newline */
}

注:矢量容器提供.push_back().size()成員函數,讓您有一個值添加到載體,告訴你有很多元素分別被包含在其中。)

示例使用/輸出

$ ./bin/rd2dintarr+stuff dat/2dintarr+stuff.txt
2D array of values:

 1 0 0 0 1
 1 1 1 0 0
 1 1 0 0 0
 1 1 1 1 0

Single-values:

 8 5

仔細檢查一下,如果您還有其他問題,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM