首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 解析不定長數據文件:結構體設計與高效讀取

     編輯:程式設計綜合問答

面對每行長度不定、每行包含多組 `[C int int]` 格式數據的文本文件,核心挑戰在於:行數未知、每行配對數未知、整數範圍未知。本文提供結構化存儲方案與高效解析代碼。

資料結構設計

採用 「行 → 配對列表」 的兩層動態結構:

// 單個配對
struct Pair {
    int first;   // 對應 [C 1 1] 中的 1
    int second;  // 對應 [C 1 1] 中的 1
};

// 一行數據 (動態數組)
using LineData = std::vector;

// 整個文件 (動態數組)
using FileData = std::vector;

優點:
✅ 無需預知行數與每行配對數
✅ 記憶體按需分配,無浪費
✅ 支援任意大小整數 (配合 `long long`)

高效解析策略:流式讀取 + 字符串分割

避免一次性讀入整個文件 (可能超大),採用 `std::getline` 逐行處理,結合 `std::stringstream` 或手寫狀態機分割。

完整可運行範例 (C++17)

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

struct Pair { int a, b; };

int main() {
    std::ifstream fin("data.txt");
    if (!fin) { std::cerr << "無法開啟文件\n"; return 1; }

    std::vector> allLines;
    std::string line;

    while (std::getline(fin, line)) {
        // 1. 過濾非數據行 (如 ###################begin##line...)
        if (line.find('[') == std::string::npos) continue;

        std::vector pairs;
        std::stringstream ss(line);
        char ch;
        int n1, n2;

        // 2. 利用流提取器自動跳過空白與分隔符
        // 格式: [C 1 1] [C 1 7] ...
        while (ss >> ch) {  // 讀取 '['
            if (ch != '[') continue;
            char c;         // 讀取 'C'
            if (!(ss >> c)) break;
            if (!(ss >> n1 >> n2)) break;  // 讀取兩個 int
            pairs.push_back({n1, n2});
            ss >> ch;  // 讀取 ']' (可選,下輪循環會處理下一個 '[')
        }

        if (!pairs.empty())
            allLines.push_back(std::move(pairs));
    }

    // 3. 驗證輸出
    for (size_t i = 0; i < allLines.size(); ++i) {
        std::cout << "Line " << i+1 << ": ";
        for (auto &p : allLines[i])
            std::cout << "[" << p.a << "," << p.b << "] ";
        std::cout << "\n";
    }
    return 0;
}

關鍵技術點解析

  1. `std::getline`:安全讀取整行,不受行長限制。
  2. `std::stringstream`:將行字符串轉為流,配合 `operator>>` 自動處理空白、分隔符 (`[`, `]`, `C`),直接提取 `int`,比手寫 `strtok`/`sscanf` 更安全、可讀性更高。
  3. 移動語義 `std::move`:將解析好的行數據高效轉移到總容器,避免拷貝。
  4. 異常安全:`std::vector` 自動管理記憶體,無需手動 `malloc`/`free`,杜絕洩漏。

進階:超大文件/極高性能場景

若文件達 GB 級,或需極致速度:

  • 使用 **記憶體映射文件** (`mmap` / `CreateFileMapping`) + 手寫 **SIMD 加速解析器**。
  • 或採用 **流式 Tokenizer** (如 `re2c` 生成的詞法分析器) 直接從緩衝區解析,避免 `stringstream` 開銷。

但對 99% 業務場景,上述 `getline + stringstream` 方案已足夠快且代碼極簡。

常見坑點提醒

  • ❌ 使用固定大小 `char buffer[1024]` + `fgets`:行長超過緩衝區會截斷導致解析錯誤。
  • ❌ `strtok` 修改原字符串且非線程安全;`sscanf` 格式字符串難以應對變長空白。
  • ✅ 善用 C++ 標準庫:`fstream`, `string`, `vector`, `stringstream` 組合能優雅解決 90% 文本解析問題。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved