黎自強(qiáng) 羅翠英
摘要:本文討論了C語(yǔ)言的前綴++(前綴--)與后綴++(后綴--)運(yùn)算符的優(yōu)先級(jí)、C程序設(shè)計(jì)和調(diào)試的幾點(diǎn)技巧,更好地讓學(xué)生進(jìn)一步學(xué)好C語(yǔ)言,掌握C語(yǔ)言程序設(shè)計(jì),提高學(xué)生的軟件開(kāi)發(fā)能力。
關(guān)鍵詞:C語(yǔ)言程序設(shè)計(jì);運(yùn)算符;優(yōu)先級(jí);二維數(shù)組
中圖分類號(hào):G642 文獻(xiàn)標(biāo)識(shí)碼:B
1引言
“C語(yǔ)言程序設(shè)計(jì)”課程對(duì)理工科專業(yè)學(xué)生來(lái)說(shuō),是一門(mén)非常重要的基礎(chǔ)課程,但初學(xué)起來(lái)十分困難。其主要原因是:(1) C語(yǔ)言的數(shù)據(jù)類型和運(yùn)算符多、表達(dá)式復(fù)雜;(2) 初學(xué)者在學(xué)習(xí)過(guò)程中必須暫時(shí)保留人的思維形式,使用計(jì)算機(jī)的程序模式工作。為了使學(xué)生學(xué)習(xí)好“C語(yǔ)言程序設(shè)計(jì)”這門(mén)課程,許多教育工作者對(duì)教學(xué)方法進(jìn)行了深入的探索,積累了豐富的教學(xué)經(jīng)驗(yàn)。例如:文獻(xiàn)[1]介紹了C語(yǔ)言程序設(shè)計(jì)的案例教學(xué)方法,文獻(xiàn)[2]討論了C語(yǔ)言程序設(shè)計(jì)中關(guān)于自增和自減運(yùn)算符的理解和編程要點(diǎn)。盡管如此,如何使學(xué)生能更好地掌握C語(yǔ)言程序設(shè)計(jì)仍然值得教育工作者進(jìn)一步探索。本文將自增和自減運(yùn)算符分為優(yōu)先級(jí)不同的前綴++(前綴--)與后綴++(后綴--)兩種運(yùn)算符,給出若干程序設(shè)計(jì)和調(diào)試的技巧,使學(xué)生更好地掌握C語(yǔ)言程序設(shè)計(jì)。
2關(guān)于自增和自減運(yùn)算符
如果C語(yǔ)言表達(dá)式存在自增或自減運(yùn)算符,則其值的計(jì)算和表達(dá)式中變量值的改變很容易弄錯(cuò)。文獻(xiàn)[3~5]規(guī)定前綴自增(自減)和后綴自增(自減)運(yùn)算符的優(yōu)先級(jí)相同,都大于算術(shù)運(yùn)算符,結(jié)合方向是自右向左。它們的區(qū)別是:前綴自增(自減)是在使用前增加或自減少1,而后綴自增(自減)是在使用后增加或自減少1。作者在教學(xué)實(shí)踐中發(fā)現(xiàn):學(xué)生按上述規(guī)則并不容易讀懂程序和編寫(xiě)程序。本文把前綴自增(自減)和后綴自增(自減)運(yùn)算符看成兩種運(yùn)算符,且規(guī)定前綴自增(自減)運(yùn)算符的優(yōu)先級(jí)大于算術(shù)運(yùn)算符,后綴自增(自減)運(yùn)算符的優(yōu)先級(jí)低于賦值運(yùn)算符,僅高于逗號(hào)運(yùn)算符。本文的這一規(guī)則比較適合我們常常使用的Turbo C編譯系統(tǒng),也容易被學(xué)生理解和掌握。
例1:若i=3,則執(zhí)行賦值語(yǔ)句j=++i;時(shí)是將i的值先變?yōu)?,再賦值給j,j的值變?yōu)?;而執(zhí)行賦值語(yǔ)句j=i++;時(shí)是先將i的值賦給j,j的值為3,然后i的值先變?yōu)?。
例2:若i=3,則執(zhí)行賦值語(yǔ)句j=(i++)+(i++)+(i++);時(shí)是將三個(gè)i的值先加得12賦給j,j的值變12,然后i的值再三次增1變?yōu)?;而執(zhí)行賦值語(yǔ)句j=(++i)+(++i)+(++i);時(shí)是先將i的值再三次增1變?yōu)?,然后將三個(gè)i的值相加得18賦給j,j的值為18。
例3:若i=3,則執(zhí)行賦值語(yǔ)句printf(“%d”, -i++);時(shí)是將先輸出i的相反數(shù)-3,然后i的值再增1變?yōu)?;而執(zhí)行賦值語(yǔ)句printf(“%d”, -++i);時(shí)根據(jù)優(yōu)先級(jí)相同的負(fù)號(hào)與前綴自增運(yùn)算符為自右向左的結(jié)合方向,則是先將i的值增1變?yōu)?,然后再輸出i的相反數(shù)-4。
值得注意的兩個(gè)問(wèn)題:
(1) 當(dāng)一個(gè)變量出現(xiàn)在一個(gè)函數(shù)的多個(gè)參數(shù)中時(shí),不能將自增或自減運(yùn)算符作用于該變量,否則用本文規(guī)則不能正確計(jì)算表達(dá)式的值和輸出結(jié)果。例如:若i=3,則執(zhí)行賦值語(yǔ)句printf(“%d, %d”, i,i*i++);時(shí)其輸出結(jié)果為(4,12);而執(zhí)行賦值語(yǔ)句printf(“%d ,%d”, i*i++,i);時(shí)其輸出結(jié)果為(12,3)。
(2) 當(dāng)自增或自減運(yùn)算符出現(xiàn)在邏輯表達(dá)式中時(shí),自增或自減運(yùn)算可能不被計(jì)算。例如:
若i=1,j=1,k=1,在計(jì)算表達(dá)式++i||++j&&++k時(shí),因++i非0,不再計(jì)算++j&&++k部分,直接得到整個(gè)表達(dá)式的值為1,因此,計(jì)算表達(dá)式后,變量i的值為2,而j和k沒(méi)有執(zhí)行自增加運(yùn)算,其值都為1。
基金項(xiàng)目:2006年湘潭大學(xué)校級(jí)精品課程基金(湘大教發(fā)[2007]20)。
作者簡(jiǎn)介:黎自強(qiáng)(1963-),男,教授,博士,研究方向?yàn)橛?jì)算機(jī)圖形學(xué),計(jì)算機(jī)視覺(jué),智能計(jì)算。羅翠英(1966-),女,湖南益陽(yáng)人,湖南工業(yè)大學(xué)講師,研究方向?yàn)橛?jì)算機(jī)圖形學(xué)。
3關(guān)于scanf()函數(shù)和實(shí)型二維數(shù)組
在C語(yǔ)言程序設(shè)計(jì)中,常常利用scanf()函數(shù)對(duì)二維實(shí)型數(shù)組賦值,例如:下面的程序段是從鍵盤(pán)輸入10個(gè)數(shù)到二維實(shí)型數(shù)組x中。
voidmain()
{ int i,j;
float x[5][2];
for(i=1;i<5;i++)
for(j=1;j<2;j++)
scanf(“%f”,&x[i][j]);
for(i=1;i<5;i++)
for(j=1;j<2;j++)
printf(“%f”,x[i][j]);
}
上述程序在Turbo C2.0集成開(kāi)發(fā)環(huán)境下編譯和連接是沒(méi)有錯(cuò)誤的,但運(yùn)行時(shí)出現(xiàn)如下錯(cuò)誤信息:
scanf:floating point formats not linked
Abnormal program termination
解決的方法有兩種,方法一:
(1) float x[10][2]—>float x[10][2], t;
(2) scanf(“%f”,&x[i][j]);—>{scanf (“%f ”, &t);x[i][j]=t;}
方法二:在scanf()函數(shù)的%f前面保留一個(gè)空格,即:scanf(“_%f”,&x[i][j]);
4關(guān)于getch()的妙用
4.1查看顯示結(jié)果
一般,在Turbo C2.0集成開(kāi)發(fā)環(huán)境下,運(yùn)行C程序后即刻返回到編輯狀態(tài)。如果想看到程序執(zhí)行的結(jié)果,就必須按Alt+F5鍵。如果在程序的結(jié)束行前加一個(gè)語(yǔ)句getch();則程序運(yùn)行暫停在顯示結(jié)果的界面,按任意鍵才返回編輯狀態(tài)。這樣能讓程序員更簡(jiǎn)捷地查看結(jié)果。
4.2調(diào)試程序
一個(gè)能夠編譯、連接和運(yùn)行的C程序,只有在沒(méi)有結(jié)構(gòu)上的錯(cuò)誤的前提下才能保證其結(jié)果正確。這一步是靠調(diào)試程序來(lái)完成。對(duì)于初學(xué)C語(yǔ)言程序設(shè)計(jì)的學(xué)生來(lái)說(shuō),迅速找出程序結(jié)構(gòu)上的錯(cuò)誤是一個(gè)至關(guān)重要的問(wèn)題。一個(gè)簡(jiǎn)單、可行方法就是利用printf()和getch()的組合語(yǔ)句在關(guān)鍵點(diǎn)跟蹤程序的執(zhí)行。
例如:程序段1-14是求1+2+3+…+n的和(正整數(shù)n由文件輸入)。
1#include
2main()
3{
4int i=0,n=0;
5long sum=0;
6FILE *fp=NULL;
7fp=fopen("in2.txt","r");
8if(fp!=NULL)
9 fscanf(fp,"%d",&n);
10 for(i=1;i<=n;i++);
11 sum=sum+i;
12printf("%ld ",sum);
13fclose(fp);
14}
當(dāng)文件in2.txt中的數(shù)據(jù)為10時(shí),運(yùn)行程序得到的結(jié)果為11,不正確。為了迅速找到錯(cuò)誤所在,在9行與10行之間插入兩行語(yǔ)句:
printf("n=%d ",n);
getch();
再次運(yùn)行程序,若屏幕上沒(méi)有顯示n=10,則就檢查1-9行程序,直到屏幕上顯示n=10為止;否則程序的錯(cuò)誤是在10-13行,這時(shí)去掉在9行與10行之間插入的兩行語(yǔ)句并將11行語(yǔ)句改成:
{ sum=sum+i;
printf("%ld ",sum);
getch();
}
再次運(yùn)行程序,結(jié)果發(fā)現(xiàn)只要擊一次鍵就會(huì)返回編輯狀態(tài),這就說(shuō)明循環(huán)語(yǔ)句沒(méi)有起到循環(huán)作用。檢查出第10行末尾多了個(gè)“;”,去掉“;”并運(yùn)行程序得正確值55。
4.3用于菜單選擇
getchar()和getch()都可以從鍵盤(pán)接收字符,它們的區(qū)別是:(1)前者是一個(gè)函數(shù),后者是一個(gè)宏名;(2)前者接收字符時(shí),會(huì)將鍵入的字符回顯到屏幕上;后者則不會(huì)將鍵入的字符回顯,很適合于在菜單中進(jìn)行選擇。下面的程序段引自文獻(xiàn)[2],它是判斷某年是否為潤(rùn)年,但在標(biāo)號(hào)語(yǔ)句處有一個(gè)結(jié)構(gòu)錯(cuò)誤,文獻(xiàn)[2]是將標(biāo)號(hào)為error 的語(yǔ)句改為getchar(),ch=getchar();,本文給出一種不同的修改方法:將標(biāo)號(hào)為error 的語(yǔ)句改為getch()。
# include
main( )
{
int ch;
int year;
do {
printf("please input year: ");
scanf("%d", &year);
if(year%4 ==0 && year% 100!=0||year%400== 0)
printf("YES %d ",year);
else
printf("NO%d ", year);
printf("Y--continue, any key--exit ");
error: ch=getchar ( ) ;
} while (ch = = ‘Y || ch = = ‘y);
}
4結(jié)束語(yǔ)
C語(yǔ)言程序的編寫(xiě)和調(diào)試是初學(xué)者學(xué)習(xí)“C語(yǔ)言程序設(shè)計(jì)”課程中遇到的難點(diǎn)中的兩個(gè)。掌握C語(yǔ)言運(yùn)算符的優(yōu)先級(jí)和結(jié)合方向是初學(xué)者正確編寫(xiě)C語(yǔ)言程序代碼的前
提。本文通過(guò)把前綴++(前綴--)與后綴++(后綴--)運(yùn)算符理解為優(yōu)先級(jí)不同的兩個(gè)運(yùn)算符,能使初學(xué)者,尤其是非計(jì)算機(jī)專業(yè)的學(xué)生,更好地掌握其表達(dá)式的計(jì)算,進(jìn)而正確設(shè)計(jì)出高效的C程序。同時(shí),介紹的幾點(diǎn)C程序調(diào)試技巧能在一定程度上提高初學(xué)者的程序調(diào)試能力。
參考文獻(xiàn):
[1] 徐萍,宮麗華. “C語(yǔ)言程序設(shè)計(jì)”課程教學(xué)改革的實(shí)踐和探討[J]. 電腦知識(shí)與技術(shù),2008,4(1):160-162.
[2] 陳仲民. 關(guān)于C語(yǔ)言教學(xué)方法和程序設(shè)計(jì)的探討[J]. 計(jì)算機(jī)教育[J]. 2007(6):3-6.
[3] Kernighan B W, Ritchie D M. The C Programming Language[M]. 2nd ed. Pearson Educatin,2006.8.
[4] 譚浩強(qiáng). C程序設(shè)計(jì)[M]. 2版. 北京:清華大學(xué)出版社,1999.
[5] 王秀貴,曹江連. C語(yǔ)言程序設(shè)計(jì)教程[M]. 北京:中國(guó)鐵道出版社,2007.