首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 解析格式化文字設定檔:自定義語法 + C++ 封裝類完整實作

     編輯:VC 教學

設定檔語法設計

// 註解
// 協定名稱: TL
// 工程: SQ

#DEFINE_BEGIN          // 單值參數區塊開始
@COM_PORT .COM1        // 鍵值以空白/Tab 分隔,行尾可接註解
@COM_BAUDRATE 1200
@STATIONNO 0
#DEFINE_END

#TABLE_BEGIN           // 表格區塊
// ID  識別字串       欄位以 空白/Tab/逗號 分隔,字串內空白保留
0  Ion Detector, ALU1, L1S43
1  Thermal Det, ALU1, L1S39
#TABLE_END

語法規則摘要

  • 單行註解://;
  • 區塊標記:#DEFINE_BEGIN/END、#TABLE_BEGIN/END;
  • 單值:@KEY VALUE,分隔符 space/tab;
  • 表格:第一欄整數 ID,之後欄位 space/tab/comma 分隔,**字串內空白保留**;
  • 檔案 < 48KB,表格 ≤ 100 行 × 4 欄 (含 ID)。

C++ 封裝類 CDataTxt

資料結構

#define TABLE_MAXROW 100
#define TABLE_MAXCOL 5

struct TableRec {
    int nID;
    char s[TABLE_MAXCOL-1][64]; // 除 ID 外欄位
};

class CDataTxt {
public:
    CDataTxt(); ~CDataTxt();
    CString m_szPath;           // 設定檔完整路徑

    BOOL Read();                // 讀入並解析
    BOOL GetDefine(LPCTSTR key, CString& val); // 取單值

    TableRec m_Table[TABLE_MAXROW];
    int m_nRows;

private:
    char m_cbuf[1024*48];       // 原始檔案緩衝
    int m_nBufSize, m_nDataSize;
    CString m_szDefine, m_szTable; // 區塊文字
    int m_nDefineLen, m_nTableLen;

    void DelNote();             // 移除註解
    void FormatTable();         // 正規化表格分隔
};

核心解析邏輯 (節錄)

BOOL CDataTxt::Read() {
    CFile fl;
    if (!fl.Open(m_szPath, CFile::modeRead|CFile::typeBinary)) return FALSE;
    m_nDataSize = fl.Read(m_cbuf, m_nBufSize);
    fl.Close();
    m_cbuf[m_nDataSize] = '\0';

    // 1. 移除註解
    DelNote();

    // 2. 擷取 #DEFINE_BEGIN ... #DEFINE_END 區塊
    //    簡易實現:strstr 定位 → 子字串 → m_szDefine
    // 3. 擷取 #TABLE_BEGIN ... #TABLE_END → m_szTable

    // 4. 解析單值區塊
    //    每行 @KEY VALUE → 存入 map 或線性搜尋
    // 5. 解析表格區塊
    FormatTable(); // 統一分隔符為 \t
    //    逐行 sscanf: "%d %63[^\t] %63[^\t] %63[^\t] %63[^\n]"
    //    填入 m_Table[m_nRows++]

    return TRUE;
}

void CDataTxt::DelNote() {
    char* p = m_cbuf;
    while (*p) {
        if (p[0]=='/' && p[1]=='/') {
            // 找到行尾或檔尾
            char* eol = strchr(p, '\n');
            if (!eol) eol = p + strlen(p);
            memmove(p, eol, strlen(eol)+1); // 覆蓋刪除
        } else p++;
    }
}

void CDataTxt::FormatTable() {
    // 將逗號、多空白/Tab 統一為單一 Tab
    // 便於 sscanf 固定格式解析
}

單值查詢

BOOL CDataTxt::GetDefine(LPCTSTR key, CString& val) {
    // 在 m_szDefine 中逐行比對 @KEY
    // 找到 → 取 VALUE 部分 → val = VALUE; return TRUE;
    return FALSE;
}

使用範例

CDataTxt cfg;
cfg.m_szPath = _T("SQTL.txt");
if (cfg.Read()) {
    CString port, baud;
    cfg.GetDefine(_T("@COM_PORT"), port);     // → ".COM1"
    cfg.GetDefine(_T("@COM_BAUDRATE"), baud); // → "1200"

    for (int i=0; i

擴展建議

  • 改用 std::unordered_map 存單值,查詢 O(1);
  • 表格欄位數動態:改用 vector>;
  • 支援區塊巢狀 / 多檔案 #include;
  • 加入型別轉換輔助:GetInt/GetFloat/GetBool;
  • 寫入功能:Write() 依原格式輸出,保留註解與排版。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved