1.單項選擇題
試題中的單項選擇題中的多數試題涉及整本教材介紹的概念和知識點。為解答這類試題,要求考生要熟練地掌握和熟記大綱中指出的“識記”和“領會”的內容。考生應摘出教材中有關c語言的重要概念、定義、有關語言成分性質的敘述,對它們深入的理解和熟記,並對語言的一些基本規定能作簡單的套用。清考生注意,理解、熟記和大段地背誦的區別。由於考題表現形式的多樣性,理解是最重要的,僅對關鍵性的概念才有準確熟記的必要,多數的概念因是理解,並要求能熟練套用。試題通常要求對某個概念、術語或計算結果作出判斷,或對一些規定作簡單的套用等。由於計算機科學是一門新興學科,許多概念還沒有唯一性的定義,不同書籍由於出發點或論述領域不同,同一概念會有不同的說法,為此考生在複習迎考時,不要脫離指定自學考試教材,而從其它教材出發進行複習。
「例1」設有以下代碼定義字元數組c和字元指針變數pc:
char c[10]=“abed”,*pc=c;
問*(pc+4)的值。供選擇的答案有:
①“abcd‘ ②'\0' ③ ' d' ④不能確定
上述代碼使字元數組c的前5個元素依次為:c[0]=‘a’c[1]=‘b’, c[2]=‘c’, c[3]= ‘d',c[4]=’\0‘。初始化pc=c使字元指針變數pc指向c數組的首元素c[0].而表達式pc+4的值是c[4]的指針。因此,表達式*(pc+4)就是引用c[4].所以問題的解答為②。
「例2」指出下列說法中錯誤的敘述。
①構成數組的所有元素的數據類型必須是相同的
②用指針法引用數組元素允許數組元素的下標越界
③一維數組元素的下標為1,2,3,……
④定義數組時的長度可以是整型常量表達式
由數組的概念知,數組的全部元素有相同的數據類型,另在定義數組時,需指出數組的元素個數,指定數組元素個數的表達式必須在編譯時可計算的,即只允許是常量表達式,不可以含有變數。所以①和④是正確的敘述,不是問題要求的解答。在c語言中,當指針指向數組的某元素(不一定是數組的首元素)時,可利用該指針加減一個整表達式,構成指針表達式指向數組的某元素,然後用取內容運算符。間接引用指針表達式所指的數組元素。如有代碼:
int a[100],* p;
表達式p=&a「20]使p指向a[20],,通過p引用數組a[l],可用表達式*(p-19)。由c語言的約定,當指針指向數組某元素時,用指針表達式引用它所指的數組的某元素也可寫成等價的下標引用形式,如表達式*(p-9)可以等價地寫成p[-19].這裡-19是一個負整數,所以敘述②也是一個正確敘述。這種表示方法是借用下標表示法,與指針加減的整表達式引用數組元素,其中加減的整數實際不是數組元素的下標。還需要指出一點,指針與整表達式和的新指針不應該指向數組之外的別的地址。如前述的例子中指針變數p指向a[20],表達式*(p+n)中的 n要求不能小於 20,也不能大於 79.最後,c語言規定數組元素的下標從0開始順序編號,所以選擇③才是錯誤的敘述。
2.填充題
填充題要考核的內容與選擇題的考核內容基本相同,但考核的形式不同。填充題的試題多數是從基本概念兒語言關於數據類型、程式對象、程式結構等的規定、c程式設計基本技巧等引伸的具體套用。如c語言規定每個字元占一個位元組,每個字元串除存儲它所包含的字元外,在字元串最後一個字元之後還存有一個字元串結束符。對於這樣兩個基本概念和規定,填充題可能是問具體的一個字元和一個字元串各占多少個位元組等。因填充題是概念或規定的具體套用,解答的難度也就比選擇題的要大,不可能有猜得分的機會。
「例3」下列函式的功能是統計並返回形參指針s所指向的字元串所含字元‘a’的個數。試完成程式,寫出應填寫在程式空框中的代碼。
int counts(char *s)
{ int n;
for( n=0;。 ; s++)
if(*s==‘a’)n++;
return n;
}
為統計字元指針s所指字元串包含的某字元的出現次數,必須用一個循環順序考察整個字元串。由從指針s所指字元串的首字元開始,每考察一個字元後,指針s後移一個字元位置,考察循環直至字元率結束終止。所以填寫在空框中的正確代碼可寫成* s! =‘\ 0’。由於字元串束符‘\ 0’的代碼為 8位全0,其值為 0,正確解答也可寫成* s!= 0,或更簡潔地寫成*s.
「例4」在記憶體中存儲‘a’要占用____位元組,存儲“a”又要占用____位元組。
由於c語言規定字元只占1個位元組,一個具體的字元當然也只占1個位元組。字元串“a”要有1個位元組用於存儲字元‘a’,另需要1個位元組存儲字元串的結束符,所以它要占用連續的2個位元組。
「例5」設整型變數a、b的值均為3,執行語句:
b= a++, b++, ++a;
後,a的值為____,b的值為____.
該試題的表達式書寫形式一般不會直接出現在實際應用程式中,但作為考核考生對有關表達式的計算規則,也不失為是一個很有意義的試題。賦值表達式自右至左計算,而逗號運算符的優先權最低,並且逗號表達式自左至右逐一計算,並以最後子表達式的值為逗號表達式的結果。上述表達式的計算順序可用以下3個表達式語句等價表示:
b=a++;b++;++a;
由以上一系列表達式知,變數b的最終值與其原來值無關,表達式b= a+十是先計算a++。表達式a+十的值是變數a的原先值3,但又讓變數a增1後變為4.然後表達式b++又使變數b增1,變成4.而計算++a的值,是讓a增1,使a的值變為5.所以上述表達式使變數a的值變為5,b的值變為4.
如上述表達式改寫為:
b+=(a++,b++,++a);
請讀者回答執行該表達式後,變數a和b的值又分別為多少。
3.程式分析題
程式分析題要求考生閱讀程式,回答程式的輸出結果,或指出程式的功能。回答這類問題,要求考生將自己當作一台假想的計算機,模擬執行序。
對於這類試題常有兩種可用的方法。一是從程式的初值、循環結構、條件等發現程式的規律廠是完全從模擬執行出發讀程式,求出程式的輸出結果。如採用後一種方法,由於程式執行的動態性,程式中的有關變數,隨著程式的執行,變數的值就會不斷變化。一般來說,隨時記住全部變數的當前值是非常困難的。一個行之有效的方法是用一個變數表,將程式中的全部變數羅列在該表中,某個變數值的變化記錄在該變數當前值的欄中,這樣就能方便地列出各個變數的動態變化過程。在這裡,考生要當心函式形參及函式的局部變數與實參變數及程式的外部全局變數同名的情況。為了區別它們,對於函式形參和局部變數可以標上它所屬的函式名,以與同名的實參變數及外部全局變數相區別。由於試題程式總是完成某種有一定意義的計算工作。一般來說,程式的執行過程舍有某種規律存在。如能找出程式的規律,就不需要逐句閱讀程式的語句,能直接導出程式的結果。程式的規律從以下幾個方面著手:有關變數的初值,特別是數組的初值;程式的循環控制結構,特別是遍歷數組的循環,它的循環控制變數將控制數組元素下標的變化;循環體中的語句的條件,一般條件有兩種形式,一種是由數組元素值的大小描述,另一種是由元素的下標值描述,前者用於對其值滿足某種條件的元素進行指定的計算,後者用於對滿足條件的某些位置上的元素進行指定的計算。
最容易出題,變化也最多的是數組(包括字元串)處理程式,正確解答這類試題要熟練掌握兩點:一是引用數組元素的兩個等價方法,即用數組首元素指針(數組名)和下標引用數組元素,及通過指向數組元素的指針間接引用數組的元素;二是一些常用的簡單算法,如數組或字元串遍歷、插入元素或刪除元素,以及常用的排序方法等。對於檔案處理程式,要注意檔案當前的讀/寫位置,即對於讀檔案,注意當前讀人的數據及前讀頭位置;對於寫檔案,要注意當前寫入的數據。另外要特別指出的是,通過讀程式,能發現程式執行的規律是非常有用的技術。但這個技術的掌握是建立在熟讀大量的程式和自己編寫過大量程式的基礎上的。如一個程式是對數組的前n個元素執行某種操作。考生在閱讀這種程式時,不妨假定輸入的n值為4或5,將n等於4或5的結果類推到任意的n.
「例6」閱讀下列程式,寫出程式運行後的輸出結果。
# include <stdio.h>
main()
{int a[][3]={1,2,3,4,5,6,7,8,9};
int i,j,s1= 0,s2= 0;
for(i= 0;i<3, i++)
for(j=0;j<3;j++){
if(i==j)sl+=a[i][j];
if(i+j==2) s2+=a[i][j];
}
printf(“sl=%ds2=%d\n”, sl,sz);
}
首先將二維數組a的初值寫成每行3個元素,由於程式只提供9個初值,a只有3行:
1 2 3
4 5 6
7 8 9
程式用a[i][j]引用a的元素,所以外循環i是控制行的循環,內循環j是控制列的循環,這兩重循環控制遍歷整個數組 a的全部元素。條件 i==j表示當行下標與列下標相等時,即是 a的主對角錢上的元素時,將它們累計到變數s1,所以s1的值為15.條件i+j==2用於控制行下標與列下標之和為行列下標之和為某個常數的元素是同在某條右高左低斜線上的元素。對於3行3列的二維數組來說,就是副對角線上的元素。將這些元素累計於變數s2,所以s2的值也是15.
「例7」閱讀下列程式,簡述程式的主要功能。
main()
{ int i,s[10],*p=&s[9];
for(i=0;i<10;i++) scanf(“%d”,&s[i]);
for(;p>=s;p——) print(“%d”,*p);
printf(“\n );
}
程式中定義的變數i用於循環控制,數組s用於存儲讀人的整數,指針變數p的初值指向數組s的末元素。程式的第一個循環用於順序輸入數組s的10個元素的情。從程式的第二個循環代碼知,每循環一次,指針p減1,即指向數組的前一個元素,循環條件直至循環處理了數組的首元素後結束,循環體只是簡單地輸出指針當前所指的數組元素。所以該循環實現從數組的末元素開始逆序遍歷數組輸出。這樣程式的功能可簡述如下:
“順序輸入10個整數,並逆序輸出它們的值。”
4.程式設計題
程式設計題是給出問題,要求考生自己獨立編寫程式。考生平時認真參加上機實習,自己編寫程式,是能解答這類試題的基本條件。多數考生學了程式設計以後,能基本了解教材的內容,能解答大部分前述三種類型的試題,平時還能指出別人程式的錯誤,但由於很少自己動手,或不知道從何著手編寫程式等原因,自己還一直不會編程式。簡單程式的設計通常要包含兩個步驟:首先是構想計算方法,即用什麼方法來解決給定的計算問題;其次是將求解方法告訴計算機,命令計算機怎么做。第一步工作人們採用常人的思維習慣,而第二步工作必須採用計算機的思維習慣。對於程式設計的初學者來說,最困難的可能還是很難適應電腦程式的思維習慣,人們幾乎無法承受程式必須將要計算機完成的計算過程描述得幾乎絕對的精細和精確。但對計算機來說,這又是非常必要的。編寫程式就是在向計算機講話,非常精確地告訴計算機怎么做。
「例8」編一個程式,從名為“text.txt”的文本檔案中讀取一個字元顯示在螢幕上。
本例題要求實現最簡單的檔案處理。如考生知道檔案處理程式的編寫要點,就能方便地寫出程式。
檔案處理程式有以下幾個要點:
(l)在程式的開始處,用包含預處理命令,包含標準檔案stdio.h.定義檔案指針變數和存儲檔案名稱的字元數組。如以下代碼所示:
# include<stdio.h>
file *fp /* 定義檔案指針變數 fp*/
char fname「40」=“某檔案名稱”;
(2)如檔案名稱在程式執行時輸入,可用以下代碼:
prinif(“請輸入檔案名稱(包括檔案的目錄路徑、檔案的擴展名)\n);
scanf(“%s%*c”,fname);/*輸入檔案名稱及其隨後的回車符。/
(3)使用檔案前,必須先打開檔案,常用的有兩種打開方式:
老檔案打開為了讓程式從正文檔案輸入數據,用讀方式打開,則用以下代碼:
if((fp=fopen(fname,“r‘’))== null) {/* 為讀打開*/
printf(“%s檔案不能打開,結束程式的執行\n”,fname);
return;
}
若檔案打開為了讓程式向正文檔案輸出數據,則用以下代碼:
fp=fopen(fname,“w”);/*為寫打開*/
讀打開時,要求被打開檔案已存在。寫打開時,若被打開檔案不存在,則建立一個以fname內容命名的新檔案;若被打開檔案已存在,則該檔案上的數據被刪除。
(4)檔案使用結束後,要及時關閉,如以下代碼所示:
fclose(fp);/* 以後中又可用於打開檔案。/
(5)調用有關檔案輸入輸出庫函式。最經常使用的有:
調用函式 fgetc()從檔案輸入下一個字元,如:
ch= fgetc(fp);/*將輸入字元存於變數 ch*/
調用函式fscanf()從檔案按指定格式輸入數據,如:
fscanf(fp,“%d%d”,&k,&j);/*從檔案輸入兩個整數分別存於k和j*/除在第一位置增加一個檔案指針變數實參外,其餘與函式scanf()的用法全相同。
調用函式fputc()向檔案輸出一個字元,如:
fputc(ch,fp);/*將變數ch中的字元輸出到檔案。/
調用函式fprintf()向檔案按指定格式輸出數據,如:
fprintf(fp,“%d%d\n”,k,j);
該函式調用是按格式要求將k和j的值輸出到檔案。除在第一位置增加一個檔案指針變數實參外,其餘與函式prinif()的用法全相同。
(6)從正文檔案逐一輸入字元,作某種處理的程式結構為:
int c;/*若要用eof測試檔案結束,則不能為char類型*/
file *fp;
……/*說明有關變數和設定初值等*/
if((fp=fopen檔案名稱,“r”))==null){/*以輸入方式打開*/
printf(“不能打開檔案%s./n”,“檔案名稱字元列”);
return;
}
while((c=fgetc(fp))!= eof){
……/* 這裡對剛讀人的字元信息c作某種處理*/
}
fclose(fp);
……/* 輸出處理結果*/
(7)字元逐一生成輸出,形成新檔案程式的一般結構形式有:
int c;/*也可以是 char類型*/
對於本例題,只要包含上述(1)、(3)、(5)和(4)即可,寫成完整程式如下:
# include<stdio.h>
file*fp;/*定義檔案指針變數 fp*/
char fname[40]=“text.txt”;
main()
{char c;/*或 int c*/
if((fp= fopen(fname,“r”))== null){ /*為讀打開*/
printf(“%s檔案不能打開,結束程式的執行\n”,fname);
return;
}
c=fgetc(fp);/*將從檔案輸入的字元存於變數c*/
printf(“%c\n”, c);
fclose(fp);/*中所指檔案關閉*/
}
「例9」編寫函式f,該函式沒有浮點型數組形參float[]和整型形參n,函式的功能是計算並返回p[]中前n個元素的平均值。由於函式返回已知數組的平均值,函式的頭有以下形式:
float f( float p[], int n)
函式為了計算平均值,需要兩個計算步驟,首先是求出數組元素之和,然後將求得的和除以元素個數。嚴格地說,函式還因防止形參n小於等於0的情況,假定當n小等於0時,函式返回0值。為求數組元素和,需要一個存儲和的變數(例如說s)。求和通過遺歷數組實現,有兩種實現方法:
一是引入一個循環控制變數(例如說i),並讓 i作為弓傭數組元素的下標(如 p[i])。所以有以下代碼:
float f(float p[], int n)
{ int i; float s;
if(n<=0)return 0.0;
for( s=0.0, i=0; i<n; i++) s+= p[i];
return s/n;
}
二是由於函式的數組形參實際是一個指針變數,遍歷數組直接可用指針形參p實現。循環次數可讓變數 j控制, j的初值為 n,每次循環後讓 j減 1,循環直至 j為 0結束。寫成 c代碼如下:
float f( float p[], int n)
{ floa s; int j=n;
if( n<=0) return 0.0;
for( s=0.0; j>0; j——) s+=*p++;
return s/n;
}