西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁編程開發(fā)VC|VC++ → 代碼調(diào)試技巧小集合(C語言描述,但C/C++/Pascal通用)

代碼調(diào)試技巧小集合(C語言描述,但C/C++/Pascal通用)

相關(guān)軟件相關(guān)文章發(fā)表評論 來源:本站整理時間:2010/10/3 23:00:17字體大。A-A+

作者:佚名點擊:532次評論:0次標(biāo)簽: 代碼 調(diào)試技巧

  • 類型:編程輔助大。410KB語言:中文 評分:5.7
  • 標(biāo)簽:
立即下載
1.輸入重定向
有不少人對自己提交到網(wǎng)站里得到的錯誤的結(jié)果而感到莫名其妙。
但有可能由于題目的輸入數(shù)據(jù)巨多,要是手工輸入將會非常累。
例如輸入的數(shù)據(jù)可能多達成千上萬。其實以下將要介紹的代碼技巧,
對于做ACM題目較多的人來說,他(她)們也肯定會知道的。
本文算是在做普及工作吧。
首先,從手工轉(zhuǎn)為自動方式,最顯然的就是從文件讀入的數(shù)據(jù)代替手工。
如果在源代碼里希望把輸入從屏幕輸入定向到一個文件,
可以使用freopen函數(shù)(C/C++均支持此方法),以下為示例:
#include <stdio.h>
int main(void)
{
freopen("in.txt","r",stdin); //輸入從in.txt
int a,b;
while(scanf("%d%d", &a, &b)!=EOF)
{
printf("%d\n", a+b);
}
return 0;
}
這樣你可以把題目的輸入內(nèi)容先保存的in.txt文件里,
在程序運行后看看屏幕輸出,看是否和題目的樣例輸出一樣。
從這里也可以看出,輸入和輸出是完全獨立的,
您不必把所有輸入或輸出保存,直到程序全部計算完畢再輸出,
這樣會很浪費內(nèi)存,我們也不希望你這樣做。
你應(yīng)當(dāng)在你能夠確定輸出內(nèi)容的時候就馬上輸出,能少占用內(nèi)存就少用。
如果你希望本地調(diào)試成功的代碼不用修改就可以直接提交到OJ系統(tǒng)上,
那你應(yīng)該加上如下預(yù)處理(OJ系統(tǒng)通用標(biāo)準(zhǔn),不支持這個特性的OJ就不合格):
#ifdef ONLINE_JUDGE //判斷是不是OJ系統(tǒng)上編譯
#define FINPUT(file) 0 // 如果是,則不重定向到文件
#else
#define FINPUT(file) freopen(file,"r",stdin)
#endif
#include <stdio.h>
int main(void)
{
FINPUT("in.txt"); //如果不是則輸入從本地in.txt
int a,b;
while(scanf("%d%d", &a, &b)!=EOF)
{
printf("%d\n", a+b);
}
return 0;
}
如果你懂得命令行下運行一個程序,那么你可以不用修改源代碼,
假設(shè)你的代碼所生成的程序名是temp.exe,在命令行下運行:
temp.exe<in.txt
一樣實現(xiàn)了相同的功能。
如果程序輸出內(nèi)容過多,你需要保存下來分析的話,那么還可以使用輸出重定向。
如上方法,你也可以定義這樣一個宏:
#define FOUTPUT(file) freopen(file,"w",stdout)
如果輸入輸出均需要重定向,上面的代碼可以改寫為:
#ifdef ONLINE_JUDGE //判斷是不是OJ系統(tǒng)上編譯
#define FINPUT(file) 0 // 如果是,則不重定向到文件
#define FOUTPUT(file) 0
#else
#define FINPUT(file) freopen(file,"r",stdin)
#define FOUTPUT(file) freopen(file,"w",stdout)
#endif
#include <stdio.h>
int main(void)
{
FINPUT("in.txt"); //如果不是則輸入從本地in.txt
FOUTPUT("out.txt");
int a,b;
while(scanf("%d%d", &a, &b)!=EOF)
{
printf("%d\n", a+b);
}
return 0;
}
在命令行下則可以:
temp.exe <in.txt >out.txt

2.斷言和運行時錯誤捕獲
斷言對于初學(xué)者來說,可能是一個很新鮮的名詞。
但這個東西對于軟件調(diào)試來說有一個非常有用的東西,
不過使用的時候也得小心,不正確的使用甚至?xí)m得其反。
首先,斷言就是在邏輯上,你認(rèn)為一定會得到的結(jié)果,
例如你假定內(nèi)存分配一定成功,那么返回值一定不為NULL,
在你包含了頭文件assert.h或者cassert后,就可以使用
assert(exp);
exp是你需要斷言的表達式,bool類型,當(dāng)exp為true的時候,
斷言成功,程序繼續(xù)執(zhí)行,否則程序強制停止,并且發(fā)出警告。
這樣你就可以明確得知程序發(fā)生了邏輯問題,必須進行修改。
但問題就在于,如果你直接使用assert(exp)這個函數(shù),
那么這個斷言不管在什么情況下都會編譯進執(zhí)行文件,
如果提交到OJ上,并且斷言在內(nèi)循環(huán)里,就顯得這個斷言會占用相當(dāng)?shù)臅r間。
如果我們不希望發(fā)布正式版本的軟件或者提交代碼時去掉這個斷言以提升速度,
我們又可以用宏封裝一下:
#ifdef ONLINE_JUDGE //判斷是不是OJ系統(tǒng),非OJ系統(tǒng)調(diào)試可另起名字
#define ASSERT_LEVEL 1
#else
#define ASSERT_LEVEL 0
#endif
#if (ASSERT_LEVEL>=1)
#define ASSERT(exp) _assert(#exp, __FILE__, __LINE__)
#else
#define ASSERT(exp) 0
#endif
double foo(int n) //計算階乘
{
ASSERT(n>=0);
return n*foo(n-1);
}
#include <stdio.h>
int main(void)
{
int n=10;
printf("%d\n", foo(n));
return 0;
}
以上為一個錯誤遞歸算階乘的程序示例,運行一下你就知道斷言的威力了。
那個foo函數(shù)應(yīng)當(dāng)改為:
double foo(int n) //計算階乘
{
ASSERT(n>=0);
if(n==0)return 1;
return n*foo(n-1);
}
使用斷言還有很多技巧和需要注意的東西,這里暫不多說,先自己體會體會吧。

關(guān)于運行時錯誤捕獲,很多人馬上就想到了C++的try。但事實上,
這種方法不一定能把異常都捕獲,但在OJ系統(tǒng)里面,
你任何一個沒有進行處理的異常的拋出都會導(dǎo)致RE(注意main函數(shù)返回非0也RE),
盡管有些異常不會對運行結(jié)果有影響,操作系統(tǒng)也會忽略掉,
于是一般運行的時候用戶也無法發(fā)現(xiàn)已經(jīng)出現(xiàn)異常。
同樣,VC也是MS的產(chǎn)品,連操作系統(tǒng)都忽略的異常,用它去調(diào)試同樣也忽略,
你不能依賴VC調(diào)試器得到所有異常的信息,
所以你不要以為VC上調(diào)試沒有出現(xiàn)任何異常信息就以為那真的是正確的代碼,
有可能是系統(tǒng)忽略掉,也有可能是你自己的測試用的數(shù)據(jù)沒有觸發(fā)它。
對于這個問題目前本人也沒有較好的解決辦法,所以還是建議你,
養(yǎng)成良好的編程習(xí)慣,適當(dāng)?shù)牡胤骄图由蠑嘌,以增加異常被捕獲的機率,
這樣就更容易發(fā)現(xiàn)出錯的地方。

    相關(guān)評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)