簡體   English   中英

如何將文本文件讀入 c++ 中的二維數組?

[英]how do I read a textfile into a 2D array in c++?

我真的很難嘗試將逗號分隔的 integer 文本文件傳遞到 c++ 中的二維數組中。 例如,如果文本文件看起來像

2,4,5,6
3,7,5,3
4,8,4,2
6,7,3,0

請問我怎樣才能把它放入一個 4 x 4 的數組中? 稍后我需要對其進行計算,一旦它位於二維數組中,我就知道如何計算。 先感謝您

到目前為止我有

#include <iostream> 
#include <sstream>
#include <string>
#include <fstream>
using namespace std;
int main()
{

const int row =4;
const int col =4;
int array[row][col];
int r =0;
int c =0;
ifstream inputfile("numbers.txt");
if (!inputfile.is_open())
{cout<<"error"<<endl;
}
string line,num;
int number;
while(get line(inputfile,line))
{
string stream ss(line);
getline(ss,num,',');
number= stop(num);

for (int r=0; r<row;r++)
{
for (int c=0; c<col; c++)
{
array[row][col] =number;
}

}


inputfile.close();
return 0;
}

好消息是你已經收集了正確的拼圖來做你想做的事情。 壞消息是……你把拼圖拼錯了……(但不是很嚴重)。

關鍵是系統地編寫將 csv 文件讀入二維數組所需完成的每個步驟。 (您應該使用std::vector<std::vector<int>> ,但我懷疑 2D 數組是分配要求——知道如何處理基本類型的 arrays 也很好——有一個遺留代碼中有很多)。 從文件中讀取每一行並填充stringstream流,然后使用','作為分隔符使用getline進行解析,一切看起來都很好。

您缺少的是防止讀取的列多於您的存儲空間和多於您聲明的行數的保護措施。 雖然如果您的文件包含您為數組聲明的值的數量,這不會影響您從文件中讀取值,但正確使用基本類型的 arrays 至關重要。 它們的大小是固定的,如果您嘗試寫入超出數組的范圍(您只會損壞程序堆棧),沒有自動分配可以節省您的時間

您如何保護您的 arrays 綁定? 簡單,只需檢查當前行不超過分配的數量並且列的數量相同,例如

    /* read each line, protect row bounds */
    while (r < row && getline (inputfile,line)) {
        int c = 0;      /* declare c local to loop so it is reset each iteration */
        std::string num;
        std::stringstream ss (line);
        /* loop reading from stringstream, protect column bounds */
        while (c < col && getline (ss, num, ',')) {
            try {   /* try/catch exception handling required for stoi conversion */
                array[r][c++] = std::stoi (num);    /* convert, increment col count */
            }
            catch (const std::exception & e) {
                std::cerr << "error: invalid conversion " << e.what() << '\n';
                return 1;
            }
        }
        if (c != col) { /* validate col number of values read & stored */
            std::cerr << "error: invalid number of columns '" << c << "' row: " 
                        << r << '\n';
            return 1;
        }
        r++;    /* increment row count */
    }

還要注意使用try/catch異常處理。 使用std::stoi ,這是您必須驗證轉換的唯一方式,請參閱cppreference.com - std::stoi並注意Exception標題詳細說明了兩個異常( std::invalid_argumentstd::out_of_range )必須是處理。 您不能簡單地猜測所有輸入文件都將采用具有正確值的所需格式並希望獲得最好的結果——您必須驗證每個輸入

這也適用於每行中的列數(以及完成讀取循環時填充的行數)。 當您完成從stringstring讀取時,您需要驗證讀取的列值的數量是預期的數量並且您沒有遇到短行。 注意:這些是所需的最低驗證 您可以自由編寫其他驗證,例如檢查以確保stringstring為空並且附加值不會保持未讀狀態(對代碼的操作不重要,但可能會標記無效格式的輸入文件)

最后,雖然代碼的其余部分只是簡單地輸出值,但請看一下為什么“使用命名空間 std;” 被認為是不好的做法? . 早日養成好習慣。 這也意味着不要硬編碼文件名 arguments to main()提供了一種在啟動時將所需信息傳遞到程序中的方法——使用它們,或者至少提示打開文件名。

此外,始終在啟用警告的情況下進行編譯。 這意味着-Wall -Wextra -pedantic -Wshadow用於 gcc/clang 和 VS /W3 包括-Wshadow你會發現你在for (int c=0; c<col; c++)中隱藏了變量c的先前聲明

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

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

#define ROW 4       /* while const int is fine, if you #define your constants  */
#define COL ROW     /* you have one single location at the top to make changes */

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

    const int row = ROW, col = COL; /* optional, you can just use ROW & COL */
    int array[row][col], r = 0;
    std::string line;

    if (argc < 2) { /* validate at least 1 argument given for filename */
        std::cerr << "error: insufficient arguments\nusage: ./prog filename\n";
        return 1;
    }

    std::ifstream inputfile (argv[1]);  /* open file provided as 1st argument */
    if (!inputfile.is_open()) { /* use std::cerr for error output, handle error */
        std::cerr << "error: file open failed '" << argv[1] << "'.\n";
        return 1;
    }

    /* read each line, protect row bounds */
    while (r < row && getline (inputfile,line)) {
        int c = 0;      /* declare c local to loop so it is reset each iteration */
        std::string num;
        std::stringstream ss (line);
        /* loop reading from stringstream, protect column bounds */
        while (c < col && getline (ss, num, ',')) {
            try {   /* try/catch exception handling required for stoi conversion */
                array[r][c++] = std::stoi (num);    /* convert, increment col count */
            }
            catch (const std::exception & e) {
                std::cerr << "error: invalid conversion " << e.what() << '\n';
                return 1;
            }
        }
        if (c != col) { /* validate col number of values read & stored */
            std::cerr << "error: invalid number of columns '" << c << "' row: " 
                        << r << '\n';
            return 1;
        }
        r++;    /* increment row count */
    }

    if (r < row) {  /* validate row number of arrays stored in 2D array */
        std::cerr << "error: invalid number of rows '" << r << "'\n";
        return 1;
    }

    for (r = 0; r < row; r++) {         /* loop outputting results */
        for (int c = 0; c < col; c++)
            std::cout << " " << array[r][c];
        std::cout << '\n';
    }
}

注意: #define語句是可選的,但在代碼頂部提供一個方便的位置,以便在需要時調整常量)

示例使用/輸出

當您在dat/2darr.csv中輸入文件時,您將執行並接收以下 output:

$ ./bin/read2darrcsv dat/2darr.csv
 2 4 5 6
 3 7 5 3
 4 8 4 2
 6 7 3 0

如果您還有其他問題,請告訴我。

暫無
暫無

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

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