在 MFC 中使用 CStdioFile 讀取文本檔案時,若需過濾「非法數據」,關鍵在於明確定義何為「合法」,再針對每行進行解析驗證。本文提供完整讀取框架與三種常見驗證策略。
CStdioFile file;
CString strLine;
CFileException ex;
if (!file.Open(_T("data.txt"), CFile::modeRead | CFile::typeText, &ex)) {
ex.ReportError();
return;
}
while (file.ReadString(strLine)) {
strLine.Trim(); // 移除首尾空白/換行
if (strLine.IsEmpty()) continue; // 跳過空行
// === 此處放入驗證邏輯 ===
if (IsValidLine(strLine)) {
ProcessValidLine(strLine); // 解析、存入結構、顯示等
} else {
LogInvalidLine(strLine); // 記錄或忽略
}
}
file.Close();
要求每行為單一數字,或固定欄位數字:
bool IsValidLine(const CString& line) {
// 允許:整數、負數、浮點數、科學記號
// 正則:^[-+]?\d+(\.\d+)?([eE][-+]?\d+)?$
// MFC 無內建正則,可用 ATL::CAtlRegExp 或手寫解析
// 簡易版:逐字元檢查
int len = line.GetLength();
if (len == 0) return false;
int i = 0;
if (line[0] == '+' || line[0] == '-') i++;
bool hasDigit = false, hasDot = false;
for (; i < len; ++i) {
TCHAR ch = line[i];
if (ch >= '0' && ch <= '9') hasDigit = true;
else if (ch == '.' && !hasDot) hasDot = true;
else return false; // 非法字元
}
return hasDigit;
}
例:ID,Name,Score 三欄,Score 必為數字:
bool IsValidLine(const CString& line) {
CString token;
int curPos = 0;
// 欄位 1: ID (非空)
token = line.Tokenize(_T(","), curPos);
if (token.IsEmpty()) return false;
// 欄位 2: Name (非空)
token = line.Tokenize(_T(","), curPos);
if (token.IsEmpty()) return false;
// 欄位 3: Score (數字)
token = line.Tokenize(_T(","), curPos);
if (token.IsEmpty()) return false;
double val;
// 簡易數字轉換檢查
return _stscanf_s(token, _T("%lf"), &val) == 1;
}
引入 atlrx.h 使用 CAtlRegExp:
#include
bool IsValidLine(const CString& line) {
// 例:行首為 4 位年份,逗號,任意文字,逗號,浮點數
static const TCHAR* pattern = _T("^\\d{4},.+,[-+]?\\d+(\\.\\d+)?$");
CAtlRegExp<> re;
REParseError status = re.Parse(pattern);
if (status != REPARSE_ERROR_OK) return false; // 模式錯誤
return re.Match(line) != FALSE;
}
CStdioFile 內部已緩衝,逐行 ReadString 通常足夠。CAtlRegExp 物件提升為成員/靜態,僅 Parse 一次。PostMessage 更新 UI 進度。CStdioFile 本身不具備「判斷非法」能力,開發者必須:
ReadString 迴圈中逐行解析驗證。建議先在獨立測試程式驗證邏輯,再整合至 MFC 專案。