C語言程序設(shè)計(下)218_第1頁
C語言程序設(shè)計(下)218_第2頁
C語言程序設(shè)計(下)218_第3頁
C語言程序設(shè)計(下)218_第4頁
C語言程序設(shè)計(下)218_第5頁
已閱讀5頁,還剩213頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

C語言程序設(shè)計(下)

第一、二次課4學(xué)時第六章指針

第十一次課2學(xué)時學(xué)習(xí)目的1、通過本章的學(xué)習(xí)使學(xué)生掌握指針的意義及使用。2、應(yīng)知數(shù)組的指針的意義,數(shù)組元素的指針的意義,及使用數(shù)組名作函數(shù)參數(shù),應(yīng)會通過指針引用數(shù)組元素。學(xué)習(xí)重點1.指針的使用2、指針和數(shù)組的關(guān)系學(xué)習(xí)難點1.通過指針引用變量的意義2、指針和數(shù)組的關(guān)系3指針的根本概念指針變量的定義與引用指針與數(shù)組

為什么要學(xué)習(xí)指針?指針是C語言一個重要的概念也是C語言的重要特色。正確靈活的運用指針可以有效地表示負(fù)責(zé)的數(shù)據(jù)結(jié)構(gòu)。能動態(tài)的分配內(nèi)存,方便的使用字符串,有效的而方便的使用數(shù)組,在調(diào)用函數(shù)時能獲得一個以上的結(jié)果,能直接處理內(nèi)存單元地址等。而這些是設(shè)計系統(tǒng)軟件非常必要的,掌握指針可以有效的使程序簡潔、緊湊、高效。6.1指針的根本概念6.1.1指針的概念1.內(nèi)存及其地址“程序存儲〞就是在程序運行之前將程序和數(shù)據(jù)存入計算機內(nèi)存。所以在計算機中,所有的數(shù)據(jù)都是存放在存儲器中的。一般把存儲器中的一個字節(jié)稱為一個內(nèi)存單元,為了正確地訪問這些內(nèi)存單元,必須為每個內(nèi)存單元編號。根據(jù)一個內(nèi)存單元的編號即可準(zhǔn)確地找到該內(nèi)存單元。內(nèi)存單元的編號也叫做地址。6.1指針的根本概念6.1.1指針的概念

main(){floatx;inty;

…}變量的兩個物理意義200020012002200320042005…xy變量的內(nèi)容變量的地址6.1指針的根本概念6.1.1指針的概念2.變量地址的獲取變量的存儲單元是在編譯時〔對靜態(tài)存儲變量〕或程序運行時〔對動態(tài)存儲變量〕分配的,因此變量的地址不能人為確定,而要通過取地址運算符&獲取。例如在如下的程序段中:inta;floatb;charc;scanf〔"%d%f%c",&a,&b,&c〕;由&a、&b和&c分別得到變量a、b和c的內(nèi)存地址。值得注意的是,由于常量和表達(dá)式?jīng)]有用戶可操作的內(nèi)存地址,因此&不能作用到常量或表達(dá)式上。6.1指針的根本概念6.1.1指針的概念3.指針與指針變量根據(jù)內(nèi)存單元的編號或地址就可以找到所需的內(nèi)存單元,通常把這個地址稱為指針。在C語言中,專門存放變量〔或其它程序?qū)嶓w〕地址的變量是指針變量。指針變量也需要存儲單元〔存放地址值的整數(shù)〕,它本身也有地址。例如讓變量p存放整型變量a的地址〔如下圖〕,這樣,由變量p的值〔地址,圖中為1012〕就可以找到變量a,因此稱變量p指向變量a,變量p就是指針變量,它存放的地址就稱為“指針〞。因此,指針就是地址。6.1指針的根本概念6.1.1指針的概念4.直接訪問方式與間接訪問方式有了指針變量以后,對一般變量的訪問即可以通過變量名進行,也可以通過指針變量進行。通過變量名或其地址〔如a或&a〕訪問變量的方式叫直接訪問方式;通過指針變量〔如p〕訪問它指向的變量〔如a〕的方式叫間接訪問方式。6.2指針變量的定義與引用6.2.1指針變量的定義與初始化指針變量的一般定義形式為:類型名*標(biāo)識符;其中“標(biāo)識符〞是指針變量名,標(biāo)識符前加“*〞號表示該變量是指針變量,用于存放地址,“類型名〞表示該指針變量所指向變量的類型。6.2指針變量的定義與引用6.2.2指針變量的賦值1.通過地址運算“&〞賦值地址運算符“&〞是單目運算符,運算對象放在地址運算符“&〞的右邊,用于求出運算對象的地址。通過地址運算“&〞可把一個變量的地址賦給指針變量。2.指針變量的初始化與動態(tài)變量的初值一樣,在定義了一個〔動態(tài)的〕指針變量之后,其初值也是一個不確定的值??梢栽诙x變量時給指針變量賦初值,如floatf,*p=&f;那么把變量f的地址賦值給指針變量p,此語句相當(dāng)于floatf,*p;p=&f;這兩條語句。6.2指針變量的定義與引用6.2.2指針變量的賦值3.通過其它指針變量賦值可以通過賦值運算符,把一個指針變量的地址值賦給另一個指針變量,這樣兩個指針變量均指向同一地址。4.用NULL給指針變量賦空值

除了給指針變量賦地址值外,還可以給指針變量賦空值,如

p=NULL;6.2指針變量的定義與引用6.2.3指針的運算及引用1.指針變量的賦值運算在函數(shù)的執(zhí)行局部給指針變量賦地址值有以下幾種情況。(1)賦給同類型普通變量求地址運算得到的地址值。如:intk=10,*p,*q;q=&k;這時scanf〔"%d",&k〕;與scanf〔"%d",q〕;作用相同。(2)通過已有地址值的指針變量賦值。(3)通過標(biāo)準(zhǔn)函數(shù)獲得地址值。(4)給指針變量賦“空〞值,如:p=NULL;這樣做的目的是:讓指針變量存有確定的地址值又不指向任何變量〔類似于給數(shù)值型變量賦初值0〕。6.2指針變量的定義與引用6.2.3指針的運算及引用2.指向運算和指針變量的引用(1)指向運算符**運算符作用在指針〔地址〕上,代表該指針?biāo)赶虻拇鎯卧布捌渲怠?,實現(xiàn)間接訪問,因此又叫“間接訪問運算符〞。如:inta=5,*p;p=&a;printf〔"%d",*p〕;*p的值為5與a等價。*運算符為單目運算符,與其他的單目運算符具有相同的優(yōu)先級和結(jié)合性〔右結(jié)合性〕。根據(jù)*運算符的作用,*運算符和取地址運算符&互逆:*〔&a〕==a&〔*p〕==p注意,在定義指針變量時,“*〞表示其后是指針變量;在執(zhí)行局部的表達(dá)式中,“*〞是指向運算符。(2)指針變量的引用知道了指針變量的作用以及相關(guān)的運算符以后,我們就可以引用指針變量了。6.2指針變量的定義與引用6.2.3指針的運算及引用【例6-1】請理解以下程序中各語句的含義:#include<stdio.h>voidmain(){inta=10,*p=&a;printf("*p=%d\n",*p);/*打印指針變量p所指向的變量a的值10*/printf("Entera:");scanf("%d",p);/*對指針變量p所指向的變量a的地址讀入整數(shù)*/printf("a=%d\n",a);printf("p=%x\n",p);/*輸出指針變量p存儲的變量a的地址*/printf("&p=%x\n",&p);/*輸出指針變量p自身的地址*/*p=5;/*把5賦給p所指向的存儲單元,相當(dāng)于a=5;*/printf("a=%d\n",a);(*p)++;/*使指針變量p所指向的存儲單元的值自增,相當(dāng)于a++;*/printf("a=%d\n",a);}程序運行結(jié)果:*p=10Entera:15a=15p=13ff7c&p=13ff78a=5a=66.2指針變量的定義與引用6.2.3指針的運算及引用【例6-2】輸入兩個整數(shù)i1和i2,利用指針將大數(shù)存放到i1中,小數(shù)存放到i2中,最后按i1、i2的順序輸出。按題意,定義兩個指針變量p1、p2,將i1、i2的地址分別存入p1、p2,當(dāng)i1<i2時利用指針變量p1、p2交換i1、i2的值然后輸出。程序如下:6.2指針變量的定義與引用6.2.3指針的運算及引用#include<stdio.h>voidmain(){inti1,i2,*p1,*p2,t;p1=&i1;p2=&i2;printf("Entertwonumbers:\n");scanf("%d%d",p1,p2);/*利用指針變量輸入i1、i2的值*/if(i1<i2){t=*p1;*p1=*p2;*p2=t;}/*利用指針變量的指向操作交換i1、i2的值*/printf("i1=%d,i2=%d\n",i1,i2);}Entertwonumbers:510程序運行結(jié)果:i1=10,i2=56.2指針變量的定義與引用6.2.3指針的運算及引用【思考】如果將變量定義改為inti1,i2,*p1,*p2,*p;交換i1、i2值的語句改為:if(i1<i2){p=p1;p1=p2;p2=p;}或者if(i1<i2){*p=*p1;*p1=*p2;*p2=*p;}將會怎樣?【分析】第一種情況是:在i1<i2的情況下,利用臨時指針變量p交換指針變量p1、p2存放的地址值,而i1、i2的值沒有改變,因此題目的要求沒有實現(xiàn)〔如圖6-5所示〕。但如果同時將輸出語句改為:printf("max=%d,min=%d\n",*p1,*p2);可實現(xiàn)從大到小輸出。第二種情況是:在i1<i2的情況下,利用三個指針變量的指向操作交換i1、i2的值。問題是:指針變量p沒有存放普通變量的地址,因此也是錯誤的〔運行時有警告〕。6.2指針變量的定義與引用6.2.3指針的運算及引用【思考】如果將變量定義改為inti1,i2,*p1,*p2,*p;交換i1、i2值的語句改為:if(i1<i2){p=p1;p1=p2;p2=p;}或者if(i1<i2){*p=*p1;*p1=*p2;*p2=*p;}將會怎樣?【分析】第一種情況是:在i1<i2的情況下,利用臨時指針變量p交換指針變量p1、p2存放的地址值,而i1、i2的值沒有改變,因此題目的要求沒有實現(xiàn)〔如圖6-5所示〕。但如果同時將輸出語句改為:printf("max=%d,min=%d\n",*p1,*p2);可實現(xiàn)從大到小輸出。第二種情況是:在i1<i2的情況下,利用三個指針變量的指向操作交換i1、i2的值。問題是:指針變量p沒有存放普通變量的地址,因此也是錯誤的〔運行時有警告〕。6.2指針變量的定義與引用6.2.4指針作為函數(shù)參數(shù)函數(shù)的參數(shù)可以是我們在前面學(xué)過的簡單數(shù)據(jù)類型,也可以是指針類型。使用指針類型做函數(shù)的參數(shù),實際向函數(shù)傳遞的是變量的地址。由于函數(shù)中獲得了所傳遞變量的地址,在該地址空間的數(shù)據(jù)當(dāng)函數(shù)調(diào)用結(jié)束后被物理地保存下來。6.2指針變量的定義與引用6.2.4指針作為函數(shù)參數(shù)【例6-3】利用指針變量作為函數(shù)的參數(shù),用函數(shù)的方法再次實現(xiàn)上述功能。#include<stdio.h>voidmain(){voidchang(); /*函數(shù)聲明*/int *p1,*p2,a,b,*t;scanf("%d,%d",&a,&b);p1=&a;p2=&b;chang(p1,p2); /*調(diào)用函數(shù)*/printf("%d,%d\n",*p1,*p2);return0;}6.2指針變量的定義與引用6.2.4指針作為函數(shù)參數(shù)voidchang(int*pt1,int*pt2) /*函數(shù)實現(xiàn)將兩數(shù)值調(diào)整為由大到小*/{intt;if(*pt1<*pt2) {t=*pt1;*pt1=*pt2;*pt2=t;}/*交換內(nèi)存變量的值*/return;}由于在調(diào)用函數(shù)時,實際參數(shù)是指針變量,形式參數(shù)也是指針變量,實參與形參相結(jié)合,傳值調(diào)用將指針變量傳遞給形式參數(shù)pt1和pt2。但此時傳值傳遞的是變量地址,使得在函數(shù)中pt1和pt2具有了p1和p2的值,指向了與調(diào)用程序相同的內(nèi)存變量,并對其在內(nèi)存存放的數(shù)據(jù)進行了交換,其效果與例6-2相同。6.2指針變量的定義與引用6.2.5多級指針的概念按照上述二級指針的思路,顯然可以推廣到三級指針、四級指針……。使用多級指針變量的要點是:①多級指針變量均用基類型定義,定義幾級指針變量要將變量名前放幾個“*〞號;②各指針變量均應(yīng)取得低一級指針變量的地址后才能引用;③引用幾級指針變量訪問最終的普通變量時,變量名前需用幾個指向運算符“*〞號。6.2指針變量的定義與引用6.2.5多級指針的概念【例6-4】運行下面的程序#include<stdio.h>voidmain(){int*p1,**p2,***p3,****p4,x=10;p1=&x;p2=&p1;p3=&p2;p4=&p3;printf〔"x=%d\n",****p4〕;}程序運行結(jié)果:x=106.3指針與數(shù)組6.3.1指針與一維數(shù)組一個數(shù)組的元素在內(nèi)存中是連續(xù)存放的,數(shù)組第一個元素的地址稱數(shù)組的首地址。在C語言中,數(shù)組名是該數(shù)組的首地址。例如有以下定義語句:inta[10],*p;那么語句p=a;和p=&a[0];是等價的,都表示指針變量p指向a數(shù)組的首地址。數(shù)組首地址的值在C語言中是一個地址常量,是不能改變的。因此,語句a=p;或a++;都是非法的。6.3指針與數(shù)組6.3.1指針與一維數(shù)組1.通過一維數(shù)組名所代表的地址存取數(shù)組元素.

假設(shè)已定義一維數(shù)組a,由上述可知a+i是元素a[i]的地址,根據(jù)指針運算符“*〞的運算規(guī)那么知*(a+i)與元素a[i]等價。例如,下述程序段:inta[]={1,2,3,4,5,6,7,8,9,10};*(a+5)=50;/*相當(dāng)于a[5]=50;*/scanf("%d",&a[8]);/*相當(dāng)于scanf("%d",a+8);*/printf("%d\n",*(a+5));/*相當(dāng)于printf("%d\n",a[5]))*/6.3指針與數(shù)組6.3.1指針與一維數(shù)組2.通過指針運算符“*〞存取數(shù)組元素設(shè)有如下程序段:inta[10],*p;p=a;即p指向a數(shù)組的首地址,由上述可知p+i是元素a[i]的地址,根據(jù)指針運算符“*〞的運算規(guī)那么知*(p+i)與元素a[i]等價。例如,下述程序段:inta[]={1,2,3,4,5,6,7,8,9,10},*p=a;*(p+5)=50;/*相當(dāng)于a[5]=50;*/scanf("%d",&a[8]);/*相當(dāng)于scanf("%d",p+8);*/printf("%d\n",*(p+5));/*相當(dāng)于printf("%d\n",a[5]))*/6.3指針與數(shù)組6.3.1指針與一維數(shù)組3.通過帶下標(biāo)的指針變量存取數(shù)組元素C語言中的下標(biāo)運算符“[]〞可以構(gòu)成表達(dá)式,假設(shè)p為指針變量,i為整型表達(dá)式,那么可以把p[i]看成是表達(dá)式,首先按p+i計算地址,然后再存取此地址單元中的值。因此p[i]與*(p+i)等價。例如,下述程序段:inta[]={1,2,3,4,5,6,7,8,9,10},*p=a;p[5]=50;/*相當(dāng)于a[5]=50;*/scanf("%d",&a[8]);/*相當(dāng)于scanf("%d",&p[8]);*/printf("%d\n",p[5]);/*相當(dāng)于printf("%d\n",a[5]))*/6.3指針與數(shù)組6.3.2指針與二維數(shù)組1.二維數(shù)組的地址表示法C語言規(guī)定,二維數(shù)組由一維數(shù)組擴展形成,即一維數(shù)組的每一個元素作為數(shù)組名形成一行數(shù)組,各行數(shù)組的元素個數(shù)相同,是二維數(shù)組的列數(shù)。例如定義了二維數(shù)組inta[3][4],它是由一維數(shù)組inta[3]擴展形成,即以a[0]、a[1]、a[2]為數(shù)組名〔首地址〕形成三行一維數(shù)組,元素個數(shù)均為列數(shù)4。因此a[0]、a[1]、a[2]為一級指針常量,指向各行的首列〔列指針〕。例如0行的a[0]=&a[0][0]指向0行0列。0行有四個元素,它們是a[0][0]、a[0][1]、a[0][2]、a[0][3]。另外a[0]、a[1]、a[2]又是數(shù)組名為a的一維數(shù)組的三個元素,首地址a=&a[0]指向的“元素〞為一級指針常量,因此a為二級指針常量,指向0行〔行指針〕。6.3指針與數(shù)組6.3.2指針與二維數(shù)組【例6-5】輸出二維數(shù)組的有關(guān)值,程序編寫如下,注意理解各語句的含義。#include<stdio.h>voidmain(){inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};printf("%u,%u\n",a,*a);/*0行首地址和0行0列首地址*/printf("%u,%u\n",a+1,*a+1);/*1行首地址和0行1列首地址*/printf("%u,%u\n",a,&a[0]);/*0行首地址*/printf("%u,%u,%u\n",*(a+1),a[1],&a[1][0]);/*1行0列首地址*/printf("%d,%d,%d\n",*(*(a+1)+2),*(a[1]+2),a[1][2]);/*1行2列的元素7*/}程序運行結(jié)果:1310544,13105441310560,13105481310544,13105441310560,1310560,13105607,7,76.3指針與數(shù)組6.3.2指針與二維數(shù)組2.用于二維數(shù)組的指針變量(1)指向數(shù)組元素的指針變量〔一級指針變量〕:將二維數(shù)組當(dāng)成一維數(shù)組訪問。6.3指針與數(shù)組6.3.2指針與二維數(shù)組【例6-6】用一級指針變量輸出二維數(shù)組的全部元素。#include<stdio.h>voidmain(){inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12},i,j,*p;p=a[0];/*指針變量必須得到首元素地址a[0]或*a或&a[0][0]*/for(i=0;i<3;i++)for(j=0;j<4;j++)printf("%3d",*(p+4*i+j));printf("\n");}程序運行結(jié)果:

1234567891011126.3指針與數(shù)組6.3.2指針與二維數(shù)組(2)指向一維數(shù)組的指針變量〔行指針變量〕二維數(shù)組名〔設(shè)為a〕以及a+1、a+2等均為行指針〔二級指針〕常量,分別指向由一行元素組成的行一維數(shù)組,但它們不能移動〔例如不能由a++使a得到地址a+1〕。但是如果有定義:inta[3][4],(*prt)[4];prt=a;考慮其中的(*prt)[4],因為()和[]的優(yōu)先級相同,*prt表示prt應(yīng)為指針變量,它指向一個含有4個元素的整型一維數(shù)組,而不是指向一個元素,因此它是二級指針變量〔行指針變量〕,可以移動。指向一維數(shù)組的指針變量的一般定義形式為:類型(*指針變量名)[一維數(shù)組元素個數(shù)];6.3指針與數(shù)組6.3.2指針與二維數(shù)組【例6-7】輸出二維數(shù)組任意行任意列的元素值。定義指向一維數(shù)組的指針變量,按照上面的說明表示二維數(shù)組任意行任意列的元素,程序如下:#include<stdio.h>voidmain(){inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};int(*p)[4]=a,row,col;printf("Enterarbitrarynumberofrowandcolumn:\n");scanf("%d,%d",&row,&col);printf("a[%d][%d]=%d\n",row,col,*(*(p+row)+col));}程序運行結(jié)果:a[2][3]=12Enterarbitrarynumberofrowandcolumn:2,36.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)【例6-8】調(diào)用函數(shù),實現(xiàn)求解一維數(shù)組中的最大元素。我們首先假設(shè)一維數(shù)組中下標(biāo)為0的元素是最大和用指針變量指向該元素。后續(xù)元素與該元素一一比較,假設(shè)找到更大的元素,就替換。sub_max()函數(shù)的形式參數(shù)為一維數(shù)組,實際參數(shù)是指向一維數(shù)組的指針。6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)#include<stdio.h>voidmain(){int sub_max(); /*函數(shù)聲明*/int n,a[10],*ptr=a; /*定義變量,并使指針指向數(shù)組*/int max;for(n=0;n<=9;n++) /*輸入數(shù)據(jù)*/scanf("%d",&a[n]);max=sub_max(ptr,10); /*函數(shù)調(diào)用,其實參是指針*/printf("max=%d\n",max);}intsub_max(b,i)/*函數(shù)定義,其形參為數(shù)組*/int b[],i; {int temp,j;temp=b[0];for(j=1;j<=9;j++)if(temp<b[j]) temp=b[j];returntemp;}6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)程序的main()函數(shù)局部,定義數(shù)組a共有10個元素,由于將其首地址傳給了ptr,那么指針變量ptr就指向了數(shù)組,調(diào)用sub_max()函數(shù),再將此地址傳遞給sub_max()函數(shù)的形式參數(shù)b,這樣一來,b數(shù)組在內(nèi)存與a數(shù)組具有相同地址,即在內(nèi)存完全重合。在sub_max()函數(shù)中對數(shù)組b的操作,與操作數(shù)組a意義相同。main()函數(shù)完成數(shù)據(jù)的輸入,調(diào)用sub_max()函數(shù)并輸出運行結(jié)果。sub_max()函數(shù)完成對數(shù)組元素找最大的過程。在sub_max()函數(shù)內(nèi)數(shù)組元素的表示采用下標(biāo)法。6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)#include<stdio.h>voidmain(){intsub_max();intn,a[10],*ptr=a;intmax;for(n=0;n<=9;n++)scanf("%d",&a[n]);max=sub_max(ptr,10);printf("max=%d\n",max);}intsub_max(b,i) /*形式參數(shù)為指針變量*/int *b,i;{inttemp,j;temp=b[0]; /*數(shù)組元素指針的下標(biāo)法表示*/for(j=1;j<=i-1;j++)if(temp<b[j]) temp=b[j];returntemp;}6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)在sub_max()中,形式參數(shù)是指針,調(diào)用程序的實際參數(shù)ptr為指向一維數(shù)組a的指針,虛實結(jié)合,sub_max()的形式參數(shù)b得到ptr的值,指向了內(nèi)存的一維數(shù)組。數(shù)組元素采用下標(biāo)法表示,即一維數(shù)組的頭指針為b,數(shù)組元素可以用b[j]表示。程序輸入數(shù)據(jù):13568912562378程序運行結(jié)果:max=896.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)上述程序的函數(shù)中,數(shù)組元素還可以用指針表示intsub_max(b,i) /*函數(shù)定義*/int *b,i;{int temp,j;temp=*b++;for(j=1;j<=i-1;j++)if(temp<*b) temp=*b++;returntemp;}6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)【例6-8】用指向數(shù)組的指針變量實現(xiàn)一維數(shù)組的由小到大的冒泡排序。編寫三個函數(shù)用于輸入數(shù)據(jù)、數(shù)據(jù)排序、數(shù)據(jù)輸出。6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)#include<stdio.h>#defineN 10voidmain(){voidinput(); /*函數(shù)聲明*/voidsort();voidoutput();int a[N],*p; /*定義一維數(shù)組和指針變量*/input(a,N); /*數(shù)據(jù)輸入函數(shù)調(diào)用,實參a是數(shù)組名*/p=a; /*指針變量指向數(shù)組的首地址*/sort(p,N); /*排序,實參p是指針變量*/output(p,N); /*輸出,實參p是指針變量*/ }6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)voidinput(arr,n) /*無需返回值的輸入數(shù)據(jù)函數(shù)定義,形參arr是數(shù)組*/intarr[],n;{int i;printf("inputdata:\n");for(i=0;i<n;i++) /*采用傳統(tǒng)的下標(biāo)法*/scanf("%d",&arr[i]);}voidsort(ptr,n) /*冒泡排序,形參ptr是指針變量*/int*ptr,n;{int i,j,t;for(i=0;i<n-1;i++)for(j=0;j<n-1-i;j++)if(*(ptr+j)>*(ptr+j+1)) /*相臨兩個元素進行比較*/{t=*(ptr+j); *(ptr+j)=*(ptr+j+1);*(ptr+j+1)=t;}/*兩個元素進行交換*/ }6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)voidoutput(arr,n) /*數(shù)據(jù)輸出*/intarr[],n;{int i,*ptr=arr; /*利用指針指向數(shù)組的首地址*/printf("outputdata:\n");for(;ptr-arr<n;ptr++) /*輸出數(shù)組的n個元素*/printf("%4d",*ptr);printf("\n");}6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)【例6-10】用指向二維數(shù)組的指針作函數(shù)的參數(shù),實現(xiàn)對二維數(shù)組的按行相加。#include<stdio.h>#define M 3#define N 4voidmain(){float a[M][N];float score1,score2,score3,*pa=a[0]; /*指針變量pa指向二維數(shù)組*//*score1,score2,score3分別記錄三行的數(shù)據(jù)相加*/int i,j;voidfun();for(i=0;i<M;i++) /*二維數(shù)組的數(shù)據(jù)輸入*/for(j=0;j<N;j++) scanf("%f",&a[i][j]);fun(pa,&score1,&score2,&score3);/*函數(shù)調(diào)用,不僅傳遞數(shù)組首地址,也傳遞變量的地址*/

6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)printf("%.2f,%.2f,%.2f\n",score1,score2,score3);}voidfun(b,p1,p2,p3)floatb[][N],*p1,*p2,*p3;{inti,j;*p1=*p2=*p3=0;for(i=0;i<M;i++)for(j=0;j<N;j++){if(i==0) *p1=*p1+b[i][j]; /*第0行的數(shù)據(jù)相加*/if(i==1)*p2=*p2+b[i][j]; /*第1行的數(shù)據(jù)相加*/if(i==2) *p3=*p3+b[i][j]; /*第2行的數(shù)據(jù)相加*/}}6.3指針與數(shù)組6.3.3數(shù)組指針作函數(shù)的參數(shù)程序中與形式參數(shù)p1、p2和p3相對應(yīng)的是實際參數(shù)&score1、&score2和&score3,其實際含義為p1=&score1等,即將變量的地址傳遞給指針變量到達(dá)按行相加。程序輸入數(shù)據(jù):13593456788976654321程序運行結(jié)果:18.00,257.00,205.00本次課學(xué)習(xí)小結(jié)1.指針的根本概念2.指針變量的定義與引用3.指針與數(shù)組1.地址與指針變量的概念,地址運算符與間址運算符。

2.一維。二維數(shù)組和字符串的地址以及指向變量、數(shù)組、字符串、函數(shù)、結(jié)構(gòu)體的指針變量的定義。通過指針引用以上各類型數(shù)據(jù)。

3.用指針作函數(shù)參數(shù)。

4.返回地址值的函數(shù)。

5.指針數(shù)組,指向指針的指針。本次課等級考試考點練習(xí):等級考試真題一、選擇題:〔2007年9月份考題〕〔33〕假設(shè)有定義語句:inta[2][3],*p[3];,那么以下語句中正確的選項是

A〕p=a;B)p[0]=a;C)p[0]=&a[1][2];D)p[1]=&a;

答案:C練習(xí):等級考試真題二、填空題:〔2007年4月份考題〕(15)以下程序的功能是:利用指針指向三個整型變量,并通過指針運算找出三個數(shù)中的最大值,輸出到屏幕上,請?zhí)羁眨?/p>

Main()

{intx,y,z,max,*px,*py,*pz,*pmax;

Scanf(“%d%d%d〞,&x,&y,&z);

Px=&x;

Py=&y;

Pz=&z;

Pmax=&max;

__________________

If(*pmax<*py)*pmax=*py;

If(*pmax<*pz)*pmax=*pz;

Printf(“max=%d\n〞,max);

}

*pmax=*px三、填空題:〔2007年9月份考題填空題〕

練習(xí):等級考試真題(11)以下程序的輸出結(jié)果是________.

#include

#include

char*fun(char*t)

{char*p=t;

return(p+strlen(t)/2);

}

main()

{char*str="abcdefgh";

str=fun(str);

puts(str);

}

efgh練習(xí):本次課作業(yè):習(xí)題集:第六章選擇題:1、2、3、4填空題:1、2、3、4、5改錯題:1、2編程題:1、2第6章指針

6.4

指向字符串的指針變量

6.5指針數(shù)組

6.6指針數(shù)組作main函數(shù)的形參

6.7指向指針的指針變量第十二次課2學(xué)時學(xué)習(xí)目的1.了解字符串的表示形式2.掌握字符串作函數(shù)參數(shù)和字符指針變量與字符數(shù)組的區(qū)別3.了解指針數(shù)組的一般定義形式4.掌握指針數(shù)組的應(yīng)用5.了解帶參數(shù)的main函數(shù)的一般形式6.掌握命令行參數(shù)的應(yīng)用7.了解指向指針的指針變量的一般定義形式8.掌握指向指針的指針變量的應(yīng)用

學(xué)習(xí)重點1.指向字符串的指針變量的定義、賦值和使用2.指針數(shù)組3.指向指針的指針變量學(xué)習(xí)難點1.字符串的指針作函數(shù)參數(shù)2.指針數(shù)組作函數(shù)參數(shù)

56指針字符串的表示形式

字符串作函數(shù)參數(shù)

字符指針變量與字符數(shù)組的區(qū)別

指針數(shù)組的一般定義形式

命令行參數(shù)的應(yīng)用指向指針的指針變量的一般定義形式指針指針數(shù)組的應(yīng)用

帶參數(shù)的main函數(shù)的一般形式指向指針的指針變量的應(yīng)用

6.4

指向字符串的指針變量6.4.1字符串的表示形式字符串是特殊的常量,它一般被存儲在一維的字符數(shù)組中并且以‘\0’結(jié)束。字符串與指針也有著密切的關(guān)系。在C語言程序中,可以采用兩種方法來實現(xiàn)訪問一個字符串:其中一種方法是采用字符數(shù)組,另一種方法是采用字符指針。在字符串的處理中,使用字符指針比使用字符數(shù)組更方便。

程序運行輸出結(jié)果:BeijingOlympicsBeijingOlympics〔1〕定義一個字符數(shù)組,并且將一個字符串存放在字符數(shù)組中,以空字符‘\0’結(jié)束。【例6-11】定義一個字符數(shù)組,然后通過下標(biāo)和數(shù)組名引用字符或字符串。#include<stdio.h>voidmain(){charstring[]="BeijingOlympics";/*定義字符數(shù)組并且初始化*/inti;for(i=0;string[i]!='\0';i++)/*逐個選取字符數(shù)組中的所有數(shù)組元素*/printf("%c",string[i]);/*通過下標(biāo)每次輸出一個字符*/printf("\n");printf(“%s\n〞,string);/*從數(shù)組名string指向的元素開始,輸出}字符串到‘\0’為止*/在【例6-11】中string是存放給定字符串的數(shù)組名,它代表字符數(shù)組第0號數(shù)組元素的地址。在C語言中規(guī)定,數(shù)組名代表數(shù)組的首地址,也就是數(shù)組中第0號數(shù)組元素的地址〔即指向該數(shù)組第0號數(shù)組元素的指針〕。所以將字符串存儲在一個數(shù)組中以后,就可以通過該數(shù)組名對它進行存取。由于string+i是一個地址,那么*(string+i)表示其內(nèi)容,它與代表數(shù)組元素的string[i]等價。程序運行輸出結(jié)果:BeijingOlympics〔2〕定義一個字符指針變量,并且將字符指針指向一個字符串常量。【例6-12】定義一個字符指針,然后通過它引用字符串。#include<stdio.h>voidmain(){char*string=“BeijingOlympics〞;/*定義字符指針變量并且指向一個字符串*/printf("%s\n",string);/*輸出字符串*/}注意,在對字符指針變量string賦初值為字符串常量時,并不是把整個字符串的內(nèi)容都賦給該字符指針變量,而僅僅是把該字符串在內(nèi)存單元的首地址〔即第一個字符的地址〕賦給該字符指針變量,這樣就可以將字符指針指向字符串的第一個字符。在C語言中,對字符串常量的存放是按靜態(tài)字符數(shù)組處理的。就是說,在內(nèi)存中分配給字符數(shù)組一片連續(xù)的存儲單元用來存放該字符串常量。一般情況下,每一個字符占用一個字節(jié)的存儲單元。在內(nèi)存中,由于字符串的最后被自動填加了一個‘\0’,所以使用字符指針變量來處理字符串的時候就很容易判斷字符串的終止位置。對于使用字符指針變量處理字符串的情況,在輸出字符串時要使用“%s〞格式符,輸出項中要給出字符指針變量名,這樣,計算機就先輸出字符指針變量所指向字符串的第一個字符,然后字符指針變量自動加1而指向字符串的下一個字符,接著再輸出該字符,…,重復(fù)上述操作直到遇到字符串結(jié)束標(biāo)志‘\0’為止。所以,雖然一個數(shù)值型數(shù)組不能使用數(shù)組名來輸出該數(shù)組的全部元素,而只能逐個元素進行輸出;但是使用字符數(shù)組名或者字符指針變量卻可以整體輸出一個字符串。為便于理解,程序可以如下編寫:#include<stdio.h>voidmain(){charstring[]="BeijingOlympics";/*定義字符數(shù)組并且初始化*/char*p=string;/*定義字符指針變量p并且賦值為字符串首地址string*/printf("%s\n",p);}/*輸出字符串*/程序運行輸出結(jié)果:string1is:Iamatearcher.

string2is:Iamatearcher.【例6-13】使用字符數(shù)組名的方法計算數(shù)組元素地址,完成字符串的復(fù)制。#include<stdio.h>voidmain(){charstring1[]="Iamatearcher.",string2[20];/*定義字符數(shù)組并且初始化*/inti;for(i=0;*(string1+i)!='\0';i++)*(string2+i)=*(string1+i);/*將string1數(shù)組中的字符串復(fù)制到string2數(shù)組*/*(string2+i)='\0';printf("string1is:%s\n",string1);printf("string2is:");for(i=0;string2[i]!='\0';i++)printf("%c",string2[i]);/*輸出字符串*/}

在【例6-13】for循環(huán)中,首先判斷string1[i]〔此處以(string1+i)的地址形式表示〕是否為‘\0’。假設(shè)不為‘\0’,那么將string1[i]的值賦給string2[i]〔此處以*(string2+i)的地址形式表示〕,完成一個字符的復(fù)制?!貜?fù)上述操作,將string1數(shù)組中字符串全部都復(fù)制給string2數(shù)組直到string1[i]〔以*(string1+i)的地址形式表示〕遇到‘\0’為止。最后要將‘\0’復(fù)制給string2數(shù)組。程序運行輸出結(jié)果:string1is:Iamatearcher.

string2is:Iamatearcher.【例6-14】使用字符指針變量的方法,完成字符串的復(fù)制。#include<stdio.h>voidmain(){charstring1[]="Iamateacher.",string2[20];/*定義字符數(shù)組并且初始化*/char*p1,*p2;/*定義字符指針變量*/inti;p1=string1;/*p1指向字符數(shù)組ch1的首地址*/p2=string2;for(;*p1!='\0';p1++,p2++)*p2=*p1;/*將p1指向的字符串復(fù)制到p2指向的字符串*/*p2='\0';printf("string1is:%s\n",string1);printf("string2is:");for(i=0;string2[i]!='\0';i++)printf("%c",string2[i]);/*輸出字符串*/}

在【例6-14】中,首先定義p1和p2是指向字符型數(shù)據(jù)的指針變量。然后使字符指針變量p1和p2分別指向字符數(shù)組string1和string2的首地址。在for循環(huán)中,首先判斷*p1是否為‘\0’。假設(shè)不為‘\0’,那么進行*p2=*p1,它的功能是將數(shù)組string1中字符串的第一個字符賦給數(shù)組string2中的第一個數(shù)組元素。然后再利用p1++和p2++使p1和p2都加1而分別指向各自的下一個數(shù)組元素,這樣就保證p1和p2同步移動,…,重復(fù)上述操作,將string1數(shù)組中字符串全部都復(fù)制給string2數(shù)組,直到*p1的值遇到‘\0’為止。最后,需要將‘\0’復(fù)制給*p2。使用地址傳遞的方法〔即用字符數(shù)組名作函數(shù)參數(shù)或者用指向字符串的指針變量作函數(shù)參數(shù)〕可以將一個字符串從一個函數(shù)傳遞到另一個函數(shù)?!纠?-15】實參、形參都用字符數(shù)組名作函數(shù)參數(shù),完成字符串的連接。#include<stdio.h>voidmain(){voidstring_catenate(charfrom[],charto[]);/*字符串連接函數(shù)的原型聲明*/charstring1[]="computer";/*定義字符數(shù)組并且初始化*/charstring2[]="language";printf("string1=%s\nstring2=%s\n",string1,string2);printf("catenatstring2tostring1:\n");string_catenate(string1,string2);/*調(diào)用函數(shù),實參為字符數(shù)組*/printf("\nstring1is:%s\n",string1);}

6.4.2字符串作函數(shù)參數(shù)程序運行輸出結(jié)果:string1is:computerlanguagevoidstring_catenate(charfrom[],charto[])/*字符串連接函數(shù),形參為字符數(shù)組*/{inti=0,j=0;while(from[i]!='\0')i++;/*將指針移動到字符串的尾部*/while(to[j]!='\0'){from[i]=to[j];i++,j++;}/*將to數(shù)組中字符串連接到from數(shù)組中字符串的尾部*/from[i]='\0';}

【例6-16】實參、形參都用字符指針變量作函數(shù)參數(shù),完成字符串的連接。

#include<stdio.h>voidmain(){voidstring_catenate(char*from,char*to);/*字符串連接函數(shù)的原型聲明*/char*string1="computer";/*定義字符指針變量并且指向一個字符串*/char*string2="language";printf("string1=%s\nstring2=%s\n",string1,string2);printf("catenatstring2tostring1:\n");string_catenate(string1,string2);/*調(diào)用函數(shù),實參為字符指針變量*/printf("\nstring1is:%s\n",string1);}程序運行輸出結(jié)果:string1is:computerlanguage

voidstring_catenate(char*from,char*to)/*字符串連接函數(shù),形參為字符指針變量*/{for(;*from!='\0';from++);/*空循環(huán)體,將指針移動到字符串的尾部*/for(;*to!='\0';from++,to++)*from=*to;/*將to指向的字符串連接到from指向的字符串的尾部*/*from='\0';}

數(shù)組名、字符指針變量既可以作函數(shù)的實參,也可以作函數(shù)的形參,歸納起來有如下幾種情況。表6-2字符數(shù)組名、字符指針變量作函數(shù)參數(shù)的4種組合實參形參數(shù)組名數(shù)組名數(shù)組名字符指針變量字符指針變量數(shù)組名字符指針變量字符指針變量6.4.3字符指針變量與字符數(shù)組的區(qū)別

使用字符數(shù)組和字符指針變量都可以實現(xiàn)字符串的存儲和運算,兩種方式有相同之處,但也是有區(qū)別的。比較的項目字符數(shù)組字符指針變量存放的內(nèi)容由若干個數(shù)組元素組成,每個數(shù)組元素中存放一個字符存放地址(如字符串中第1個字符的地址)存儲空間字符串長度加1,一個字符占用1個字節(jié)一般使用2個字節(jié)存放比較的項目字符數(shù)組字符指針變量初始化可以初始化chara[]="Hi!";可以初始化char*p="Hi!";賦值不能用字符串整體給字符數(shù)組賦值,只能對字符數(shù)組單個元素賦值能用字符串整體對字符指針賦值(為字符串中第1個字符的地址)char*p;p="Hi!";地址值有確定地址,定義數(shù)組后在編譯時分配內(nèi)存單元定義字符指針變量時分配內(nèi)存單元,但是它沒有確定的值,沒有指向具體的字符數(shù)據(jù)比較的項目字符數(shù)組字符指針變量可變性數(shù)組名為常量,其值不可變字符指針變量為變量,其值可變,可以參加運算運算效率數(shù)組元素下標(biāo)的計算需要轉(zhuǎn)換為指針后計算,如,a[i]要轉(zhuǎn)換為*(a+i),效率較低直接使用指針計算,效率較高

6.5指針數(shù)組6.5.1指針數(shù)組的一般定義形式由假設(shè)干個指向同類型對象的指針數(shù)據(jù)可以組成一個數(shù)組,稱為指針數(shù)組。其中每個數(shù)組元素都是指針變量。就是說,指針數(shù)組的所有數(shù)組元素都必須是具有相同存儲類型和指向相同數(shù)據(jù)類型的指針變量,指針數(shù)組的每個數(shù)組元素的值均為指針。指針數(shù)組的一般定義形式為: 類型名*數(shù)組名[數(shù)組大小];例如,int*pa[10];例如,int*pa[10];因為*比[]優(yōu)先級低,所以pa先要與[10]結(jié)合成為pa[10]的數(shù)組形式,它有10個數(shù)組元素;然后再與前面的int*結(jié)合來表示數(shù)組元素的類型是指向整型變量的指針,就是說,每個數(shù)組元素都可以指向一個整型變量?;蛘哒f,pa是一個指針數(shù)組,它有10個數(shù)組元素,并且每個數(shù)組元素的值都是一個指針,都指向整型的變量。請注意,不要把定義指針數(shù)組與定義指向含有假設(shè)干數(shù)組元素的指針變量相混淆。int(*pa)[10];/*表示定義一個指向含有10個數(shù)組元素的一維數(shù)組的指針變量*/指針數(shù)組處理字符串問題〔如排序或查找〕是指針數(shù)組的重要應(yīng)用之一。例如,如果對多個字符串進行排序,一種方法是可以利用二維數(shù)組來處理。如chardim[M][N]形式,其中M代表行數(shù)〔即多個字符串的個數(shù)〕,N代表列數(shù)〔即最長的字符串的長度〕。在實際應(yīng)用中,由于各個字符串的長度通常是不相等的,它們往往都小于N,按照最長的字符串的長度來定義N就會造成該二維數(shù)組占用內(nèi)存單元的存儲空間浪費。并且采用一般的排序方法,需要逐個比較字符串以便交換字符串的物理位置〔交換是通過字符串復(fù)制函數(shù)strcpy完成的〕。屢次的位置交換要消耗大量處理時間又使程序執(zhí)行速度變慢。例如,以下圖表示利用二維數(shù)組來處理字符串的時候,按照最長的字符串的長度來定義N會造成該二維數(shù)組占用內(nèi)存單元存儲空間的浪費〔即‘\0’后面的局部存儲空間〕。PyramidsofEgypt\0StatueofZeus\0LighthouseofPharos\0TempleofArtemis\0ColossusofRhodes\0MausolusTombTemple\0GreatWallofChina\0AlexandriaPort\0另一種方法是采用指針數(shù)組,它可以解決上述問題。首先定義一些字符串,再把這些字符串的首地址存放在一個字符指針數(shù)組中〔即把字符指針數(shù)組的各個數(shù)組元素分別指向各個字符串〕。當(dāng)對字符串排序而需要交換兩個字符串時,只要交換字符指針數(shù)組中對應(yīng)兩個數(shù)組元素的值(為指向?qū)?yīng)字符串的首地址)即可,也就是通過改變指針數(shù)組中相應(yīng)數(shù)組元素的指向就可以實現(xiàn)排序目的,而不必交換具體的字符串本身,不必移動字符串的物理位置,這樣將大大減少時間的開銷,能提高運行效率,同時節(jié)省了存儲空間。

6.5.2指針數(shù)組的應(yīng)用【例6-17】將世界十大奇跡文明遺址〔埃及金字塔、宙斯神像、法洛斯燈塔、巴比倫空中花園、阿提密斯神殿、羅得斯島巨像、毛索洛斯墓廟、中國萬里長城、亞歷山卓港、秦始皇兵馬俑〕按照英文字母遞增方式排序。世界十大奇跡文明遺址〔英文〕{"PyramidsofEgypt","StatueofZeus","LighthouseofPharos","HangingGardensofBabylon","TempleofArtemis","ColossusofRhodes","MausolusTombTemple","GreatWallofChina","AlexandriaPort","QinShihuangTerracottaArmy"};#include<stdio.h>#include<string.h>voidmain(){voidbubble_sort(char*name[],intn);voidprint(char*name[],intn);char*ruins_name[]={"PyramidsofEgypt","StatueofZeus","LighthouseofPharos","HangingGardensofBabylon","TempleofArtemis","ColossusofRhodes","MausolusTombTemple","GreatWallofChina","AlexandriaPort","QinShihuangTerracottaArmy"};intm=10;bubble_sort(ruins_name,m);print(ruins_name,m);}voidbubble_sort(name,n)/*冒泡法排序*/char*name[];intn;{char*temp;inti,j;for(i=0;i<n-1;i++){for(j=0;j<n-1-i;j++)if(strcmp(name[j],name[j+1])>0) {temp=name[j];name[j]=name[j+1];name[j+1]=temp;}/*交換字符串的地址*/}}

voidprint(name,n)/*將排序后的字符串進行輸出*/char*name[];intn;{inti;for(i=0;i<n;i++)printf("%s\n",name[i]);}在程序的main主函數(shù)中,定義了字符指針數(shù)組ruins_name并作了初始化賦值,使得每個數(shù)組元素的初值分別為各個字符串的首地址。函數(shù)bubble_sort使用冒泡法來完成排序,其形參n為字符串的個數(shù),另一形參name為指針數(shù)組,接受實參傳遞過來的ruins_name指針數(shù)組的首地址〔即指向待排序各字符串的數(shù)組的指針〕,所以實參指針數(shù)組ruins_name和形參指針數(shù)組name就共占同一段內(nèi)存單元,這樣對形參指針數(shù)組name中元素排序后,就相當(dāng)于對實參指針數(shù)組ruins_name中元素進行排序。在bubble_sort函數(shù)中,對兩個字符串比較采用了strcmp函數(shù),strcmp函數(shù)允許參與比較的字符串以指針方式出現(xiàn)。函數(shù)print用于將排序后的字符串進行輸出,其形參與bubble_sort的形參相同。需要注意,在排序過程中假設(shè)發(fā)現(xiàn)位于前面的字符串大于后面的字符串,不是交換被比較的兩個字符串本身,而是要交換被比較的兩個字符串的指針。就是說,字符串的存儲位置不變,改變的是字符串指針的存儲位置,這樣就防止了使用字符串復(fù)制函數(shù)strcpy進行字符串賦值的過程,簡化了算法,減少了時間的開銷,提高了運行效率,并且也節(jié)省了存儲空間。ruins_name[0]ruins_name[1]ruins_name[2]ruins_name[3]ruins_name[4]ruins_name[5]ruins_name[6]ruins_name[7]ruins_name[8]ruins_name[9]PyramidsofEgyptStatueofZeusLighthouseofPharosHangingGardensofBabylonTempleofArtemisColossusofRhodesMausolusTombTempleGreatWallofChinaAlexandriaPortQinShihuangTerracottaArmyruins_name[0]ruins_name[1]ruins_name[2]ruins_name[3]ruins_name[4]ruins_name[5]ruins_name[6]ruins_name[7]ruins_name[8]ruins_name[9]PyramidsofEgyptStatueofZeusLighthouseofPharosHangingGardensofBabylonTempleofArtemisColossusofRhodesMausolusTombTempleGreatWallofChinaAlexandriaPortQinShihuangTerracottaArmy

ruins_name指針數(shù)組字符串

6.6指針數(shù)組作main函數(shù)的形參帶參數(shù)的main函數(shù)的一般形式指針數(shù)組作為main函數(shù)的形式參數(shù)也是指針數(shù)組的重要應(yīng)用之一。在前面的程序中,main函數(shù)都是不帶參數(shù)的,即main函數(shù)之后的一對圓括號中為空,如main〔〕的形式。而在實際應(yīng)用中,main函數(shù)是可以帶參數(shù)的,這樣的參數(shù)一般稱為命令行參數(shù)。在操作系統(tǒng)狀態(tài)下,為了執(zhí)行某個程序而鍵入的一行字符稱為命令行,它一般以回車作為結(jié)束符。命令行中必須要有程序的可執(zhí)行文件名〔即命令名〕,有時也帶有假設(shè)干參數(shù)〔即命令行參數(shù)〕。C程序是在main函數(shù)中使用參數(shù)〔形參〕來接受命令行參數(shù)〔實參〕的?!?〕帶參數(shù)的main函數(shù)的一般形式intmain(intargc,char*argv[]){函數(shù)體}其中,形參argc用來存放命令行中單詞的個數(shù),它表示傳遞給程序的參數(shù)個數(shù)〔指包括命令名在內(nèi)的所有參數(shù)〕,為整型,它的值至少是1;而形參argv是指向字符串的指針數(shù)組,它用來存放命令行中單詞的內(nèi)容,實際上存放的是命令名和各個命令行參數(shù)字符串的首地址。形參argc和argv的名字可由用戶任意命名〔一般情況下可以不用改變〕;但是它們的類型卻是固定的而不能由用戶改變。〔2〕命令行參數(shù)的一般形式可執(zhí)行文件名參數(shù)1參數(shù)2……參數(shù)n當(dāng)按照可執(zhí)行文件名〔即命令名〕執(zhí)行程序的時候,系統(tǒng)會把參數(shù)1、參數(shù)2、……、參數(shù)n依次傳遞給該文件名中main函數(shù)的形參。在C語言中,main函數(shù)可以調(diào)用其它函數(shù),其它函數(shù)不能調(diào)用main函數(shù),所以無法從程序中得到main函數(shù)的形參。實際上,在操作系統(tǒng)狀態(tài)下〔如DOS環(huán)境下〕,輸入main函數(shù)所在的文件名〔為包含該main函數(shù)并且已經(jīng)進行編譯、連接的可執(zhí)行文件〕,系統(tǒng)才能調(diào)用該文件名中的main函數(shù)。就是說,在命令提示符后面輸入一個命令行,在命令行中應(yīng)包括命令名〔即可執(zhí)行文件名〕和要傳遞給main函數(shù)的實參〔即命令行的參數(shù)〕。當(dāng)輸入一個命令行并按下回車鍵后,命令解釋程序就開始對該命令行進行如下處理:首先根據(jù)命令名來搜索命令路徑以便找到對應(yīng)的程序文件,然后將命令行參數(shù)傳遞給該程序文件,最后執(zhí)行該程序文件。由于命令名必須存在,所以表示傳遞給程序的參數(shù)個數(shù)argc的值至少是1。而argv[]是指針數(shù)組,其中的argv[0]指向命令名字符串,argv[1]到argv[argc-1]就分別指向命令名后面的各個實參字符串。請注意,在命令名和參數(shù)之間、各個參數(shù)之間要有空格,并且文件名應(yīng)該包括文件所在的盤符、路徑以及文件的擴展名。除了系統(tǒng)提供的各種命令可以通過命令行方式執(zhí)行以外,用戶編寫的C程序經(jīng)過編譯、連接成為可執(zhí)行文件后,也可以像使用命令一樣使用可執(zhí)行文件名。例如,DOS命令提示符下命令行的一般形式為:

C:\>可執(zhí)行文件名參數(shù)1參數(shù)2……參數(shù)n當(dāng)要運行一個可執(zhí)行文件時,首先在DOS命令提示符下鍵入文件名,然后再輸入實際參數(shù)就可以把這些實參傳送給main函數(shù)的形參中去。6.6.2命令行參數(shù)的應(yīng)用由于命令行中各個參數(shù)字符串的長度事先不知道并且通常不相同,所以利用指針數(shù)組作為main函數(shù)中的參數(shù)是非常合理的,可以節(jié)省內(nèi)存存儲空間?!纠?-18】觀察參數(shù)回送命令echo程序〔文件名為echo.c〕。它只是簡單地輸出命令行上的參數(shù),每個參數(shù)后面是空格,最后是換行。#include<stdio.h>intmain(intargc,char*argv[]){printf("argc=%d\n",argc);while(--argc>0)printf("%s%c",*++argv,(argc>1)?'':'\n');}程序運行輸出結(jié)果:argc=5systembrowserandshow把文件名為echo.c的程序保存后,經(jīng)過編譯、連接后生成echo.exe文件,在DOS環(huán)境下如果輸入命令行:echosystembrowserandshow↙

對于*++argv來說,argv要先與++結(jié)合進行++argv運算,使得argv指向下一個數(shù)組元素;再與前面的*結(jié)合,以便找到當(dāng)前所指向字符串的首地址,然后來輸出該字符串。第一次,在指針數(shù)組argv中,argv指向第一個數(shù)組元素argv[0],而argv[0]指向字符串echo〔即命令字符串echo的首地址〕。進行++argv后使得argv指向下一

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論