作為一位兢兢業業的人民教師,就不得不需要編寫教案,借助教案可以讓教學工作更科學化。那么什么樣的教案才是好的呢?以下是小編收集整理的《c語言第10章教案標準》,供大家參考,更多范文可通過本站頂部搜索您需要的內容。
第一篇:c語言第10章教案標準
C電子教案第7章
泰山職業技術學院電子教案
第7章 函數
7.1 概述
一個C程序是由函數組成的,所以函數是C語言中最重要的概念,本章專門討論函數的定義、函數的調用及參數傳遞等問題。 例7.1。 說明:
(1)一個源程序文件是由一個或多個C函數組成的,一個源程序文件是一個編譯單位。
(2)一個C程序由一個或多個源程序文件組成,一個源程序文件可以為多個C程序共用。
(3)一個C程序中一定要有一個名為main的主函數,執行時總是從主函數開始,其它函數只有被調用時才會執行,執行完畢返回到調用處繼續執行,正常情況下總是在主函數結束執行。
(4)所有的函數是平行的,即在定義時是互相獨立的,主函數可以調用其它函數,其它函數之間可以互相調用,但其它函數不能調用主函數。
(5)從用戶使用的角度看,函數可分為標準函數(庫函數)和用戶自定義函數。 (6)從函數的形式看,函數可分為無參函數和有參函數。 7.2 函數定義的一般形式 1. 無參函數的定義形式 格式:函數類型 函數名() { 數據聲明部分; 執行語句部分; } 說明:(1)函數名:函數名是函數調用的依據,函數值的返回也是通過函數名實現的,函數名要符合標識符的定義。
(2)函數體:由數據聲明和執行語句兩部分組成,數據聲明是對數據特征的描述,執行語句是對數據處理的描述,函數的功能由它們實現。
(3)函數類型:函數類型規定了函數返回值的類型,int或char可不寫,如不要返
C語言程序設計精品課程
第 1 頁 共
第二篇:C程序設計教案(第5章 實驗5)
實驗 5 一維數組和二維數組
一、
二、 實驗學時:2課時 實驗目標:
1. 熟悉掌握一維數組的定義、賦值和輸入輸出的方法。 2. 掌握對10個整數排序的方法。
3. 掌握二維數組的定義、賦值和輸入輸出的方法。
三、 實驗要求:
1. 在上實驗課之前,每一個同學必須將實驗的題目、程序編寫完畢,做好充分的準備。
2. 所有實驗環節均由每位同學獨立完成,嚴禁抄襲他人實驗結果,若發現有結果雷同者,按實驗課考核辦法處理。
四、 實驗步驟和內容
?
【啟動Visual C++】 【新建工程】
選中【C++ Source File】項,【新建源程序文件】 編輯程序 執行程序
【例5.3】用隨機函數產生10個0~100之內的整數,按從小到大排列輸出。 /* 源文件名:Li5_3.c 功能:產生10個0~100之內的整數,按從小到大排列輸出 */ 使數組從小到大排序的規則如下:
⑴設數組為a[0],a[1],…,a[n-1],構造i循環從0,1,…,n-2變化,構造j循環從i+1,i+2,…,n-1變化,即j>i。
⑵對于任何一個a[i],如果a[i]>a[j],表面前面有一個元素a[i]比它后面的元素a[j]大,a[i]應該在后面,a[j]應該在前面,交換a[i]與a[j]。
⑶對于任何一個a[i],都循環一次j,j循環完成后a[i]必不大于a[i+1],…,a[n-1],重復i循環,i循環結束后數組從小到大排序。
#include #include void main() { int a[10],i,j,k ;
/*定義a數組,i、j為循環變量,k為臨時變量*/ for(i=0;i<10;i++)
a[i]=rand()%100 ;
/*給a數組隨機賦0~100之內的整數*/
printf("排序之前的數據") ; for(i=0;i<10;i++) printf("%d",a[i]) ;
/*輸出a數組的值,未排序*/
putchar(‘ ’) ;
for(i=0;i<9;i++)
for(j=i+1;j<50;j++)
if(a[i]>a[j])
{ k=a[i] ; a[i]=a[j] ; a[j]=k ; }
/*數組排序*/ for(i=0;i<10;i++)
printf("%d",a[i]) ;
/*輸出a數組的值,已排序*/ putchar(‘ ’) ; }
1) 觀查執行結果,是否與教材相同。 2) 重新輸入10個不同的數,再查看結果
【例5.5】定義一個a[5][6]的整數數組,用隨機函數值填寫每個單元,找出最大值的單元,輸出其行號及列號。
/* 源文件名:Li5_5.c 功能:找出二維數組中最大值的單元,輸出其行號及列號。 */ #include #include void main() { int a[5][6] ;
/*定義a二維數組*/
int i,j,k,l,max ;
/*定義i、j為循環變量,k、l為最大值所在的行和列,
max為最大值*/ for(i=0;i<5;i++)
for(j=0;j<6;j++)
a[i][j]=rand()%100 ;
/*給a二維數組賦值*/
max=a[0][0] ; k=0 ; l=0 ;
/*把a[0][0]假設為最大值*/ for(i=0;i<5;i++) for(j=0;j<6;j++)
if(a[i][j]>max)
{ k=i ; l=j ; max=a[i][j] ;}
/*保存最大值及其行號k及列號l*/ printf("數組是 ") for(i=0;i<5;i++) ;
{
for(j=0;j<6;j++)
printf("%4d",a[i][j]) ;
/*輸出a二維數組的值*/ printf(" ") ;
}
printf("最大值是a[%d][%d]=%d ",k,l,max) ; }
1)觀查執行結果,是否與教材相同。 2)重新輸入不同的數據,再查看結果
五、 思考題
1) 【例5.3】若改為從小到大排序,該如何修改?
2) 【例5.5】一開始為什么要把a[0][0]賦值給max,能把0直接賦值給max嗎?
六、
實驗小結:
第三篇:C程序設計教案(第7章 實驗9)專題
實驗9
指針使用和數組的指針
一、
二、 1. 2. 3. 4. 實驗學時:2課時 實驗目標
掌握指針的概念、指針變量的定義和使用指針變量;
掌握指針變量的運算(取地址運算&、取內容運算*、指針移動的運算等) 學會使用數組的指針和指向數組的指針變量; 掌握指針與數組的關系;
實驗要求:
三、
1. 在上實驗課之前,每個同學必須預習指針變量的定義、賦值和取地址運算&、取內容運算*、指針移動的運算等操作,數組元素的多種便是方法; 2. 每個同學必須將實驗的題目、程序編寫完畢,做好充分的準備。 3. 所有實驗環節均由每位同學獨立完成,嚴禁抄襲他人實驗結果,若發現有結果雷同者,按實驗課考核辦法處理。
四、 實驗步驟和內容
1.分析下列程序的運行結果,并上機驗證。 1) void main() {
int i, j, *pi, *pj; pi=&i; pj=&j; i=5; j=7;
printf( "%d %d %d %d", i, j, pi, pj );
printf( " %d %d %d %d ", &i, *&i, &j, *&j ); }
程序的運行結果是:______________________ 2) void main() {
int a[ ]={ 1, 2, 3 }; int *p, i; p=a;
for ( i=0; i<3; i++ )
printf( "%d %d %d %d ", a[i], p[i], *(p+i), *(a+i) ); } 程序的運行結果是:______________________ 3) void main() {
int a[ ]={ 2, 5, 3, 6, 8 }; int *p, i=1, s=0;
for ( p=a; p
1) 用地址法輸入輸出二維數組各元素。 2) 用指針法輸入輸出二維數組各元素。
五、 思考題
1. 數組的指針和指向數組的指針變量的區別 2. 分析指針與數組的關系
六、
實驗小結:
第四篇:C語言程序設計教案 第十章指針
第十章 指 針
課題:
教學目的: 教學重點: 教學難點: 第十章 指針
§1-§2
1、了解指針與地址的概念
2、掌握指針變量的定義、初始化及指針的運算 指針變量的定義、初始化及指針的運算
指針的運算
步驟一 復習引導
指針是C語言的一個重要概念,也是C語言的一個重要特色。正確而靈活地運用它,可以有效地表示復雜的數據結構;能動態分配內存;能方便地使用字符串;有效而方便地使用數組;在調用函數時能得到多于1個的值;能直接處理內存地址等,這對設計系統軟件是很必要的。
指針的概念比較復雜,使用也比較靈活,因此初學者時常會出錯,務請在學習本章內容時十分小心。
步驟二 講授新課
§10.1 地址和指針的概念
計算機的主存儲器被分成一個個存儲單元,為了區分各存儲單元,要為每個存儲單元編號,這個編號即地址。
例:i =3;
或 scanf(“%d”, &i);
是將3送給 i所在的空間。
例:將3送到變量I_pointer所“指向”的單元(即I所標志的單元)。
所謂“指向”,是通過地址來體現的,I_pointer中的值為2000,它是變量I 的地址,這樣就在I_pointer和變量之間建立起一種聯系,即通過I_pointer能知道I的地址,從而找到變量I的內存單元。因而在C語言中,將地址形象化地稱為“指針”。
意思是通過它能找到以它為地址的內存單元。一個變量的地址稱為該變量的“指針”。
內存單元的地址和內存單元的內容是兩個不同的概念。
指針:就是地址,即內存單元的編號。
指針變量:用來存放另一變量的地址(即指針)的變量。
如:地址2000是變量 i的指針;i_pointer是指針變量,其值就是指針2000。
§10.2變量的指針和指向變量的指針變量
變量的指針就是變量的地址。
存放變量地址的變量是指針變量,用來指向另一個變量。
*i_pointer 表示 i_pointer 所指向的變量。
一、定義一個指針變量
指針變量的定義包含三個方面的內容:
⑴ 指針類型說明,即定義變量為一個指針變量 ⑵ 指針變量名
⑶ 變量值(指針)所指向的變量的數據類型。 格式:
存儲類型
基類型
*指針變量名; 例:int *pointer_1, *pointer_2;
float *pointer_3;
char *pointer_4;
二、指針的引用
指針變量有兩個運算符: & :取地址運算符
功能:取變量地址;單目,右結合。
* :取內容運算符(“間接訪問”運算符)
功能:只能跟地址,取變量所指向單元的內容;單目,右結合。
例:&a為變量a的地址,
*p 為指針變量p所指向的存儲單元。
例:int a=5, *p=&a;
printf ( “%d”, *p ); main() { int a,b;
int *pointer_1,*pointer_2;
a=100;b=10;
pointer_1=&a;
/*把變量a的地址賦給pointer_1*/
pointer_2=&b;
/*把變量b的地址賦給pointer_2*/
printf(“%d,%d ”,a,b);
printf(“%d,%d ”,*pointer_1, *pointer_2); } 輸出結果:100, 10
100, 10
評注:
1、在第3行雖然定義了兩個指針變量,只是提供了兩個指針變量,但并未指向任何一個整型變量。稱為指針“懸空”。
2、最后一行的*pointer_1和pointer_2就是變量a和b。
3、程序中兩處出現*pointer_1等,含義不同。程序第3行中的*pointer_1表示定義指針變量pointer_1。它前面的*只是表示該變量是指針變量。程序最后一行中的*pointer_1則代表變量,即pointer_1所指向的變量。
4、第5行中的pointer_1=&a 是將a的地址賦給指針變量pointer_1,而不是*pointer_1。
注意:不應寫成:*pointer_1=&a;
5、從上例中可看出,*pointer_1等價于a,*pointer_2等價于b,故凡在程序中出現a的地方均可用 *pointer_1 代替。所以,若有: int x, y, *px=&x ; 則下面的運算均是正確的: y=*px+1;
/*把 x 的內容加1 送變量y*/ printf(“%d ”, px );
/*打印當前x 的內容*/ d=sqrt((double) px);
/*把x的平方根送變量d*/ px=0;
/*把 x 置為0*/ *px+=1;
/*把 x 的值加 1*/ (*px)++;
/*使 x 的值加 1*/ y=(*px)++;
/*即y=x, x++*/
6、假設px和py都被定義為指向int 對象的指針,而且px當前已指向了int 型變量x,則執行:
py=px;
/*把指針px的內容拷貝到指針py中去*/ 即
py和px 這兩個不同的指針指向了同一對象x
7、指針不是整數,不能將它與整數混為一談。 例:
# include main() { int x=100,*p; p=x; printf(“%d”, p ); }
例如:
# include main() { int a, b, *d=&a;
b = d;
printf( “%d ”, b );
……
}——編譯不出錯,但得不到希望的值
關于&和*運算符的說明:
假設已執行
pointer_1=&a;
1、&*pointer_1含義是什么?
&*pointer_1與&a相同,即變量a的地址。
2、*&a的含義是什么?
先進行&a運算,得a的地址,再進行*運算。
*&a、*pointer_1及變量a等價。
3、(*pointer_1) + + 相當于a + +。
它與*pointer_1 + + 不同。
4、*pointer_1 + + 等價于*(pointer_1 + +),即先進行*運算,得到a的值,然后使pointer_1的值改變,這樣pointer_1不再指向a了。
例10.2:輸入a和b兩個整數,按先大后小的順序輸出a和b。
main() { int *p1,*p2,*p, a, b;
scanf(“%d,%d”,&a,&b);
p1=&a; p2=&b;
if (a
{p=p1; p1=p2; p2=p;}
printf(“ a=%d,b=%d ”,a,b);
printf(“max=%d,min=%d ”,*p1,*p2);
} 運行情況: 5,9 a=5,b=9 max=9,min=5
三、指針變量作為函數參數
例10.3對輸入的兩個整數按大小順序輸出。 先考察如下程序,看是否能得到預期的結果
swap(int p1, int p2) { int temp; temp = p1; p1 = p2; p2 =temp; } main() { int a, b;
scanf(“%d, %d”, &a, &b);
if(a
printf(“ %d,%d ”,a,b); } 不能得到預期的結果。 改為:
swap(int *p1,int *p2) { int temp;
temp = *p1;
*p1 = *p2;
*p2 =temp; } main() { int a,b;
int *pointer_1,*pointer_2;
scanf(“%d,%d”,&a,&b);
pointer_1=&a;
pointer_2=&b;
if(a
swap(pointer_1,pointer_2);
printf(“ %d,%d ”,a,b); }
注:如果想通過函數調用得到n個改變的值,可以:
1、在主調函數中設n 個變量,用n個指針變量指向它們;
2、然后將指針變量作實參,將這n 個變量的地址傳給所調用的函數的形參;
3、通過形參指針變量,改變該n個變量的值;
4、主調函數中就可以使用這些改變了值的變量。
四、指針(變量)的初始化 指針置初始化值的格式:
存儲類型
基類型
*指針名=初始化值; 如:main()
{ static int a;
int *p=&a, *p1=p;
…… } 再如: int *p = 0;
或
int *p = NULL;
五、指針的運算
1、指針的算術運算
指針僅能進行加、減算術運算
如:p+n , p-n , p++ , p-- , ++p , --p
p-= n , p+= n , p1-p2 等 其中n是整數,p、p
1、p2均為指針;
施行加法運算時,指針向地址增大的方向移動; 施行減法運算時,指針向地址減小的方向移動; 移動長度取決于指針的基類型,由計算機決定; 如有:int a,b,c, *pt =&a;
則
pt++ 則指針向后移動兩個字節; 再如:main()
{ int *p1,a=8,b=3;
p1=&a;
printf(“%d,%d ”, (*p1)++, *p1++);
printf(“%d,%d ”,a, *p1);
} 運行結果:3 , 8
8 , 4 注:p1+k = p1+k*sizeof(p1的基類型);
p1- k = p1- k*sizeof(p1的基類型); 如:
strlen(char *s)
{ char *p=s;
while(*p!=„??)p++;
return(p-s);
}
2、指針的關系運算
設指針p1,p2指向同一數組中的元素,則
p1
p1
p1= =p2:
表示p
1、p2指向數組中的同一元素;
同理可推出>、>=、<=、!=比較的意義; 不可將指針與其他類型的對象作比較;
若兩指針指向不同數組中的元素,也不可比較;
允許將指針與NULL或數值0進行= =或!=的比較,以便判定一個指針是否為空指針。
步驟三 課堂小結
本課介紹了指針與地址的概念,指針變量的定義、初始化及指針的運算。
指針:就是地址,即內存單元的編號。
指針變量:用來存放另一變量的地址(即指針)的變量。
例如:int a=5, *p=&a;
printf ( “%d”, *p );
注意:運算符*和&的用法,指針變量的自加自減運算。 步驟四 布置作業
課后作業:第十章課后練習 10.1 10.2 課題:
教學目的: 教學重點: 教學難點: 第十章 指針
§3 掌握指針與數組的知識 指向數組的指針變量
指向二維數組的指針
步驟一 復習引導
上節課介紹了指針變量的定義及其賦值。一個變量有地址,一個數組包含若干元素,每個數組元素都在內存中占用存儲單元,它們都有相應的地址。指針變量既然可以指向變量,當然也可以指向數組和數組元素(把數組起始地址或某一元素的地址放到一個指針變量中)。
步驟二 講授新課
所謂數組的指針是指數組的起始地址,數組元素的指針是數組元素的地址。
引用數組元素可以用下標法(如a[3]),也可以用指針法,即通過指向數組元素的指針找到所需的元素。使用指針法能使目標程序質量高(占內存少,運行速度快)。
一、指向一維數組的指針
定義形式:
int a[10];
int *p;
p=&a[0];
或
p=a;
含義:把數組的首地址賦給指針變量p。
也即: int *p=&a[0];
或
int *p=a;
二、通過指針引用數組元素
按C的規定:如果指針變量p已指向數組中的一個元素,則p+1指向同一個數組中的下一個元素(而不是簡單地加1)。
如果p的初值為&a[0],則:
p+i ? a+i ? &a[i],即指向a數組的第i個元素。
*(p+i) ? *(a+i) ?
a[i]。
指向數組的指針變量也可以帶下標,如p[i]與*(p+i)等價 引用數組元素時,可以用:
1、下標法,如:a[i]
2、指針法,如:*( a+i )
或
*( p+i )
其中,a是數組名,p是指向數組的指針
例10.5:輸出數組中的全部元素
假設有一個a數組,整型,有10個元素。用三種方法輸出各元素的值:
1、下標法: main() { int a[10], i ;
for( i=0; i<10 ; i++)
scanf(“%d”,&a[i]);
printf(“ ”);
for( i=0 ; i<10; i++)
printf(“%d”,a[i]); }
2、利用數組名計算數組元素地址,找出元素的值。 main() { int a[10], i ;
for( i=0; i<10 ; i++)
scanf(“%d”,&a[i]);
printf(“ ”);
for( i=0 ; i<10; i++)
printf(“%d”,*(a+i)); }
3、用指針變量指向數組元素。 main() { int a[10], *p, i ;
for( i=0; i<10 ; i++)
scanf(“%d”,&a[i]);
printf(“ ”);
for( p=a; p<(a+10); p++)
printf(“%d”,*p ); } 評注:
1、第1和2種方法執行效率是相同的。
2、第3種方法效率高。
3、用下標法比較直觀。
在使用指針變量時,有幾個問題要注意:
1、指針變量可以實現使本身的值改變。 如:for(p=a; p<(a+10); p++)
2、要注意指針變量的當前值。
如:要通過指針變量輸出a數組的10個元素。 main() { int a[10], i , *p=a;
for( i=0; i<10 ; i++)
scanf(“%d”, p++);
printf(“ ”);
for( i=0 ; i<10; i++,p++)
printf(“%d”, *p); } 這個程序輸出的并不是a數組中各元素的值。因為第一個 for 循環結束時,p已經指向數組的末尾。再繼續下去,p指向的是a數組下面的10個元素,是不可預料的。 可加一句為:p=a;
3、用指針變量p指向數組元素,可以指到數組以后的內存單元。C編譯程序不作下標越界檢查。
4、注意指針變量的運算。如果p指向數組a, ⑴ p++ (或 p+=1 ),使p指向下一元素a[1]。 ⑵ *p++
等價 *(p++)。作用是先得到p指向的變量的值(即*p),然后再使p+1→p。 ⑶ *(p++)與*(++p) 不同。前者為a[0],后者為a[1] ⑷ (*p)++表示p指向的元素值加1,即(a[0])++ ⑸ 如果p當前指向a數組中第i個元素,則:
*(p- -)相當于a[i- -],先對p進行*運算,再使p自減; *(+ + p)相當于a[+ +i],先使p自加,再作*運算。 *(-) { temp=*i; *i = *j; *j =temp; } return; } main() { int i, a[10],*p=a; printf(“The original array: ”); for( i=0; i<10; i++,p++) scanf(“%d”, p); printf(“ ”); p=a; inv(p,10); printf(“The array is : ”); for( p=a; p
例10.10:用選擇法對10個整數排序。 main() {int *p, i, a[10]; p=a; for( i=0; i<10; i++) scanf(“%d”,p++); p=a; sort(p,10); for( p=a, i=0; i<10; i++) { printf(“%d”,*p);p++;} } sort(int x[],int n) { int i, j, k, t; for( i=0; ix[k]) k=j; if( k !=i) { t = x[i]; x[i] = x[k]; x[k] = t; } }
四、指向二維數組的指針和指針變量
1、二維數組的地址如:
int a[3][4] A
a[0]
a[0] [0] a[0] [1] a[0] [2] a[0] [3]
A+1
a[1]
a[1] [0] a[1] [1] a[1] [2] a[1] [3]
A+2
a[2]
a[2] [0] a[2] [1] a[2] [2] a[2] [3] 例:int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
設首地址為2000。
a[k]+p ( 0<=k< i , 0<=p
由此得到: *(a[k]+p) 等價于a[k][p]; a[0]與&a[0][0]等價;
a+k與&a[k][0]等價,而a[0]+k與&a[0][k]等價; *(a+i)可理解為a[i],故有如下等價關系:
a+0
等價于 a[0]、
a[0]+0、
&a[0][0]、
*(a+0)
a+1
等價于 a[1]、
a[1]+0、
&a[1][0]、
*(a+1)
a+(i-1) 等價于 a[i-1]、a[i-1]+0、
&a[i-1][0]、
*(a+i-1)
*(a+k)與*a[k]是不同的,前者相當于a[k],是一個地址值;后者相當于*(a[k]+0)或*&a[k][0],是數組元素a[k][0]中存儲的值。 數組元素a[k][p]就是*(a[k]+p),即*(*(a+k)+p)
步驟三 課堂小結
本課介紹了指向數組的指針,主要是指向一維數組的指針。用指針變量p指向數組a,指針變量p可以++、--,表示指向數組的上一元素或下一元素。但C編譯程序不作下標越界檢查。使用指針既方便有靈活,但初學者容易搞錯。
步驟四 布置作業
課后作業:第十章課后練習 10.31 10.5 課題:
教學目的: 教學重點: 教學難點: 第十章 指針
§3-§4 在掌握指針與數組的基礎上,掌握字符串的指針與指向字符串的指針變量 指向字符串的指針變量
用指針處理字符串
步驟一 復習引導
上節課介紹了指向一維數組的指針及二維數組的地址,指向一維數組的指針也即指向元素的指針,那么指向二維數組的指針是怎樣的呢?它有兩種類型。
步驟二 講授新課
2、指向二維數組的指針變量
——(1)指向數組元素的指針變量
設指針變量p=a[0]
(&a[0][0]、a、a+0、*(a+0) ) 計算a[i][j]在n*m數組中的位置:
例:……
for( i=0; i<3; i++)
{for( j=0; j<4; j++ ) printf (“%4d”, *(p+i*m+j));
printf(“ ”); }
……
例:用指針變量輸出數組元素的值。 main() { int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int *p;
for( p=a[0]; p
{if((p-a[0])%4 == 0) printf(“ ”);
printf(“%4d”, *p);
} } 計算a[i][j]在n*m數組中的位置:a[0]+i*m+j
——(2)行指針(指向由m個元素組成的一維數組的指針變量)
定義:指針基類型
(*指針名)[m]
其中,m表示二維數組每行有m列;
如: int (*p)[3];
于是,p
指向第0行元素的起始存儲地址;
p+1
指向第1行元素的起始存儲地址;……
p+I
指向第i 行元素的起始存儲地址;
而每一行的元素的表示形式為:
第0行元素的表示為 (*p)[j];
第1行元素的表示為 (*(p+1))[j];……
第i 行元素的表示為 (*(p+ I))[j];
例 :
#include main() { int (*p)[4], j;
int a[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}; for(p=a; p
for(j=0;j<4; j++)
if( j==3 ) printf(“%4d ”, (*p)[j] );
else printf(“%4d” , (*p)[j] );
} 改寫為:
#include main() { int (*p)[4], i, j;
int a[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
p=a;
for( i=0; i<4; i++)
for(j=0;j<4; j++)
printf(j==3?“%4d ”: “%4d” , *(*(p+i )+j) );
}
3、多維數組的指針作函數參數
一維數組的地址可以作為函數參數傳遞,多維數組的地址也可作函數參數傳遞。在用指針變量作形參以接受實參數組名傳遞來的地址時,有兩種方法:
1、用指向變量的指針變量;
2、用指向一維數組的指針變量。
例;有一個班,3個學生,各學4門課,計算總平均分數,以及第n個學生的成績。 main() { void average(float *p ,int n);
void search(float (*p)[4], int n);
float score[3][4]={{65,67,70,60},{80,87,90,81}, {90,99,100,98}};
average( *score, 12);
/*求12個分數的平均分*/
search(score , 2);
/*求第2個學生成績*/ } void average(float *p , int n) {float *p_end;
float sum= 0,aver;
p_end = p+n-1;
for(; p<=p_end; p++) sum =sum+(*p); aver = sum/n; printf(“average=%5.2f ”,aver); } void search(float (*p)[4], int n) { int i; printf(“the score of No %d are: ”,n); for( i=0; i<4; i++) printf(“%5.2f”, *(*(p+n)+i)); }
例10.15 在上題基礎上,查找一門以上課程不及格的學生,打印出他們的全部課程的成績。 main() { void search(float (*p)[4], int n); float score[3][4]={{65,57,70,60},{58,87,90,81),{90,99,100,98}}; search(score, 3); } void search(float (*p)[4], int n) {int i, j, flag; for( j=0; j
§10.4字符串的指針和指向字符串的指針變量
一、字符串的表示形式
1、用字符數組存放一個字符串。 如:main()
{ char string[ ]=“I love China!”;
printf(“%s ”, string); }
2、用字符指針指向一個字符串。
如:main()
{ char *string=“I love China!”;
printf(“%s ”, string); } 例10.18 將字符串a復制為字符串b。 main() { char a[]=“I am a boy.” , b[20];
int i;
for( i=0; *(a+i)!=„??; i++) *(b+i) = *(a+i);
*(b+i) = „??;
printf(“string a is : %s ”, a);
printf(“string b is :”);
for( i=0; b[i]!=„??; i++ )
printf(“%c”, b[i] );
printf(“ ”); }
例10.19 用指針變量來處理上例。 main() { char a[ ]=“I am a boy.” , b[20], *p1, *p2;
int i;
p1= a; p2= b;
for( ; *p1!=„??; p1++,p2++ ) *p2 = *p1;
*p2 = „??;
printf(“string a is : %s ”, a);
printf(“string b is :”);
for( i=0; b[i]!=„??; i++)
printf(“%c”, b[i]);
printf(“ ”); }
二、字符串指針作函數參數
例10.20:用函數調用實現字符串的復制。 ——(1)用字符數組作參數。
void copy_string(char from[],char to[]) { int i=0;
while( from[i]!=„?? )
{ to[i] = from[i]; i++;}
to[i]=„??;
} main() { char a[]=“I am a teach.”;
char b[]=“you are a student.”;
printf(“string a= %s string b=%s ”,a,b);
copy_string(a,b);
printf(“ string a=%s string b=%s ”,a,b); } ——(2)形參用字符指針變量 void copy_string(char *from,char *to) { for(; * from!=„??; from++, to++ )
*to = *from;
*to=„??;
} ——(3)對copy_string函數還可以簡化。 ① void copy_string(char *from, char *to)
{ while((*to =* from)!=„??)
{ to ++; from++;}
} ② void copy_string(char *from, char *to)
{ while((*to ++ =* from++)!=„??); }
③void copy_string(char *from, char *to)
{ while(* from!=„??)
*to++ = *from ++;
*to = „??;
} ④void copy_string(char *from, char *to)
{ while(*to++ = *from ++); }
⑤void copy_string(char *from, char *to)
{ for( ;*to++ = *from ++;); }
⑥void copy_string(char from[], char to[])
{ char *p1,*p2;
p1=from; p2=to;
while((*p2++ = *p1++)!=„??);
}
三、字符指針變量和字符數組的討論
1、 字符數組由若干個元素組成,每個元素中放一個字符,而字符指針變量中存放的是地址,決不是將字符串放到字符指針變量中。
2、賦值方式。對字符數組只能對各個元素賦值,不能用以下辦法對字符數組賦值;
char str[14];
str=“I love China.”;對字符指針變量,可以采用下面方法賦值:
char *a;
a= “I love China.”;
/*賦給a的是串的首地址*/
3、對字符指針變量賦初值:
char *a=“I love China.”;
等價于
char *a;
a=“I love China.”;
而對數組的初始化:
char str[14]={“I love China.”}; 不等價于
char str[14];
str[]=“I love China.”;
即數組可以在變量定義時整體賦初值,但不能在賦值語句中整體賦值。
4、如果定義了一個字符數組,在編譯時為它分配內存單元,它有確定的地址。 而定義一個字符指針變量時,給指針變量分配內存單元,在其中可以放一個地址值,也就是說,該指針變量可以指向一個字符型數據,但如果未對它賦一個地址值,則它并未具體指向一個確定的字符數據。這很危險。
如: char str[10];
scanf(“%s”,str); 是可以的
char *a;
scanf(“%s”,a);
能運行,但危險,不提倡,在a單元中是一個不可預料的值。
應當 char *a,str[10]; a=str; scanf(“%s”,a);
5、指針變量的值是可以改變的,數組名雖然代表地址,但它的值是不能改變的??梢韵聵诵问揭盟傅淖址械淖址?。
如:main()
{char *a=“I love China.”;
a=a+7;
printf(“%s”,a); }
又如:char str[]={“I love China.”}; str=str+7; printf(“%s”,str); 是錯的
6、用指針變量指向一個格式字符串,可以用它代替printf函數中的格式字符串。也可以用字符數組實現,但由于不能采用賦值語句對數組整體賦值。
如:char *format; format=“a=%d,b=%f ”; printf(format,a,b);
等價于:printf(“a=%d,b=%f ”,a,b);
也可以:char format[ ]=“a=%d,b=%f ”; printf(format,a,b);
步驟三 課堂小結
本課介紹了指針與二維數組、指針與字符串,指向二維數組的指針有指向元素的指針和行指針,使用時應注意它們的區別。我們既要掌握用數組處理字符串,也要掌握用指針變量處理字符串。要區分這兩種方法的不同之處。
步驟四 布置作業
課后作業:第十章課后練習 10.61 10.7 課題: 第十章 指針
§5-§7 教學目的: 了解指針與函數的概念 教學重點:
教學難點: 指針數組,二級指針 掌握指針數組,二級指針等知識 掌握指針數組,二級指針等知識
步驟一 復習引導
前面介紹了指針與維數組、指針與字符串,我們可以用指針變量指向整型變量、字符串、數組,也可以指向一個函數。
步驟二 講授新課
§10.5函數的指針和指向函數的指針變量
函數的地址:函數存儲區域的首地址就是該函數的入口點,其函數名表示了入口地址。
一、函數指針變量的定義:
存儲類型
數據類型
(*函數指針名)( );
例:static int (*p)( ); 例10.23 求a和b中的大者。
main()
{ int max(int, int);
int a,b,c;
scanf(“%d,%d”,&a,&b);
c=max(a,b);
printf(“a=%d,b=%d,
max=%d”,a,b,c);
} max(int x, int y) { int z;
if(x>y) z=x;
else z=y;
return(z); } 法2:main()
{
int max(int, int);
int (*p)( );
int a,b,c;
p=max;
/*將地址送入p */
scanf(“%d,%d”,&a,&b);
c=(*p)(a,b);
/*與max(a,b)等價*/
printf(“a=%d,b=%d,max=%d”,a,b,c);
} 注:int (*p)()定義p是一個指向函數的指針變量,此函數帶回整型的返回值。
說明:
1、函數的調用可以通過函數名調用,也可以通過函數指針調用。
2、(*p)() 表示定義一個指向函數的指針變量,它不是固定指向哪一個函數的,而只是表示定義了這樣一個類型的變量,它是專門用來存放函數的入口地址的。
3、在給函數指針變量賦值時,只需給出函數名而不必給出參數,如:p=max; 。
4、用函數指針變量調用函數時,只需將(*p)代替函數名即可(p為指針變量名),在(*p)之后的括號中根據需要寫上實參。如:c=(*p)(a,b);
5、對指向函數的指針變量,像p+n、p++、p--等運算是無意義的。
二、用指向函數的指針作函數參數
函數的參數可以是變量、指向變量的指針變量、數組名、指向數組的指針變量等?,F介紹指向函數的指針也可以作為參數,以便實現函數地址的傳遞,也就是將函數名傳給形參。
它的原理可以簡述如下:有一個函數(假設函數為sub),它有兩個形參(x1和x2),定義x1和x2為指向函數的指針變量。在調用函數sub時,實參用兩個函數名f1和f2給形參傳遞函數地址。這樣在函數sub中就可以調用f1和f2函數了。
有人會問,既然在sub函數中要調用f1和f2函數,為什么不直接調用f1和f2而用函數指針變量呢?的確,如果只是用到f1和f2,完全可以直接在sub函數中直接f1和f2,而不必設指針變量x
1、x2。但是,如果在每次調用sub函數時,要調用的函數是不固定的,這次調用f1和f2,而下次要調用f3和f4,第三次要調用的名作為實參即可,sub函數不必作任何修改。這種方法是符合結構化程序設計方法原則的,是程序設計中常使用的。
例10.24 設一個函數process,在調用它的時候,每次實現不同的功能。
main() { int max(int ,int );
int min(int , int);
int add(int , int);
int a, b;
printf(“enter a and b:”);
scanf(“%d,%d”, &a, &b);
printf(“max=”); process(a,b,max);
printf(“min=”); process(a,b, min);
printf(“sum=”); process(a,b, add); }
max(int x, int y)
{ int z;
if(x>y) z = x; else z = y;
return(z);
}
min(int x, int y)
{ int z;
if(x
else z = y;
return(z); } add( int x, int y) { int z;
z = x+y;
return(z); }
process(int x, int y, int (*fun)(int ,int)) {int result;
result = (*fun)(x,y);
printf(“%d ” , result ); }
在函數process定義中,int (*fun)(int,int)表示fun是指向函數的指針,該函數是一個整型函數,有兩個整型形參。
在三次調用中,分別將函數名max、 min、 add作為實參將其入口地址送給process函數中的形參fun(fun是指向函數的指針變量)。例:process函數中的(*fun)(x,y)相當于max(x,y)。
注:在使用時,應將函數聲明,這樣編譯系統將它按函數名處理(把函數入口地址作實參值),而不是作為變量名,不致出錯。
Process函數無固定功能。如果max、 min、 add換成其它函數,此process函數不需改變,只要修改每函數的函數體。
§10.6 返回指針值的函數
一個函數可以帶回一個整型值、字符值、實型值等,也可以帶回指針型的數據,即地址。其概念與以前類似,只是帶回的值的類型是指針類型而已。 格式: 類型名
*函數名(參數表); 例: int
*a(int x, int y);
a是函數名,調用它以后能得到一個指向整型數據的指針(地址)。
例10.25 有若干個學生的成績(每個學生有4門課程),要求在用戶輸入學生序號以后,能輸出該學生的全部成績。用指針函數來實現。 float *search( float (*pointer)[4], int n)
{float *pt;
pt = *(pointer +n);
return( pt );
} main() { float score[][4]={{60,70,80,90},{56,89,67,88),{34,78,90,66}};
float *p;
int i, m;
printf(“enter the number of student:”);
scanf(“%d”,&m);
printf(“The score of No.%d are: ”, m);
p=search(score, m);
for( i=0; i<4; i++)
printf(“%5.2 ”, *(p + i));
}
例10.26 對上例中的學生,找出其中有不及格課程的學生及其學生號。 float *search(float (*pointer)[4]) { int i;
float *pt;
pt = *(pointer+1);
for( i=0; i<4 ; i++)
if(*(*pointer+i)<60) pt = *pointer;
return(pt); } main() { score[][4]={{60,70,80,90},{56,89,67,88),{34,78,90,66}};
float *search(float (*pointer)[4], int n);
float *p;
int i, m;
for( i=0; i<3; i++) { p=search(score+i);
if( p==*(score + i))
{ printf(“ No.%d score:”, i);
for(j=0; j<4; j++)
printf(“%5.2 ”, *(p + i));
printf(“ ”); }
} }
關于函數的返回值是指針的情況,程序設計時應注意:
1、因數組名是地址常量,用于接受這種返值的對象不能是數組名,這與把數組名作為實在參數傳遞給形式參數的情況不同(作為形式參數的數組名總被視為指針)。
2、不應將局部于被調用函數的指針作為返值返回給調用者,理由是局部于被調用函數的數據對象執行返回語句離開被調用函數后,原來分配的被調用函數的所有局部對象的存儲空間立即被收回(釋放),雖然調用者已經獲得了正確的地址值,但此時它指向的存儲區域的內容可能已經發生了變化,或許已經分配給其他函數了。如果調用函數中仍然使用這個指針去存取那個區域中的數據,得到的可能并非原先的數據。對于這種情況的正確做法是應該把所處理的對象定義成全局對象或static型對象。
§10.7 指針數組和指向指針的指針
一、指針數組的概念
一個數組中的元素均為指針類型,稱為指針數組。
形式:
存儲類型
類型名
*數組名[數組長度]
例如:
static
int
*p[4]
定義指針數組時也可以進行初始化,如:
static char ch[][20]={“Beijing”,“Nanjing”,“Shanghai”,“Guangzhou”};
char *p[ ]={ch[0],ch[1],ch[2],ch[3]}; 該例也可以等價定義為:
char *p[ ]={“Beijing”,“Nanjing”,“Shanghai”,“Guangzhou”};
例如: main( ) { int i, min, j;
char *temp, *p[ ]={“Beging”,“Nanjing”,“Shanghai”, “Guangzhou”};
for( i=0; i<3; i++)
{ min=i;
for( j=i+1; j<4; j++)
if (strcmp(p[j], p[min])<0) min=j;
temp=p[i]; p[i]=p[min]; p[min]=temp;
}
for(i=0; i<4; i++)
printf(“%s ”, p[i]); } 注意:不能把一個二維數組與一個指針數組混淆;
如:int a[10][10]; 與
int *b[10];的異同點 訪問形式相同;如a[5][5],b[5][5]; 占用的存儲空間數不同;
每一個b[i]必須置初值者能使用; 使用b優越
不需進行復雜的下標計算;
b[i]指向的數組并非一定要10個元素,但a中,每一行上的元素個數必須相同;因指針指向的是一個地址,故對b而言,各個b[i]指向的存儲區域之間不必連續;而對a而言,必須存儲100個連續的存儲int型數據對象的區域。
例10.27 將若干字符串按字母順序(由小到大)輸出。 main() { void sort(char *name[], int n);
void print(char *name[], int n);
char *name[]={“Follow me”, “Basic”, “Great Wall”, “Fortran”, “Computer”};
int n=5;
sort(name, n);
print(name, n);
} void sort(char *name[], int n) { char *temp;
int i, j, k;
for( i=0; i
{ k=i ;
for( j=i+1; j
if( strcmp(name[k], name[j])>0) k=j; if( k!=i )
{temp=name[i];
name[i]=name[k];
name[k]=temp;}
} } void print(char *name[], int n); { int i;
for( i=0; i
}
二、指向指針的指針
在本章開頭已提到“間接訪問”變量的方式。利用指針變量訪問另一個變量就是“間接訪問”。
如果在一個指針變量中存放一個目標變量的地址,這就是“單級間址”。指向指針的指針用的是“二級間址”方法。從理論上講,間址方法可以延伸到更多的級。但實際上在程序中很少有超過二級間址的。級數愈多,愈難理解,容易產生混亂,出錯機會也多。
二級指針的定義:
char **p;
含義:表示指針變量p是指向一個字符指針變量(即指向字符型數據的指針變量)的。 main( ) { int i, min, j;
char *temp, *p[ ]={“Beging”,“Nanjing”,“Shanghai”, “Guangzhou”};
char **pp;
pp=p;
for(i=0; i<3; i++)
{ min=i;
for( j=i+1; j<4; j++)
if (strcmp(*(pp+j),*(pp+min))<0) min=j;
temp=*(pp+i);
*(pp+i)=*(pp+min);
*(pp+min)=temp;
}
for (i=0; i<4; i++) printf(“%s ”,*pp++); } 例10.28 使用指向指針的指針。 main() { char *name[]={“Follow me”, “Basic”, “Great Wall”, “Fortran”, “Computer”};
char **p;
int i;
for( i=0; i<5; i++)
{ p=name+i;
printf(“%s ”, *p);
}
} 例 main() { static int a[5]={1,3,5,7,9};
int *num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};
int **p, i;
p= num;
for( i=0; i<5 ; i++)
{ printf(“%d ”, **p);
p++;
}
} 運行結果:
9 步驟三 課堂小結
本課介紹了指針數組、二級指針、指針與函數。要搞清它們的定義及應用; 注意區分:
char a[5];
與
char (*a)[5];
int
*p(int x);
與
int (*p)( );
步驟四 布置作業
《C語言習題集》同步練習 課題: 第十章 指針
§7-§8 教學目的: 了解指針數組作main函數的形參 教學重點:
教學難點: 指針的應用 掌握指針的應用 掌握指針的應用
步驟一 復習引導
上節課介紹了二級指針、指針數組,而指針數組的一個重要應用是作為main函數的形參。main()函數是我們C語言程序必不可少的,以往使用時main()是不帶參數的。實際上是可帶參數的,如:main(argc, argv) 。
步驟二 講授新課
三、指針數組作main函數的形參
帶參數的main原型:
main( int argc, char *argv[ ] )
{ ……
}
說明:
第1個參數是指命令行中參數的個數,含文件名本身。
第2個參數是一個指向字符串的指針數組。
main函數是由系統調用的。當處于操作命令狀態下,輸入main所在的文件名(經過編譯、連接后得到的可執行文件名),系統就調用main函數。參數應和命令一起給出。 命令形式:
命令名
參數1
參數2
……參數n 例如:有一個目標文件名file1,今想將兩個字符串“China”, “Beijing”作為傳送給main函數的參數??蓪懗桑?/p>
file1 China Beijing
例:編寫一程序echo.c,實現將命令行上除程序名之外的所有給出的其他參數都回顯到顯示器上。
main(int argc, int *argv[ ]) { while(argc>1) { ++argv;
printf(“%s”, *argv);
-- argc; } }
若將該程序編譯、連接、裝配成echo.exe,則在命令行上輸入:
echo hello, world! 則通過虛實結合后得:argc=3,argv[0]指向echo,argv[1]指向hello,argv[2]指向world! 結果為:hello, world!
§10.8有關指針的數據類型和指針運算的小結
一、有關指針的數據類型的小結
見書中的表
二、指針運算小結
1、指針變量加(減)一個整數 例:p++、p--、p+i、p-=I等
2、指針變量賦值
將一個變量地址賦給一個指針變量。 p=&a; p1=p2;
3、指針變量可以有空值,即該指針變量不指向任何變量。 如 :
p=NULL;
4、兩個指向同一數組元素的指針變量可以相減
5、兩個指向同一數組的指針變量可作關系運算
習題舉例:
習題10.4
有n個整數,使其前面各數順序向右移m個位置,最后m個數變成最前面m個數。寫一函數實現以上功能,在主函數中輸入n個整數,并輸出調整后的n個數。
main() { int number[20],n,m,I;
printf(“How many number?”);
scanf(“%d”,&n);
printf(“Input %d number: ”,n);
for( i=0; i
scanf(“%d”,&number[i]);
printf(“How many place you want to move?”);
scanf(“%d”,&m);
move(number, n, m);
printf(“Now,they are: ”);
for( i=0; i
printf(“%d”, number[i]); } move(int array[20], int n, int m) { int *p,array_end;
array_end = *(array+n-1);
for(p= array+n-1; p>array; p--)
*p= *(p-1);
*array=array_end;
m--;
if(m>0) move(array, n, m); }
習題10.5 有n個人圍成一圈,順序排號。從第一個人開始報數(從1到3報數),凡報到3的人退出圈子,問最后留下的是原來第幾號的那位。 程序: main() { int i, k, m, n, num[50], *p;
printf(“Input number of person:n=”);
scanf(“%d”,&n);
p=num;
for( i=0; i
*(p+i) = i+1;
i=0; k=0; m=0;
while ( m
{ if( *(p+i)!=0) k++;
if(k==3)
{ *(p+i)=0; k=0; m++; }
i++;
if( i= =n) i=0;
}
while(*p==0) p++;
printf(“The last one is NO.%d ”,*p);
}
習題10.6
寫出一個函數,求一個字符串的長度。在main函數中輸入字符串,并輸出其長度。 main() { int len;
char *str[20];
printf(“Input string:”);
scanf(“%s”, str);
len=length(str);
printf(“The length of string is %d.”,len); }
length(char *p) { int n;
n=0;
while(*p!=„??)
{ n++;
p++;
}
return(n); } 習題10.7
有一字符串,包含n個字符。寫一個函數,將此字符串中從第m個字符開始的全部字符復制成為另一個字符串。 main() { int m;
char *str1[20],*str2[20];
printf(“Input string:”);
gets(str1);
printf(“Which character that begin to copy?”);
scanf(“%d”,&m);
if (strlen(str1)
printf(“Input error!”);
else { copystr(str1,str2,m);
printf(“result:%s”,str2);
} }
copystr(char *p1, char *p2, int m) { int n;
n=0;
while( n
{n++ ;
p1++ ;
}
while( *p1!=„?? )
{ *p2 = *p1 ;
p1++ ; p2++ ;
}
*p2=„??; }
習題10.9 寫一個函數,將3×3的矩陣轉置。 main() { int a[3][3],*p, i;
printf(“Input matrix: ”);
for( i=0; i<3; i++) scanf(“%d %d %d”, &a[i][0], &a[i][1] , &a[i][2]);
p=&a[0][0];
move(p);
printf(“Now,matrix: ”);
for( i=0; i<3; i++)
printf(“%d %d %d”,&a[i][0], &a[i][1], &a[i][2]);
} move(int *pointer) { int i, j, t;
for( i=0; i<3; i++)
for( j=i; j<3; j++)
{ t= *(pointer+ 3*i + j);
*(pointer+ 3*i +j) = *(pointer+ 3*j + i);
*(pointer+3*j + i )=t;
}
} 習題10.16
輸入一個字符串,內有數字和非數字字符,如:
a123x456 17960?302tab5876 將其中連續的數字作為一個整數,依次存放到一數組a中。例如123放在a[0]中,456放在a[1]中……統計共有多少個整數,并輸出這些數。 #include main() { char str[50], *pstr ;
int i, j, k, m, e10, digit, ndigit, a[10], *pa;
printf(“Input a string: ”);
gets(str);
printf(“ ”);
pstr=&str[0];
pa=&a[0];
ndigit = 0; i = 0; j=0;
while( *(pstr+i)!=„??)
{ if( (*( pstr+i )>=„0?)&&(*( pstr+i )<=„9?) ) j++;
else { if( j>0 )
{ digit = *(pstr+i-1)-48;
k=1;
while( k
{ e10=1;
for(m=1; m<=k; m++) e10 =e10*10;
digit =digit+(*(pstr+i-k)-48)*e10;
k++;
}
*pa=digit; ndigit++;
pa++;
j=0;
}
}
i++;
}
printf(“There are %d numbers in this line.They are: ”,ndigit );
j=0;
pa=&a[0];
for( j=0; j
printf(“%d”, *(pa+j));
printf(“ ”); } 步驟三 課堂小結
本課主要講了一些習題,希望通過這些例子加深對指針的了解,看到指針在程序設計中的重要應用。同學們課后需要多看、多想、多練,逐步去體會指針這一重要的概念。 步驟四 布置作業
課后作業:第十章課后練習 10.10、10.11
第五篇:2010C程序教案(第10章)
【教學課題】
預編譯處理
(第10章預編譯處理,
1、2節) 【目的要求】
了解編譯預處理的特點和功能,掌握編譯預處理中的宏定義,理解文件包含。 【教學重點】
宏的定義與使用(無參和有參),理解帶參的宏和函數的區別。 【教學難點】
宏的定義與使用(無參和有參),理解帶參的宏和函數的區別。 【教學方法】
任務驅動法,問題引導法 【教學手段】
講授+多媒體演示+學生動手 【作業布置】
1、定義一個帶參數的宏,使兩個參數的值互換,并寫出程序,輸入兩個數作為使用宏時的實參。輸出已交換的兩個值。
2、分別用函數和帶參的宏,從3 個數中找出最大數。
一、提出任務,引入課題 例1:#include main() { int a„„} 例2:#include #define N 100 main() { int a[N];„„ }。
一般C程序的開發執行過程: 編輯 → 編譯 → 連接 → 執行 含有預處理命令的C程序:
編輯 → 預處理 → 編譯 → 連接 → 執行
二、分析任務,講授新課
C提供的預處理功能主要有以下三種: 宏定義、文件包含、條件編譯。
分別用宏定義命令、文件包含命令、條件編譯命令來實現。為了與一般C語句相區別,這些命令以符號“ #” 開頭。
(一)宏替換(P172)
宏: 代表一個字符串的標識符。
宏名:被定義為“宏”的標識符。
宏代換(展開):在編譯預處理時,對程序中所有出現的 “宏名”,用宏定義中的字符串去代換的過程。
不帶參數的宏定義
A、一般形式: #define 標識符 替換文本 例如:#define PI 3.14159 main() { float l,r; printf( “Input a number :”); scanf (“%f”,&r); l=2*PI*r printf(“l=%f ”,l); } 說明:
⑴宏名一般用大寫表示,以便與變量名區分。 ⑵使用宏名使程序易讀,易修改。 ⑶只作簡單的置換,不作正確性檢查。 ⑷宏定義不是C語句,不必在行末加分號。 ⑸宏名的作用域一般從自定義命令到本源文件結束。 ⑹可以用# undef命令終止宏定義的作用域。 ⑺宏定義允許嵌套,允許層層置換。
⑻宏名在源程序中用雙引號括起來,則TC中預處理不對其作宏代換。
例: printf(“L=%f”, L); 中雙引號內L不替換。
⑼宏定義與定義的變量不同,宏只作字符替換,不分配內存空間。 ⑽對“輸出格式”進行宏定義,可以減少書寫麻煩. 舉例:
例
1、不帶參數的宏的程序(見P173)
2、帶參數的宏定義
格式:#define 宏名(參數表) 替換文本
例:#define s(a,b) a*b {„„
area =s(3,2); „„}
對帶參的宏展開后,為area=3*2; 說明:
⑴對帶參數的宏展開只是將宏名后括號內的實參字符串代替#define命令行中的形參。 ⑵宏定義時,在宏名與帶參數的括號之間不應加空格,否則將空格以后的字符都作為替代字符串的一部分。
⑶有參宏的展開,只是將實參作為字符串,簡單地置換形參字符串,而不作任何語法檢查。在定義有參宏時,在所有形參和整個字符串外,均加一對圓括號。
帶參宏與函數的區別:
1、函數調用時,先求實參表達式值,后代入。而帶參的宏只是進行簡單的字符替換。
2、函數調用是在程序運行時處理的,分配臨時的內存單元。而宏展開則是在編譯時進行的,不分配內存單元,不進行值的傳遞,也無“返回值”。
3、對函數中的實參和形參都要定義類型,類型應一致。而宏不存在類型問題,宏名和參數無類型,只是一個符號代表,展開時代入指定的字符即可。
例
2、帶參數宏的使用實例(P174)
二、 “文件包含”處理
“文件包含”處理是指將指定的被包含文件的全部內容插到該控制行的位置處,使其成為源文件的一部分參與編譯。因此,被包含的文件應該是源文件。
通常置于源程序文件的首部,故也稱為“頭文件”。
C編譯系統提供的頭文件擴展名為“.h”,但設計者可根據實際情況,自行確定包含
文件的后綴、名字及其位置。
一般形式,#include “文件名” 或 #include <文件名> 二者的區別:
用尖括號時稱為標準方式,系統到存放C庫頭文件所在的目錄中尋找要包含的文件。
用雙引號時,系統先在用戶當前目錄中尋找要包含的文件,若找不到,再按標準方式查找。
說明:
編譯預處理時,預處理程序將查找指定的被包含文件,并將其復制到#include命令出現的位置。
常用在文件頭部的被包含文件,稱為“標題文件”或“頭部文件”,常以“h”作為后綴。
一條包含命令,只能指定一個被包含文件。如果要包含多個文件,則要用多條包含命令。
文件包含可以嵌套,即被包含文件又包含另一個文件。
三、解決任務,學生實踐
C語言中如何使用宏替換,如何使用文件包含。
四、針對難點,重點突破
1、帶參數宏定義的替換。
2、帶參數的宏和函數的區別。
五、拓展任務,學生實踐
1、輸入兩個整數,求它們相除的余數,用帶參的宏來實現,編程序。 提示:用一維數組存放所有約數。
六、檢查任務,評價學生