版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
項(xiàng)目3學(xué)生成績管理系統(tǒng)的3.1問題情境3.2問題分析3.3項(xiàng)目設(shè)計(jì)與實(shí)施3.4知識拓展3.5應(yīng)用實(shí)踐
本項(xiàng)目要求通過指針和數(shù)組配合使用的方式,完成學(xué)生成績管理系統(tǒng)中的學(xué)生成績錄入、成績查詢、成績修改等操作。將各個操作功能設(shè)計(jì)成獨(dú)立的函數(shù),各函數(shù)間設(shè)計(jì)良好的接口參數(shù),通過數(shù)組存儲學(xué)生的學(xué)號和成績信息,通過指針實(shí)現(xiàn)對學(xué)生學(xué)號和成績信息的錄入、查找和修改等操作。3.1問題情境
項(xiàng)目2通過數(shù)組基本實(shí)現(xiàn)了學(xué)生成績管理系統(tǒng)的常用功能。但是,數(shù)組作為函數(shù)參數(shù)在函數(shù)調(diào)用、參數(shù)傳遞過程中顯得比較繁瑣,而且數(shù)組采用數(shù)組名和下標(biāo)的方式引用數(shù)據(jù)元素對于數(shù)據(jù)元素處理起來也顯得不便。有沒有更為簡便的實(shí)現(xiàn)方法呢?那就是采用指針類型。使用指針類型能夠更為簡便和高效地解決函數(shù)調(diào)用過程中地址的傳遞問題,通過指針還能方便地訪問數(shù)組中的元素。通常在C語言程序設(shè)計(jì)中,指針和數(shù)組配合使用是一種常用的方式。3.2問題分析
根據(jù)本項(xiàng)目的任務(wù)需求,在設(shè)計(jì)思路上,首先,通過自頂向下、逐步求精的結(jié)構(gòu)化設(shè)計(jì)思想對整個程序進(jìn)行功能模塊劃分;其次,根據(jù)各個功能模塊進(jìn)行函數(shù)接口的設(shè)計(jì)和函數(shù)調(diào)度關(guān)系的設(shè)計(jì);最后,在各個函數(shù)功能實(shí)現(xiàn)過程中應(yīng)注意:3.3項(xiàng)目設(shè)計(jì)與實(shí)施
(1)對用戶輸入的可能錯誤檢查是否嚴(yán)格?程序的容錯性如何。(如學(xué)號重復(fù)、成績不符合規(guī)定等。)
(2)如何實(shí)現(xiàn)插入(添加)、刪除、排序等的一般處理功能。
(3)如何實(shí)現(xiàn)多門課程的處理。
(4)如何保存輸入及修改結(jié)果。
(5)菜單如何組織。
【項(xiàng)目分析】
學(xué)生成績管理系統(tǒng)從功能上來講,包含學(xué)生成績的錄入、修改、查詢、輸出等一系列具體任務(wù),因此,本系統(tǒng)在設(shè)計(jì)思路上仍然按照模塊化程序設(shè)計(jì)的基本思想去完成各功能模塊的程序設(shè)計(jì),在數(shù)據(jù)處理上引入了指針,主要通過指針實(shí)現(xiàn)數(shù)據(jù)的傳遞與操作,完成系統(tǒng)各項(xiàng)功能的實(shí)現(xiàn)。
【項(xiàng)目實(shí)施】
程序?qū)崿F(xiàn)所需要的預(yù)處理命令及函數(shù)聲明語句如下:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h> //控制臺相關(guān)函數(shù)定義
#include<windows.h>
#defineMAX_NUM45
voidinput(int*StudentID,int*StudentScore,intMax); //成績輸入
intfindStudentID(intStudentID[],intfindID,intMax); //查找指定學(xué)號的學(xué)生
voidDisplayScore(int*StudentID,int*StudentScore,intMax); //顯示所有記錄
voidDlspMainMenu(); //顯示主菜單
voidDlspQueryMenu(); //顯示查詢子菜單
charchoice(); //獲取用戶在菜單中的選擇
intScoreInput(int*ID,int*Score);
voidQueryScore(int*ID,int*Score,intMax);
voidEditScore(int*ID,int*Score,intMax);
功能模塊1:主菜單設(shè)計(jì)模塊
(1)模塊功能:主菜單操作界面程序設(shè)計(jì)。
(2)接口函數(shù):DispMainMenu()。
(3)程序代碼如下:
voidDispMainMenu()
{
printf("*************學(xué)生成績管理系統(tǒng)V1.0*************\n");
printf("*\t1--成績錄入2--成績修改*\n");
printf("*\t3--成績查詢0--退出*\n");
printf("***********************************************\n");
printf("請選擇(0--3):");/*顯示菜單信息*/
}
程序運(yùn)行結(jié)果如圖3-1所示。圖3-1主菜單顯示程序運(yùn)行結(jié)果功能模塊2:成績錄入模塊
(1)模塊功能:完成錄入學(xué)生學(xué)號及成績的C語言程序設(shè)計(jì)。
(2)接口函數(shù):ScoreInput(int*ID,int*Score),input(int*StudentID,int*StudentScore,intMax)。
(3)程序代碼如下:
voidinput(int*StudentID,int*StudentScore,intMax)
{
inti;
for(i=0;i<Max;i++)
{
printf("\n請輸入第%d個學(xué)生的學(xué)號:\t",i+1);
scanf("%d",StudentID+i);
printf("\t\t成績:\t");
scanf("%d",StudentScore+i);
}
printf("\n您的輸入信息是:\n");
DisplayScore(StudentID,StudentScore,Max);
}
intScoreInput(int*ID,int*Score)
{
intnumber;
printf("\n請輸入本次錄入的學(xué)生人數(shù):");
scanf("%d",&number);
if(number>MAX_NUM)
{
printf("您輸入的人數(shù)太多,大于%d人\n",MAX_NUM);
return(0);
}
input(ID,Score,number);//number是局部變量
return(number);
}圖3-2錄入學(xué)生成績的運(yùn)行圖功能模塊3:成績查詢模塊(查詢所有學(xué)生成績)
(1)模塊功能:顯示所有學(xué)生的成績信息。
(2)接口函數(shù):DispMainMenu(),voidDisplayScore(int*StudentID,int*StudentScore,intMax)。
(3)程序代碼如下:
//查詢菜單設(shè)計(jì)
voidDispQueryMenu()
{
printf("***************請選擇查詢方式*********************\n");
printf("*\tl--按學(xué)號查詢2--查詢?nèi)坑涗?\n");
printf("**************************************************\n");
printf("請選擇(1--2):");//顯示菜單信息
}
/*取用戶對菜單的選擇,返回用戶選擇的對應(yīng)字符鍵ASCII值*/
charchoice()
{
charselect;
while(!kbhit()); //kbhit()等待用戶輸入,非0有擊鍵,適用Microsoft平臺
select=getche(); //取用戶輸入,回顯,getch()則不回顯,適用Microsoft平臺
return(select);
}
/*顯示所有的學(xué)生成績信息*/
voidDisplayScore(int*StudentID,int*StudentScore,intMax)
{
inti;
printf("\n序號\t學(xué)號\t\t成績\n");
for(i=0;i<Max;i++)
printf("%d\t%d\t%d\n",i+1,*(StudentID+i),*(StudentScore+i));
printf("\n");
}
voidQueryScore(int*ID,int*Score,intMax)
{
charselect;
inti,
findID;
DispQueryMenu();
select=choice();
switch(select)
{
case'1':
printf("\n按學(xué)號查詢\n請輸入學(xué)生的學(xué)號:");
scanf("%d",&findID);
if((i=findStudentID(ID,findID,Max))!=-1)
{
printf("\n查找結(jié)果如下:\n");
printf("\t學(xué)號\t\t成績\n");
printf("\t%d\t%d\n",ID[i],Score[i]);
}else //沒有找到
printf("您輸入的學(xué)號不存在!\n");
break;
case'2':
printf("\n查詢?nèi)繉W(xué)生信息!\n");
DisplayScore(ID,Score,Max);
break;
default:
printf("選擇錯誤!\n");
}
}圖3-3所有學(xué)生成績查詢運(yùn)行結(jié)果功能模塊4:成績查詢模塊(按學(xué)號查詢學(xué)生成績)
(1)模塊功能:按照指定的學(xué)生學(xué)號查詢學(xué)生成績信息。
(2)接口函數(shù):intfindStudentID(int*StudentID,intfindID,intMax)。
(3)程序代碼如下:
intfindStudentID(int*StudentID,intfindID,intMax)
{
inti;
for(i=0;i<Max;i++)
if(*(StudentID+i)==findID)break;
if(i<Max)//找到i<Max,說明是執(zhí)行break后結(jié)束循環(huán),即找到指定的學(xué)生
returni;
elsereturn-1;
}圖3-4按學(xué)號查詢程序運(yùn)行結(jié)果功能模塊5:學(xué)生成績修改模塊
(1)模塊功能:按照輸入的學(xué)生學(xué)號,修改指定的學(xué)號所對應(yīng)的成績信息。
(2)接口函數(shù):voidEditScore(int*ID,int*Score,intMax)。
(3)程序代碼如下:
voidEditScore(int*ID,int*Score,intMax)
{
inti,findID; //findID--要查找的學(xué)生的學(xué)號
printf("\n請輸入學(xué)生的學(xué)號:");
scanf("%d",&findID);
if((i=findStudentID(ID,findID,Max))!=-1)
{
printf("原成績:%d\n",*(Score+i));
printf("請輸入新成績:");
scanf("%d",Score+i);
}
elseprintf("您輸入的學(xué)號不存在!\n"); //沒有找到
}
程序運(yùn)行結(jié)果如圖3-5所示。圖3-5修改成績程序運(yùn)行結(jié)果功能模塊6:主函數(shù)模塊
(1)模塊功能:實(shí)現(xiàn)系統(tǒng)變量的初始化和各個子函數(shù)程序模塊的調(diào)度。
(2)接口函數(shù):voidmain(intargc,char*argv[])。
(3)程序代碼如下:
voidmain(intargc,char*argv[])
{
charselect;
intID[MAX_NUM],
Score[MAX_NUM]; //保存學(xué)生學(xué)號及姓名的數(shù)組
intcurrent_number; //number指本程序當(dāng)前正在處理的學(xué)生人數(shù)
charcmdLine[]="winmine.exe";/*WINDOWS應(yīng)用程序名,并在系統(tǒng)的PATH
中能找到,否則要指定路徑,如C:\WINDOWS\System32\winmine.exe*/
select=0;
while(select!='0')
{
system("cls"); //執(zhí)行DOS系統(tǒng)命令,括號內(nèi)參數(shù)是系統(tǒng)命令名
DispMainMenu();
select=choice(); //取用戶輸入
switch(select)
{
case'0':
printf("\n您選擇的是退出測試!\n");//beep(300,400);
continue;
case'1':
printf("\n您選擇的是成績錄入!\n");
current_number=ScoreInput(ID,Score);
break;
case'2':
printf("\n您選擇的是成績修改!\n");
EditScore(ID,Score,current_number);
break;
case'3':
printf("\n您選擇的是成績查詢!\n");
QueryScore(ID,Score,current_number);
break;
default:
printf("\n選擇錯誤!請重新選擇!\n");//小于0,大于4
}
system("PAUSE");//用戶的輸入是<字符>+Enter,清除<Enter>
}
}
選擇“0—退出”,程序運(yùn)行結(jié)果如圖3-6所示。圖3-6退出程序運(yùn)行圖
【項(xiàng)目總結(jié)】
從項(xiàng)目3的程序設(shè)計(jì)可以看出,該項(xiàng)目程序設(shè)計(jì)時(shí)需注意以下幾點(diǎn):
(1)本系統(tǒng)使用模塊化程序設(shè)計(jì)思想。
(2)各個模塊的功能設(shè)計(jì)雖然相互獨(dú)立,但應(yīng)注意各個模塊相互之間的銜接關(guān)系。
(3)指針的概念及在程序設(shè)計(jì)中的靈活應(yīng)用是本系統(tǒng)完成的關(guān)鍵。
【知識總結(jié)】
完成項(xiàng)目3需用到的C語言主要知識點(diǎn)有:
(1)自定義函數(shù)及其調(diào)用規(guī)則。
(2)模塊化程序設(shè)計(jì)的基本思想。
(3)結(jié)構(gòu)體數(shù)據(jù)類型的定義及結(jié)構(gòu)體變量的使用。
(4)分支結(jié)構(gòu)與循環(huán)結(jié)構(gòu)程序設(shè)計(jì)。
(5)指針的概念及基本用法。
本項(xiàng)目相關(guān)知識總結(jié)如下。3.3.1指針的概念
1.指針和指針變量的概念
1)指針的基本概念
計(jì)算機(jī)中的所有數(shù)據(jù)都是順序存放在存儲器中的。一般把存儲器中的一個字節(jié)稱為一個內(nèi)存單元(亦稱存儲單元),不同數(shù)據(jù)類型的值所占用的內(nèi)存單元數(shù)亦不同。為了正確地訪問這些內(nèi)存單元,必須為每個內(nèi)存單元編上號。根據(jù)一個內(nèi)存單元的編號即可準(zhǔn)確地找到該內(nèi)存單元。內(nèi)存單元的編號也叫做地址,通常把這個地址稱為指針。內(nèi)存單元的指針和內(nèi)存單元的內(nèi)容是兩個不同的概念??梢杂靡粋€通俗的例子來說明它們之間的關(guān)系。我們到銀行去存(或取)款時(shí),銀行工作人員將根據(jù)我們的帳號去查找存款單,找到之后在存單上寫入存(或取)款的金額。在這里,帳號就是存單的指針,存款數(shù)是存單的內(nèi)容。
2)指針變量的基本概念
對于一個內(nèi)存單元來說,單元的地址即為指針,其中存放的數(shù)據(jù)是該單元的內(nèi)容。在C語言中,允許用一個變量來存放指針,這種變量稱為指針變量。因此,一個指針變量的值就是某個內(nèi)存單元的地址,或稱為指向某內(nèi)存單元的指針。圖3-7指向變量C的指針變量P如圖3-7所示,設(shè)有字符變量C,其內(nèi)容為字符‘K’(ASCII碼為十進(jìn)制數(shù)75),C占用了0110H號存儲單元(地址用十六進(jìn)制表示)。設(shè)有指針變量P,內(nèi)容為0110H。這種情況下,我們稱為“P指向變量C”或者“P是指向變量C的指針”。
嚴(yán)格地說,一個指針是一個地址,是一個常量,而一個指針變量卻可以被賦予不同的指針值,是變量。但通常把指針變量簡稱為“指針”。為了避免混淆,我們約定:“指針”是指地址,是常量;“指針變量”是指取值為地址的變量。定義指針的目的是為了通過指針去訪問內(nèi)存單元。
既然指針變量的值是一個地址,那么這個地址不僅可以是變量的地址,也可以是其他數(shù)據(jù)結(jié)構(gòu)。在一個指針變量中存放一個數(shù)組或一個函數(shù)的首地址有何意義呢?因?yàn)閿?shù)組或函數(shù)在內(nèi)存中都是連續(xù)存放的,通過訪問指針變量取得了數(shù)組或函數(shù)的首地址,也就找到了該數(shù)組或函數(shù)。這樣一來,凡是出現(xiàn)數(shù)組、函數(shù)的地方都可以用一個指針變量來表示,只要該指針變量中賦予數(shù)組或函數(shù)的首地址即可。這樣做,將會使程序的概念十分清楚,程序本身也精練、高效。在C語言中,一種數(shù)據(jù)類型或數(shù)據(jù)結(jié)構(gòu)往往都占有一組連續(xù)的內(nèi)存單元。用“地址”這個概念并不能很好地描述一種數(shù)據(jù)類型或數(shù)據(jù)結(jié)構(gòu),而“指針”雖然實(shí)際上也是一個地址,但它卻是一個數(shù)據(jù)結(jié)構(gòu)的首地址,它是“指向”一個數(shù)據(jù)結(jié)構(gòu)的,因而概念更為清楚,表示更為明確。這也是引入“指針”概念的一個重要原因。
2.指針變量的定義與應(yīng)用
1)指針變量的定義
指針變量定義的一般形式為
類型說明符*指針變量名;
其中:*為說明符,表示這是一個指針變量;指針變量名為用戶自定義標(biāo)識符;類型說明符表示該指針變量所指向的變量的數(shù)據(jù)類型。例如:
int*p1;該定義表示p1是一個指針變量,它的值是某個整型變量的地址,或者說p1指向一個整型變量。至于p1究竟指向哪一個整型變量,應(yīng)由向p1賦予的地址來決定。
例如:
staicint*p1; /*p1是指向靜態(tài)整型變量的指針變量*/
float*p2; /*p2是指向浮點(diǎn)變量的指針變量*/
char*p3; /*p3是指向字符變量的指針變量*/
應(yīng)該注意的是,一個指針變量只能指向同類型的變量,如p2只能指向浮點(diǎn)變量,不能時(shí)而指向一個浮點(diǎn)變量,時(shí)而又指向一個字符變量。
2)指針變量的賦值
指針變量同普通變量一樣,使用之前不僅要定義說明,而且必須賦予具體的值。未經(jīng)賦值的指針變量不能使用,否則將造成系統(tǒng)混亂,甚至死機(jī)。同時(shí),指針變量的賦值只能賦予地址,決不能賦予任何其他數(shù)據(jù),否則將引起錯誤。
在C語言中,所有初始變量的地址都是由編譯系統(tǒng)自動和隨機(jī)分配的,對用戶完全透明,用戶不知道變量的具體地址。
C語言中提供了取地址運(yùn)算符&來表示變量的地址,其一般形式為
&變量名
如&a變示變量a的地址,&b表示變量b的地址。變量本身必須預(yù)先說明或定義。
設(shè)有指向整型變量的指針變量p,如要把變量a的地址賦予p,可以有以下兩種實(shí)現(xiàn)
方法:
(1)指針變量初始化的方法。即在初始定義指針變量的同時(shí)賦予其初值,如:
inta;
int*p=&a;
(2)賦值語句的方法。即在指針變量定義后,利用賦值語句形式完成對指針變量的賦值操作,如:
inta;
int*p;
p=&a;
不允許把一個數(shù)值直接賦予指針變量,如下面的賦值是錯誤的:
int*p;
p=1000;
被賦值的指針變量前不能再加“*”說明符。如寫為
*p=&a也是錯誤的。
3)指針變量的運(yùn)算
指針變量可以進(jìn)行某些運(yùn)算,但其運(yùn)算的種類是有限的,它只能進(jìn)行賦值運(yùn)算和部分算術(shù)及關(guān)系運(yùn)算。
(1)取地址運(yùn)算符“&”。
取地址運(yùn)算符“&”是單目運(yùn)算符,其結(jié)合性為自右至左,其功能是取變量的地址。在scanf()函數(shù)及前面介紹指針變量賦值中,我們已經(jīng)了解并使用了“&”運(yùn)算符。
(2)取內(nèi)容運(yùn)算符“*”。
取內(nèi)容運(yùn)算符“*”是單目運(yùn)算符,其結(jié)合性為自右至左,用來表示指針變量所指的變量。在“*”運(yùn)算符之后必須跟指針變量。
需要注意的是,指針運(yùn)算符“*”和指針變量說明中的指針說明符“*”不是一回事。在指針變量說明中,“*”是類型說明符,表示其后的變量是指針類型;而表達(dá)式中出現(xiàn)的“*”則是一個運(yùn)算符,用以表示指針變量所指的變量。
【例3.1】指針運(yùn)算符*和&的使用。
程序如下:
/*程序功能:通過指針變量的定義、賦值及簡單應(yīng)用說明指針運(yùn)算符*和&的使用*/
#include<stdio.h>
voidmain()
{inta=5,*p; /*定義整型變量a和指針變量p*/
p=&a; /*利用&取得變量a的地址并給指針變量p賦值*/
printf("%d\n",*p); /*利用*取得指針變量所指向變量的內(nèi)容*/
}
程序運(yùn)行結(jié)果如下:
5
程序說明:在定義了指針變量p后,利用指針變量p取得整型變量a的地址,并在最后輸出中,利用指針變量取得變量a的值進(jìn)行輸出。
賦值運(yùn)算:指針變量的賦值運(yùn)算有以下幾種形式:
①指針變量初始化賦值。例如:
inta=5,*p1=&a;②把一個變量的地址賦予指向相同數(shù)據(jù)類型的指針變量。例如:
inta,*pa;
pa=&a;/*把整型變量a的地址賦予整型指針變量pa*/
③把一個指針變量的值賦予指向相同類型變量的另一個指針變量。例如:
inta,*pa=&a,*pb;
pb=pa;/*把指針變量pa實(shí)際存儲的地址賦予指針變量pb*/由于pa、pb均為指向整型變量的指針變量,因此可以相互賦值,并且賦值后,指針變量pa、pb均指向整形變量a。
④利用指針形式引用其所指變量。例如:
intn1=0,n2,*p=&n2,*q=&n1;
*p=*q;/*等價(jià)于n2=n1;*/
⑤把數(shù)組的首地址賦予指向數(shù)組的指針變量。例如:
inta[5],*pa;
pa=a;/*數(shù)組名表示數(shù)組的首地址,故可直接賦予指向數(shù)組的指針變量pa*/也可寫為
pa=&a[0];/*數(shù)組第一個元素的地址也是整個數(shù)組的首地址,也可賦予pa*/
當(dāng)然也可采取初始化賦值的方法:
inta[5],*pa=a;
⑥把字符串的首地址賦予指向字符類型的指針變量。例如:
char*pStr;
pStr="cLanguage";或用初始化賦值的方法寫為
char*pc="CLanguage";
這里需要說明的是,指針指向字符串,并不是把整個字符串裝入指針變量,而是把存放該字符串的字符數(shù)組的首地址裝入指針變量。在后面還將詳細(xì)介紹。
⑦把函數(shù)的入口地址賦予指向函數(shù)的指針變量。例如:
int(*pf)();
pf=f;/*其中f為函數(shù)名*/
加減算術(shù)運(yùn)算:對于指向數(shù)組的指針變量,可以進(jìn)行整數(shù)類型的加減法運(yùn)算。設(shè)pa是指向數(shù)組a的指針變量,則pa+n、pa-n、pa++、++pa、pa--、--pa運(yùn)算都是合法的。當(dāng)然,參與加減算術(shù)運(yùn)算的變量n只能為整型。
指針變量加或減一個整數(shù)n的意義是把指針指向的當(dāng)前位置(指向某個數(shù)組元素)向前或向后移動n個位置。應(yīng)當(dāng)注意,數(shù)組指針變量向前或向后移動一個位置和地址值加1或減1在概念上是完全不同的。如果指針變量加1,表示指針變量移動1個位置指向下一個數(shù)據(jù)元素的地址,而不是在原地址值的基礎(chǔ)上真實(shí)地加整型數(shù)值1。例如:
inta[5],*pa;
pa=a; /*pa指向數(shù)組a,也是指向數(shù)組元素a[0]*/
pa=pa+2; /*pa指向數(shù)組元素a[2],即pa的值為&pa[2]*/指針變量的加減運(yùn)算只適用于指向數(shù)組的指針變量,對指向其他類型變量的指針變量作加減運(yùn)算是毫無意義的,并容易導(dǎo)致災(zāi)難性的后果。
兩個指針變量之間的運(yùn)算:只有指向同一數(shù)組的兩個指針變量之間才能進(jìn)行運(yùn)算,否則運(yùn)算也毫無意義。
①兩個指針變量相減。兩個指針變量相減所得之差是兩個指針?biāo)笖?shù)組元素之間相差的元素個數(shù)。
例如,pf1和pf2是指向同一浮點(diǎn)數(shù)組的兩個指針變量,設(shè)pf1的值為2010H,pf2的值為2000H。由于浮點(diǎn)數(shù)組每個元素各占用4個字節(jié),所以pf1-pf2的結(jié)果為(2010H-2000H)/4=4,表示pf1和pf2所指數(shù)組元素之間相差4個元素。兩個指針變量不能進(jìn)行加法運(yùn)算。例如,pf1+pf2就毫無實(shí)際意義。
②兩個指針變量進(jìn)行關(guān)系運(yùn)算。指向同一數(shù)組的兩個指針變量進(jìn)行關(guān)系運(yùn)算可表示它們所指數(shù)組元素之間的關(guān)系。例如:
pf1==pf2表示pf1和pf2指向同一數(shù)組元素
pf1>pf2表示pf1處于高地址位置
pf1<pf2表示pf2處于高地址位置
指針變量還可以與0比較。設(shè)p為指針變量,則p==0表明p是空指針,它不指向任何變量;p!=0表示p不是空指針。空指針是由對指針變量賦予0值而得到的。例如:
#defineNULL0
int*p=NULL;
對指針變量賦0值和不賦值是不同的。指針變量未賦值時(shí),其初始化結(jié)果可能是任意值,是不能使用的,否則將造成意外錯誤。而指針變量賦0值后,則可以使用,只是它不指向具體的變量而已。
4)指針變量應(yīng)用示例
以下C程序示例用以增強(qiáng)對本節(jié)內(nèi)容的理解及鞏固。通讀這些程序,并編譯運(yùn)行它們,以掌握指針變量的基礎(chǔ)應(yīng)用。
【例3.2】指針變量的應(yīng)用。
/*程序功能:熟悉指針變量的基礎(chǔ)應(yīng)用*/
#include<stdio.h>
voidmain()
{
intnNumber; /*定義普通整型變量*/
int*pPointer; /*定義指向整型變量的指針變量pPointer*/
nNumber=15;
pPointer=&nNumber; /*給指針變量賦值*/
printf("nNumberisequalto:%d\n",nNumber); /*輸出變量nNumber的值*/
*pPointer=25; /*通過指針改變nNumber的值*/
printf("Now,nNumberisequalto:%d",nNumber);/*證明nNumber值已被改變*/
}程序運(yùn)行結(jié)果如下:
nNumberisequalto:15
Now,nNumberisequalto:25
【例3.3】指針變量的應(yīng)用。
/*程序功能:熟悉指針變量的基礎(chǔ)應(yīng)用*/
#include<stdio.h>
voidmain()
{
inta=10,b=20,s,t,*pa,*pb;
pa=&a;pb=&b;
s=*pa+*pb;/*對于指針變量所指內(nèi)容的引用*/
t=*pa**pb; /*指針運(yùn)算符優(yōu)先級高于算術(shù)運(yùn)算符*/
printf("a=%d\nb=%d\na+b=%d\na*b=%d\n",a,b,a+b,a*b);
printf("s=%d\nt=%d\n",s,t);/*兩種算式運(yùn)算結(jié)果相同*/
}程序運(yùn)行結(jié)果如下:
a=10
b=20
a+b=30
a*b=200
s=30
t=200
【例3.4】輸出三個任意輸入整型數(shù)值的最大數(shù)和最小數(shù)。
/*程序功能:輸出三個任意輸入整型數(shù)值的最大數(shù)和最小數(shù)*/
#include<stdio.h>
voidmain()
{
inta,b,c,*pmax,*pmin;
printf("inputthreeintnumbers:");
scanf("%d%d%d",&a,&b,&c); /*任意輸入三個整型數(shù)值*/
if(a>b)
{pmax=&a;pmin=&b;} /*比較a和b*/
else
{pmax=&b;pmin=&a;}
if(c>*pmax)pmax=&c; /*比較c和a、b的最大值*/
if(c<*pmin)pmin=&c; /*比較c和a、b的最小值*/
printf("max=%d\nmin=%d\n",*pmax,*pmin);
}程序運(yùn)行結(jié)果如下:
inputthreeintnumbers:234567↙
max=67
min=233.3.2指針變量作函數(shù)參數(shù)
在函數(shù)應(yīng)用中,函數(shù)的參數(shù)不僅可以是整型、實(shí)型、字符型、數(shù)組等數(shù)據(jù),也可以是指針類型,以實(shí)現(xiàn)將地址傳送到另一函數(shù)中參與操作
【例3.5】指針的應(yīng)用。
/*程序功能:利用AddFive()函數(shù)實(shí)現(xiàn)對所傳遞變量加5的操作*/
#include"stdio.h"
AddFive(intN) /*定義函數(shù)AddFive()*/
{N=N+5;
}
main()
{intv=20;
printf("Myoriginalvalueis%d\n",v);
AddFive(v); /*調(diào)用函數(shù)AddFive()實(shí)現(xiàn)對變量v加5的操作*/
printf("Mynewvalueis%d",v);
}程序運(yùn)行結(jié)果如下:
Myoriginalvalueis20
Mynewvalueis20
在這里應(yīng)說明的是,本例并沒有得到預(yù)想的結(jié)果25。問題出在哪兒?其實(shí)本例程描述了一個函數(shù)調(diào)用中的“值傳遞”,因此,AddFive()函數(shù)中“N=N+5”這一行雖改變了N值,但原始的變量v在主函數(shù)main()里依然沒變,所以,程序輸出顯示主函數(shù)中的變量v的實(shí)際值前后并沒有發(fā)生變化。如果要實(shí)現(xiàn)正確的程序功能,可以通過傳遞指針到函數(shù)來達(dá)到目的。下面就是修改過的程序,在AddFive()函數(shù)形參說明要加*號,函數(shù)調(diào)用時(shí)要用&號,以表示傳遞的是指針。
#include"stdio.h"
AddFive(int*N) /*定義函數(shù)AddFive()*/
{*N=*N+5; /*實(shí)現(xiàn)對指針?biāo)傅淖兞考?*/
}
main()
{intv=20;
printf("Myoriginalvalueis%d\n",v);
AddFive(&v); /*注意變量前加&,表示傳遞的是變量v的指針*/
printf("Mynewvalueis%d",v);
}
程序運(yùn)行結(jié)果如下:
Myoriginalvalueis20
Mynewvalueis25
注意:本例程序是把指針?biāo)傅淖兞考?,而并不是指針自己加5。
【例3.6】指針變量作函數(shù)參數(shù)參與應(yīng)用。
/*程序功能:指針變量作為函數(shù)的參數(shù)參與傳遞*/
#include<stdio.h>
outval(int*p1,float*p2) /*函數(shù)形參為指針類型*/
{printf("Theintvalueis%d\n",*p1);
printf("Thefloatvalueis%f\n",*p2);
}
voidmain()
{inta=5,*p_int;
floatb=4.5,*p_float;
p_int=&a;
p_float=&b;
outval(p_int,p_float); /*實(shí)參傳遞的是指針類型的值*/
}
程序運(yùn)行結(jié)果如下:
Theintvalueis5
Thefloatvalueis4.500000說明:
(1)本例利用指針變量p_int和p_float作為實(shí)參對函數(shù)outval()進(jìn)行調(diào)用。
(2)在函數(shù)outval()的定義中,必須使用相同類型、相同個數(shù)的形式參數(shù)和實(shí)際參數(shù)相對應(yīng)。
(3)在函數(shù)outval()調(diào)用開始時(shí),實(shí)參變量p_int和p_float利用“值傳遞”的方式將它們的值(分別指向變量a和b的地址)傳送給形參變量p1和p2。
(4)在函數(shù)outval()調(diào)用開始后,可利用形參變量p1和p2所指向的變量內(nèi)容參與各種運(yùn)算。本例中只是對其指向的內(nèi)容進(jìn)行輸出顯示。
(5)在函數(shù)outval()調(diào)用結(jié)束后,形參變量p1和p2將被釋放,實(shí)參變量p_int和p_float保留原指向。
(6)如果在函數(shù)outval()中,利用指針對變量a和b的值進(jìn)行了變化,函數(shù)調(diào)用結(jié)束后該變化將會影響至主函數(shù)。
【例3.7】指針變量作函數(shù)參數(shù)參與應(yīng)用。
/*程序功能:指針變量作為函數(shù)參數(shù)參與傳遞,并對主函數(shù)的變量值產(chǎn)生影響*/
#include<stdio.h>
outval(int*p1,float*p2) /*函數(shù)形參為指針類型*/
{*p1=*p1*10;
*p2=*p2*10; /*對指針?biāo)缸兞窟M(jìn)行運(yùn)算變化*/
}
voidmain()
{inta=5,*p_int;
floatb=4.5,*p_float;
p_int=&a;
p_float=&b;
printf("The1thoutput__beforeuseoutval()function\n");
printf("Theintvalueis%d\n",*p_int);
printf("Thefloatvalueis%f\n",*p_float);
outval(p_int,p_float);
printf("The2thoutput__afteruseoutval()function\n");
printf("Theintvalueis%d\n",*p_int);
printf("Thefloatvalueis%f\n",*p_float);
}程序運(yùn)行結(jié)果如下:
The1thoutput__beforeuseoutval()function
Theintvalueis5
Thefloatvalueis4.500000
The2thoutput__afteruseoutval()function
Theintvalueis50
Thefloatvalueis45.000000
可見,當(dāng)利用指針變量作為實(shí)參對函數(shù)進(jìn)行調(diào)用的過程中,如果函數(shù)對指針?biāo)缸兞康闹颠M(jìn)行了變化,函數(shù)運(yùn)行結(jié)束后,該變化將會影響主函數(shù)中實(shí)參的值。3.3.3指針與數(shù)組
1.概述
指針和數(shù)組有著密切的關(guān)系,任何能由數(shù)組下標(biāo)完成的操作也都可用指針來實(shí)現(xiàn),但程序中使用指針可使編程代碼更緊湊、更靈活。
一個數(shù)組是由連續(xù)的一塊內(nèi)存單元組成的,數(shù)組名就是這塊連續(xù)內(nèi)存單元的首地址。一個數(shù)組也是由各個數(shù)組元素(下標(biāo)變量)組成的,每個數(shù)組元素按數(shù)據(jù)類型的不同占有幾個連續(xù)的內(nèi)存單元。一個指針變量既可以指向一個數(shù)組,也可以指向一個數(shù)組元素。如果要使一個指針變量指向一個數(shù)組,可把數(shù)組名或數(shù)組第一個元素的地址賦予它;如果要使指針變量指向某個數(shù)組的第n個元素,可以把該數(shù)組第n個元素的地址賦予它或把數(shù)組名加n賦予它。例如
charstr[80],*pl;
pl=str;這里,將數(shù)組名str賦予指針變量pl。在C程序中,不帶下標(biāo)的數(shù)組名為數(shù)組的起始地址。因此,數(shù)組名也是指向數(shù)組的指針。
語句“pl=str;”還可以這樣表示為pl=&str[0];,即把數(shù)組str的第一個元素的地址賦予指針變量pl。如果希望訪問str中的第5個元素,可以這樣寫:
str[4]
或*(pl+4)兩種表示形式都將返回第5個元素的值。因?yàn)閿?shù)組下標(biāo)是從0開始的,所以要訪問數(shù)組的第5個元素,str的下標(biāo)應(yīng)為4。還可以將指針pl加4,以存取第5個元素。例如:
#include<stdio.h>
voidmain()
{inta[10]={1,2,3,4,5,6,7,8,9,10},*p=&a[3],*q=p+2;
/*指針變量p指向a[3],指針變量q指向a[5]*/
printf("%d,%d\n",*p,*q);
}程序運(yùn)行結(jié)果如下:
4,6
2.通過指針引用數(shù)組元素
數(shù)組指針變量說明的一般形式為
類型說明符*指針變量名;
其中,類型說明符表示該指針?biāo)笖?shù)組的類型。從一般形式可以看出,指向數(shù)組的指針變量和指向普通變量的指針變量的說明是相同的。
設(shè)有數(shù)組a,指向a的同類型指針變量為pa,則通過對指針概念的理解就存在以下關(guān)系:
pa、a、&a[0]均指向同一單元。它們都是數(shù)組a的首地址,也是數(shù)組元素a[0]的地址。
pa+1、a+1、&a[1]均指向數(shù)組元素a[1]。類似可知pa+i、a+i、&a[i]指向數(shù)組元素a[i]。
應(yīng)該說明的是,指針pa是變量,而a、&a[i]都是常量(程序運(yùn)行中,數(shù)組所分配的內(nèi)存單元地址固定不變),在編程時(shí)應(yīng)予以注意。
引入指針變量后,就可以使用兩種方法來訪問數(shù)組元素了。
1)下標(biāo)法
下標(biāo)法是用a[i]或*(a+i)形式訪問數(shù)組元素,在前面介紹數(shù)組時(shí)都是采用這種方法。
例如:
#include<stdio.h>
voidmain()
{
inta[5],i;
for(i=0;i<5;i++)
{
a[i]=i; /*給數(shù)組元素賦值*/
printf("a[%d]=%d\n",i,*(a+i)); /*輸出數(shù)組元素*/
}
printf("\n");
}
程序運(yùn)行結(jié)果如下:
a[0]=0
a[1]=1
a[2]=2
a[3]=3
a[4]=4
2)指針法
指針法是采用
*(pa+i)或pa[i]形式,用間接訪問的方法來訪問數(shù)組元素。
【例3.8】指針變量訪問數(shù)組元素。
/*程序功能:利用指針變量訪問數(shù)組各個元素,并輸出所有數(shù)組元素值*/
#include<stdio.h>
voidmain()
{
inta[5],i,*pa;
pa=a; /*指針變量指向數(shù)組a首地址*/
for(i=0;i<5;i++)
{*pa=i+1; /*給數(shù)組元素賦值*/
pa++; /*指針指向下一個元素*/
}
pa=a; /*重新使pa指向數(shù)組a首地址*/
for(i=0;i<5;i++)
{printf("a[%d]=%d\n",i,*(pa+i)); /*順序輸出各數(shù)組元素的值*/
}
}說明:
(1)程序中有兩個語句pa=a;。因?yàn)樵谥骱瘮?shù)中,當(dāng)?shù)谝粋€循環(huán)結(jié)束后,指針pa已指向a[5],而后面需要重新對數(shù)組a進(jìn)行引用,所以須重新使指針變量指向數(shù)組首地址。
(2)在實(shí)現(xiàn)數(shù)組內(nèi)容輸出時(shí),也可采用下面的實(shí)現(xiàn)方法:
for(i=0;i<5;i++)
{
printf("a[%d]=%d\n",i,*pa);
pa++;
}
甚至,整個程序更可簡寫為例3.9所示。
【例3.9】指針變量訪問數(shù)組元素。
/*程序功能:利用指針變量訪問數(shù)組各個元素,并對內(nèi)容進(jìn)行輸出*/
#include<stdio.h>
voidmain()
{
inta[5],i,*pa=a;
for(i=0;i<5;)
{*pa=i;
printf("a[%d]=%d\n",i++,*pa++);/*注意++運(yùn)算符的合理使用*/
}
}
程序運(yùn)行情況同例3.8。
使用下標(biāo)法的程序執(zhí)行速度比使用指針法的慢。原因是利用下標(biāo)操作數(shù)組元素所使用的時(shí)間比使用指針操作數(shù)組元素所花費(fèi)的時(shí)間長。尤其在順序訪問數(shù)組的過程中,使用指針來引用數(shù)組元素的程序段效率會更高。但如果是隨機(jī)訪問數(shù)組,則采用下標(biāo)法引用更好,因?yàn)樗ǔJ桥c計(jì)算一個復(fù)雜的指針表達(dá)式一樣快,而且易于編碼和理解。
下面程序段是較為典型的數(shù)組元素運(yùn)算操作,分析程序段的輸出結(jié)果是什么?
#include<stdio.h>
voidmain()
{
inta[]={2,4,6,8,10},y=0,x,*p;
p=&a[1]; /*注意:指針p指向數(shù)組第二個元素*/
for(x=1;x<3;x++) /*循環(huán)段*/
y+=p[x]; /*累計(jì)求和:p[x]等價(jià)于*(p+x)*/
printf("%d\n",y);
}綜上所述,若有定義“inta[10],*pa=a;”,則利用指針給出數(shù)組元素地址和內(nèi)容的表示形式主要包括:
(1)
pa+i和a+i均表示a[i]的地址,它們均指向數(shù)組a的第i個元素,即指向a[i]。
(2)
*(pa+i)和*(a+i)都表示pa+i和a+i所指對象的內(nèi)容,即為a[i]。
(3)指向數(shù)組元素的指針,也可以表示成數(shù)組的形式。如pa[i]與*(pa+i)等價(jià),a[i]與*(a+i)等價(jià)。也就是說,它允許指針變量帶下標(biāo)。假若pa=a+5;,則pa[2]就相當(dāng)于
*(pa+2),由于pa指向a[5],所以pa[2]就相當(dāng)于a[7]。而pa[-3]就相當(dāng)于*(pa-3),它表示a[2]。
3.指向數(shù)組的指針變量作函數(shù)參數(shù)
前面已經(jīng)介紹了利用指針變量引用數(shù)組元素,下面介紹指向數(shù)組的指針變量作為函數(shù)參數(shù)的使用,具體如下例所示。
【例3.10】鍵盤輸入5門功課成績,自定義函數(shù)完成平均分的計(jì)算。
/*程序功能:指向數(shù)組的指針變量作為函數(shù)參數(shù)的使用*/
#include<stdio.h>
floataver(float*pa)
{
inti;
floatave,s=0;
for(i=0;i<5;i++)
s=s+*pa++; /*利用指針引用數(shù)組元素,求和*/
ave=s/5;
returnave; /*返回平均值*/
}
voidmain()
{
floatscore[5],ave,*sp;
inti;
sp=score; /*指針指向數(shù)組score的首地址*/
printf("\input5scores:\n");
for(i=0;i<5;i++)
scanf("%f",&score[i]);
ave=aver(sp); /*將數(shù)組首地址傳遞到函數(shù)aver()*/
printf("averagescoreis%5.2f",ave);
}程序運(yùn)行結(jié)果如下:
input5scores:
8687969776↙
averagescoreis88.40
說明:
(1)例3.10主函數(shù)中,指針sp指向數(shù)組score的首地址,并在調(diào)用函數(shù)aver()時(shí),對指向數(shù)組的指針變量sp進(jìn)行了引用,表示傳遞給函數(shù)aver()的是一個地址值。自定義函數(shù)aver()形參說明也是一個指針類型的變量,以接收主函數(shù)傳遞過來的指針值。在程序設(shè)計(jì)中,為了保證函數(shù)的正確調(diào)用,應(yīng)保證形參、實(shí)參數(shù)據(jù)類型的一致性。在這里,實(shí)參、形參都是指向符點(diǎn)類型的指針變量。
(2)函數(shù)aver()中,由于利用指針變量pa接收了sp所指地址值,且sp指向主函數(shù)數(shù)組score的首地址,所以,指針變量pa也指向主函數(shù)數(shù)組score的首地址。
(3)程序行“s=s+*pa++;”中,由于運(yùn)算符
*
比
++
運(yùn)算符優(yōu)先級高,所以就等同于“s=s+*pa;pa++;”,即先引用指針pa所指對象求和,而后使指針pa指向下一個元素。
下面程序段將在自定義函數(shù)sum()中,利用指針變量接收主函數(shù)傳遞過來的一個數(shù)組元素的地址,并利用指針對數(shù)組元素進(jìn)行相關(guān)操作。
#include<stdio.h>
sum(int*p)
{p[0]=p[-1]+p[1]; /*利用指針形式引用數(shù)組元素并進(jìn)行操作*/
}
voidmain()
{
inta[10]={1,2,3,4,5,6,7,8,9,10};
sum(&a[2]); /*調(diào)用函數(shù)sum()*/
printf("%d",a[2]);
}程序運(yùn)行結(jié)果如下:
6
說明:主函數(shù)調(diào)用sum()函數(shù)時(shí),傳遞的實(shí)參為a[2]的地址,所以,在函數(shù)sum()中,指針變量p指向數(shù)組元素a[2]。函數(shù)sum()中的語句“p[0]=p[-1]+p[1];”是以指針變量引用數(shù)組元素,該語句等同于語句“*p=*(p-1)+*(p+1);”或“a[2]=a[1]+a[3];”,其結(jié)果對數(shù)組元素a[2]的值產(chǎn)生了影響。
“值傳遞”與“地址傳遞”有何區(qū)別呢?如下例所示。
#include<stdio.h>
swap1(intc0[],intc1[]) /*數(shù)組名形參*/
{intt;
t=c0[0];c0[0]=c1[0];c1[0]=t; /*交換結(jié)果影響到主函數(shù)*/
}
swap2(int*c0,int*c1) /*指針形參*/
{intt;
t=*c0;*c0=*c1;*c1=t; /*交換結(jié)果影響到主函數(shù)*/
}
swap3(intc0,intc1) /*普通變量形參*/
{intt;
t=c0;c0=c1;c1=t; /*交換結(jié)果不影響到主函數(shù)*/
}
voidmain()
{inta[2]={3,5},b[2]={3,5},c[2]={3,5};
swap1(a,a+1); /*以數(shù)組名形式傳遞地址*/
swap2(&b[0],&b[1]); /*利用&運(yùn)算符取址傳遞*/
swap3(c[0],c[1]); /*數(shù)組元素值傳遞*/
printf("%d%d\n%d%d\n%d%d",a[0],a[1],b[0],b[1],c[0],c[1]);
}
程序運(yùn)行結(jié)果如下:
53
53
35說明:函數(shù)swap1()、swap2()都是“地址傳遞”,利用指針接收主函數(shù)傳遞過來的數(shù)組元素地址(注意函數(shù)形參類型說明,以及函數(shù)調(diào)用時(shí)傳遞的地址形式),所以,在函數(shù)內(nèi)部進(jìn)行所指向數(shù)組元素值的交換后,其結(jié)果對主函數(shù)產(chǎn)生了影響。而swap3()函數(shù)是“值傳遞”,在主函數(shù)調(diào)用開始后,變量c0和c1分別取得主函數(shù)c[0]和c[1]的值,雖然swap3()函數(shù)對c0和c1的值進(jìn)行了交換,但函數(shù)運(yùn)行結(jié)束后,由于變量c0、c1、t會被釋放,其交換并未對主函數(shù)數(shù)組c的兩個元素產(chǎn)生影響。另外,不能企圖通過改變指針形參的地址值,而使指針實(shí)參的值也改變。例如:
#include<stdio.h>
swap(int*p1,int*p2)
{int*p;
p=p1;p1=p2;p2=p;
}
voidmain()
{inta,b;
scanf("%d,%d",&a,&b);
swap(&a,&b);
printf("%d%d\n",a,b);
}
程序運(yùn)行結(jié)果如下:
10,20↙
1020/*swap()函數(shù)交換結(jié)果不影響a和b的值*/
3.4.1宏定義
在C語言源程序中,允許用一個標(biāo)識符來表示一個字符串,稱為“宏”。被定義為“宏”的標(biāo)識符稱為“宏名”。在編譯預(yù)處理時(shí),對程序中所有出現(xiàn)的“宏名”,都用宏定義中的字符串去代換,這稱為“宏代換”或“宏展開”。宏定義是由源程序中的宏定義命令完成的。宏代換是由預(yù)處理程序自動完成的。3.4知識拓展宏提供了一種詞法符號替換機(jī)制,它們可以帶也可以不帶類似函數(shù)中的形式參數(shù)。所以,宏定義也分為無參宏定義和帶參宏定義兩種。
1.無參宏定義
無參宏的宏名后不帶參數(shù)。其定義的一般形式為
#define標(biāo)識符字符串
其中的“#”表示這是一條預(yù)處理命令,凡是以“#”開頭的均為預(yù)處理命令;define為宏定義命令;標(biāo)識符為所定義的宏名;字符串可以是常量、表達(dá)式、格式串等。
在前面經(jīng)常使用過的符號常量的定義就是一種無參宏定義。
【例3.11】利用無參宏定義形式定義各種類型符號常量并輸出。本例通過定義各種數(shù)值及字符串,完成一個給定半徑情況下圓面積的計(jì)算輸出。
程序如下:
#include"stdio.h"
#definePI3.14159 /*定義π值*/
#defineR4 /*定義半徑值*/
#defineINFO"Theareais:" /*定義面積輸出提示*/
main()
{printf("%s%f\n",INFO,PI*R*R); /*以給定提示字符串輸出面積值*/
}
程序運(yùn)行結(jié)果如下:
Theareais:50.265440說明:
(1)根據(jù)一般C語言程序中變量的命名規(guī)則,符號常量的定義一般習(xí)慣使用大寫字母表示,主要是因?yàn)橥ǔT谝话阕兞康亩x中常使用小寫字母的形式。當(dāng)然,符號常量也可以以小寫字母命名。
(2)宏定義是用宏名來表示一個字符串,在宏展開時(shí)又以該字符串取代宏名,屬于一種簡單的代換。其中,所表示的字符串可含任意字符,可以是常數(shù),也可以是表達(dá)式,預(yù)處理程序?qū)λ蛔魅魏螜z查。如有錯誤,只能在編譯已被宏展開源程序的過程中發(fā)現(xiàn)問題。
(3)宏定義常用于程序中反復(fù)使用的常量或表達(dá)式。例如,利用符號常量M表示表達(dá)式(y*y+3*y)。在編寫源程序時(shí),所有使用到表達(dá)式(y*y+3*y)的地方都可由M代替,而對源程序作編譯時(shí),將先由預(yù)處理程序進(jìn)行宏代換,即用(y*y+3*y)表達(dá)式去置換所有的宏名M,然后再進(jìn)行編譯。
(4)宏定義不是說明或語句,在行末不必加分號,如加上分號則連分號也一起置換。
【例3.12】宏名表示一個表達(dá)式的應(yīng)用。
程序如下:
#include"stdio.h"
#defineM(y*y+3*y)/*定義宏名M表示指定表達(dá)式*/
voidmain()
{
ints,y;
printf("inputanumber:");
scanf("%d",&y);
s=3*M+4*M+5*M;/*M在預(yù)處理過程中被替換為所表示的表達(dá)式*/
printf("s=%d\n",s);
}
程序運(yùn)行結(jié)果如下:
inputanumber:12↙
s=2160本例中首先進(jìn)行宏定義,定義M表示表達(dá)式(y*y+3*y),在語句“s=3*M+4*M+5*M;”處作了宏調(diào)用。在預(yù)處理時(shí),經(jīng)宏展開后該語句變?yōu)?/p>
s=3*(y*y+3*y)+4*(y*y+3*y)+5*(y*y+3*y);
需要注意的是,在宏調(diào)用中,表達(dá)式(y*y+3*y)兩邊的括號不能省略,否則會發(fā)生錯誤。如果在例3.12中,將M的宏定義變?yōu)?/p>
#difineMy*y+3*y
則在宏展開時(shí)將得到下述語句:
s=3*y*y+3*y+4*y*y+3*y+5*y*y+3*y;
當(dāng)輸入y值12后,程序運(yùn)行結(jié)果為s=1836。
此結(jié)果顯然與加有括號的原題計(jì)算結(jié)果差異很大。因此,在作宏定義時(shí)必須十分注意,應(yīng)保證在宏代換之后不發(fā)生錯誤。
【例3.13】宏名所表示表達(dá)式末尾帶分號的實(shí)際使用。
/*程序功能:程序設(shè)計(jì)中宏名所表示表達(dá)式末尾帶分號的實(shí)際使用情況*/
#include"stdio.h"
#defineAAA500+1000;
voidmain()
{
inti;
i=AAA/*注意該命令行未加;*/
printf("i=%d\n",i);
}
程序運(yùn)行結(jié)果如下:
i=1500
本例所定義宏名AAA在實(shí)際宏代換過程中,將表達(dá)式500+1000連同所帶分號一起置換。在命令行i=AAA中,因所替換表達(dá)式已帶有分號,所以現(xiàn)命令行無須再增加末尾
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024跨境電商服務(wù)平臺居間合同
- 二零二四年中英文教育培訓(xùn)機(jī)構(gòu)合作服務(wù)合同3篇
- 2025年度物流倉儲場地租賃及供應(yīng)鏈管理合同6篇
- 2025年度航空航天產(chǎn)業(yè)技術(shù)工人勞動合同3篇
- 2025年度網(wǎng)絡(luò)安全監(jiān)測預(yù)警服務(wù)合同6篇
- 2025年度大型企業(yè)員工培訓(xùn)服務(wù)采購合同范本3篇
- 二零二四年A公司網(wǎng)站開發(fā)合同協(xié)議書
- 二零二五年度大廈商場租賃合同(含節(jié)假日營業(yè)規(guī)定)3篇
- 2025年度餐廚廢棄物處置與廢棄物處理設(shè)施運(yùn)營管理合同3篇
- 2025版煤礦安全生產(chǎn)責(zé)任險(xiǎn)投保合同3篇
- 春節(jié)文化常識單選題100道及答案
- 12123交管學(xué)法減分考試題及答案
- 2024年杭州師范大學(xué)附屬醫(yī)院招聘高層次緊缺專業(yè)人才筆試真題
- 制造業(yè)BCM業(yè)務(wù)連續(xù)性管理培訓(xùn)
- 商場停車場管理制度
- 24年追覓在線測評28題及答案
- TGDNAS 043-2024 成人靜脈中等長度導(dǎo)管置管技術(shù)
- 《陸上風(fēng)電場工程概算定額》NBT 31010-2019
- 皮帶輸送機(jī)工程施工電氣安裝措施要點(diǎn)
- 藥房(冰柜)溫濕度表
- QJ903.9A-1995航天產(chǎn)品工藝文件管理制度管理用工藝文件編制規(guī)則
評論
0/150
提交評論