Visual C++ 作為微軟旗下的旗艦級開發工具,功能強大且應用廣泛,幾乎能覆蓋 Windows 平台上的所有開發需求。然而,龐大的功能體系也意味著極高的學習門檻。儘管經過嚴格測試與持續迭代,核心功能中的 Bug 難以被發現,一旦存在往往極難排查。本文將深入剖析一個經典的 CEdit 控件 Bug,並展示如何運用遞歸算法優雅地化解難題。
假設有一個限制輸入的編輯介面:最多 6 行,每行上限 20 個字元,總計 120 字元。初始狀態下輸入了 60 個字元(圖 1)。
當我們執行以下操作時,異常發生了:
此時問題浮現:第 3 行明明還有空間,卻無法輸入任何字元,甚至整個編輯區都陷入「凍結」狀態。通過調試發現(圖 5),被替換的空格未被顯示,導致第 1、2 行實際變為 21 字元,超出限制。若擴大到 1000 行、200 處此類替換,將造成 200 字元無法輸入,嚴重影響如 SWIFT 報文等對格式要求嚴格的業務系統。
這是一個極具欺騙性的 Bug,難點在於:
核心思路:獲取編輯框全文後,以換行符為遞歸邊界,逐行檢查。若某行第 nMaxCols 位置為空格,則刪除該空格,並遞歸處理下一行(位置 + nMaxCols),最終重構合法字串寫回控件。
CString strText, strObjText, strExchange;
CEdit *pEdit;
UpdateWindow();
pEdit = (CEdit *)GetDlgItem(IDC_ET_CON);
int nPos = 0, nLen = 0;
int nMaxCols = 20;
strObjText = "";
pEdit->GetWindowText(strText);
nPos = strText.Find(" ");
while(nPos != -1)
{
strExchange = strText.Left(nPos);
strText = strText.Right(strText.GetLength() - nPos - 2);
TrimEndNull(nMaxCols, strExchange, nMaxCols);
strObjText = strObjText + strExchange + " ";
nPos = strText.Find(" ");
}
strExchange = strText;
TrimEndNull(nMaxCols, strExchange, nMaxCols);
strObjText = strObjText + strExchange;
pEdit->SetWindowText(strObjText);
UpdateWindow();
void TrimEndNull(int nPos, CString &strExchange, const int nMaxCols)
{
if (nPos >= strExchange.GetLength())
return;
if (strExchange.GetAt(nPos) == ' ')
{
strExchange = strExchange.Left(nPos) +
strExchange.Right(strExchange.GetLength() - nPos - 1);
}
nPos = nPos + nMaxCols;
TrimEndNull(nPos, strExchange, nMaxCols);
}
修復後,原始輸入中的多餘空格被精準清理,插入字元 A、B 後可順利填滿編輯框,不再出現「虛假滿行」導致的輸入阻塞。
本文實戰演示了如何以遞歸算法攻克 VC++ CEdit 控件的隱性 Bug。看似棘手的邏輯錯誤,經過結構化分析與遞歸處理,變得清晰可控。這不僅是技術修復,更是對「分治思想」在工程實踐中威力的生動註腳。