摘要 Visual C++ 是Microsoft編程工具中的老大,它功能強大,使用它幾乎可以開發Windows平台上的任何程序。但同時由於其功能強大,涉及面廣而讓人很難進入VC++的門檻。由於是Microsoft開發工具的拳頭產品,發布前都要經過嚴格的測試,同時不斷地升級維護,因此,其中常用的功能很難發現Bug,一旦存在Bug則很難解決。
關鍵詞 Visual C++; 控件; Bug; Debug
控件是Visual C++中的被封裝的一個類,使用控件,我們能夠很快的開發OOP程序; Bug是程序中的錯誤; Debug就是在程序運行期間進行調試。
Bug描述
如下圖所示界面:
Figure 1
按Confirm按鈕,Debug界面如下:
Figure 2
從strText的值可以看出,Figure 1中的輸入內容沒有" ",並且Figure 1中的內容被限制輸入6×10個字符,每行最多為20個字符,現在對Figure1 中的內容作如下修改:
刪除第三行的8,9兩個字符,也就是說Figure 1中的內容現在只有58個字符,用空格替換Figure 1中內容的第一行與第二行的最後一個字符,如圖:
Figure 3
現在如果在第一行與第二行中間分別加一個字符,出現如下界面:
Figure 4
那麼我想問大家一個問題,在第三行中還能輸入幾個字符? 答案是:不能輸入字符,同時在內容的任何地方都不能輸入字符。通過Debug我們能夠知道其中的原因,請看Debug界面:
Figure 5
從Figure 5中,我們能夠看見,被替換的字符(空格)在Figure 4沒有被顯示出來,同時第一行與第二行中變成了21個字符。少數這樣的情況能夠讓用戶明白,同時能夠方便地修改輸入內容,但如果存在大量這種情況,則就是一個嚴重的問題了,比如:如果上面的文本中有1000行,每行有10個字符,同時有200個上述替換,那麼,表現給用戶的是:如果用戶要填滿編輯框的話,編輯框中有200個字符不能輸入,有200行中的每行內容是11個字符。同時,如果程序的後續處理對上面輸入的每行的字符有嚴格要求的話(比如銀行國際業務結算使用的SWIFT報文等),那麼嚴重的問題將會發生。
問題分析
這是一個非常棘手的問題,存在以下關鍵必須解決:
⑴ 確定這個問題中的空格是用戶需要的,被用戶手工輸入的還是通過我們上述方法形成的;
⑵ 每次輸入字符後,不能取得當前輸入行的字符串;
⑶ 不能取得分隔每行的標志,比如回車換行等;
⑷ 假如在編輯框中存在100行,每行長度為10,那麼如果超過10行存在那樣的問題的話,也很難確定。
解決問題的算法
針對以上存在的問題,在取得編輯框的內容後,可以使用遞歸算法來過濾掉相關輸入。
算法思想:
從第一行開始,以回車換行為一次遞歸調用,把每次的結果加起來。遞歸的思路是:根據每行最大的字符數,對每行進行判斷,如果最後一個字符是空格,則把那個空格刪除,最後,把不需要的空格都刪除掉了。調用程序如下:
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();
遞歸函數如下:
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,使用了大家熟習的遞歸算法,通過對這個Bug的分析,使用遞歸算法後,這個難於解決的問題就變得很簡單了。