⼀、單項選擇題(15⼩題,每⼩題2分,共30分)html
解析:【傳值調用】,實參和形參之間傳遞的是「地址」數組
解析:【優先級】:算術運算符 > 關係運算符 > 賦值運算符 函數
【結核性】:賦值運算符(從右至左) 算數運算符和關係運算符(從左至右)測試
至關於: ( k > i ) < j , ( i < j ) == ( j < k ) 編碼
解析:指針數組是指數組的每個元素都是一個指針變量的數組加密
至關於: point[2] 同樣spa
例如:設計
解析:數組定義時,常量表達式中不容許包含變量3d
解析:【函數遞歸】,至關於 fib (2) + fib (1) 指針
解析:【do 循環】
解析:【數組傳參】:傳過去的是地址,實參和虛參都改變
題目有錯!!!
解析:【運算優先級】:「 * 」和「 ++ 」 高於 " = ",「 * 」和「 ++ 」優先級相同,結合性:從右往左
*p1 += *p2++ 至關於: *p1 = *p1 + *(p2++)
*p2 = p1++ 至關於: *p1 = (p1++)
解析:【運算優先級】+ 【結合性】
i = 3 / 2 + 7 / 2 == 5 至關於: i = ( ( (3 / 2) + (7 / 2) ) == 5 )
j = 45 % 11 + (((7 > 8) ? 15: 14) == 14 至關於:j = (45 % 11) + ((((7 > 8) ? 15: 14) == 14 )
解析:!x是邏輯非操做,當x爲0時,值爲真,不然值爲假。 在這裏等效於x==0 ,即x = 8,while (!x) 爲假,退出循環
例如:
解析:(i * j) / k + 6 - 15 % k 至關於 ((i * j) / k) + 6 - (15 % k) : 「+」和「-」 結合性從左向右
解析: while()是循環語句。while(expr)表示當邏輯表達式expr爲真時,循環運行循環體,直到expr值爲假或遇到break語句時退出
由 316 = 13 * i + 11 * j 得:k 必定得是11的倍數
例:
解析:【字符數組的定義】:
char cc[ ] = {'1','2','3','4','5'}, 數組長度爲5,字符串長度爲5
char cc[ ] =」12345「,數組長度爲6,字符串長度爲5,自動在字符串結尾加上一個終止符 \0 ,
[strlen()]函數:測試字符串長度,不包括 \0
解析: 【指針與結構數組】:指向結構 的 指針 要先定義,後賦值
p 指向結構第一個字節,*p 至關於 stu
第一種方式:(*p).num 【因爲結構成員引用符 "."的優先級比間接運算符 「 *」 高,故必須加括號】
第二種方式:p->num
第二種方式:stu.num 三種方式等價!!!
⼆、指出程序段中的錯誤:分析緣由並修改。(每題15分,共30分)
改正後:
int main() { char *src = "HELLO,UESTC"; //指向字符串常量的指針 char *dest = NULL; int len = strlen(src); dest = (char *)malloc(len + 1); char *d = dest; char *s = &src[len - 1]; while ( len-- != 0 ) *d++ = *s--; *d = '\0'; printf("%s\n", dest); // 使用printf()輸出時,%s 表示輸出一個字符串,src指向字符串的第一個字符,而後src自動加1 free(dest); return 0; }
知識點:
【指向字符串常量的指針】:不是將字符串存放在指針src中,而是將指向字符串的指針賦給指針變量,src指針指向字符串的首地址
改正後:
void fun() { char data[50] = "welcome to CHENGDU and UESTC"; char *point; char array[200]; int i = 0, length = 0; point = array; while (data[length] != '\0') length++; for (; i < length; i++) { *point = *data; point++; } puts(data); }
3、問答題(共70分)
一、C語⾔的單詞符號除關鍵字外,還包括其餘哪四類?存儲類型關鍵字是哪4個?(每一個1分,共8分)
答: 標識符【只能由字母、常量、下劃線、數字組成,且第一個字符必須是字母或者下劃線】、運算符、常量和分隔符【空格、製表符、換行符】。
存儲類型關鍵字:anto、extern、register、static二、函數中,如何使⽤與局部變量同名的全局變量?(3分)
答:使⽤::(做⽤域區分符)(3分)
三、如何使⽤1個表達式將float類型變量f的值四舍五⼊ 轉換爲long類型的值?(3分)
答:(long)(f + 0.5) (3分)
四、參數傳遞的⽅式分別是什麼?(6分)
數組做爲函數參數有三種形式:
1. 實參是數組元素; 傳(數據)值(2分)
2. 形參是指針,實參是數組; 傳地址值(2分)
3. 函數的形參和實參都是數組。 傳地址(2分)五、 C程序運⾏時,不對數組進⾏越界檢查,可能致使什麼問題?(5分)
答:編譯經過,但可能致使運⾏出錯(訪問不可訪問的存儲單元)(3分)或訪問和修改
其餘⾮數組元素的數據。(2分)六、C語⾔的隱式類型轉換髮⽣在哪4種狀況下?轉換規則分別是什麼?(6分)
混合運算: 級別低的類型向級別⾼的類型值轉換。 1分
將表達式的值賦給變量: 表達式的值向變量類型的值轉換。 1分
實參向函數形參傳值: 實參的值向形參的值進⾏轉換。 2分
函數返回值: 返回值向函數返回類型的值進⾏轉換。 2分七、程序⽚段爲: (14分)
當程序執⾏進⼊fun函數時,請列出各個數據(包括常量、變量)在內存中對應存儲區的名稱和數據的存儲順序以及所佔⽤的存儲空間的字節數。
假設整數佔2個字節,字符佔2個字節,指針佔4個字節;⽽內存按2個字節進⾏編址。存儲區名稱1分,其餘每3個1分
int n = 2018; void main() { char * p=」COMPUTER」, *q; int mm, arr[2018]; char ch2; ... fun(mm); ... } void fun(int nn) { int mm = 10; static int snum; ... }
八、下⾯的程序的功能是什麼?(5分)
void main () { int d, i, j, k, flag1, flag2; scanf("%d", &d); for (i = 1; i <= 100; i++) { j = i; flag1 = 0;
// 該數是否含有 d while ((j > 0) && (!flag1)) { k = j % 10; j = j / 10; if (k == d) flag1 = 1; }
// 該數的平方是否含有 d if (flag1) { j = i * i; flag2 = 0; while ((j > 0) && (!flag2)) { k = j % 10; j /= 10; if (k == d) flag2 = 1; } if(flag2) printf("%-5d %-5d\n", i, i * i); } } }功能:輸⼊數字d=0~9,找1~100中滿⾜條件的數:該數的本⾝及它的平⽅中都含有數字d。
九、採⽤Eratasthenes篩選法求2-200之間的素數 連接:http://www.javashuo.com/article/p-xhhhwtle-dn.html 請對第六、七、八、9⾏的代碼進⾏修改,使得程序執⾏效率獲得提⾼。(8分)
void main() { int prime[201] = {0}; //用於存儲200之內的數是否已篩去 int d, i,k; for (d = 2; d < 200; d++) if (prime[d] == 0) for (k = d + 1; k <= 200; k++) if (k % d == 0) prime[k] = 1; for (i = 2; i <= 200; i++) if(prime[i]==0) printf("%d\t", i); }
// 改成: for (d=2; d < sqrt(200); d++) if (prime[d] == 0) for (k = 2*d; k<=200; k = k+d) //篩去d的全部倍數 prime[k]=1;
要點:
爲提升篩選效率:
一個合數n必有一個不大於sqrt(n)的正因子,故一個數如果沒有小於sqrt(n)的正因子,則說明它是一個素數
十、爲提⾼程序執⾏效率,C語⾔除了提供指針、宏定義、位運算、不檢查數組下標外,簡述C語⾔還採起了其餘哪些措施及緣由(12分)
主要從 數據類型 類型檢查 邏輯運算的處理 等⽅⾯分析。
例如: 寄存器變量 ⽆布爾類型 ⽆⼦界類型
a&&b(只有a成⽴才計算b) 數組作參數是採⽤傳地址⽅式 等
4、程序填空(每空2.5分,共50分)
一、快排找第K⼩
low = 0; // 該空爲填空 high = n - 1; // 該空爲填空 do { do { i = low; j = high; // 該空爲填空 t = a[i]; // 該空爲填空 } while(i < j); // 該空爲填空 a[i] = t; // 該空爲填空 if(i == k) return t; // 該空爲填空 if(i > k) high = i - 1; // 該空爲填空 if(i < k) low = i + 1; // 該空爲填空 }while(low < high); return a[low]; // 該空爲填空
此題錯誤!!!
改正後:仍是有錯!!!
low = 0; high = n - 1; do { i = low; j = high; t = a[i]; do { while (a[j--] > t) ; while (a[i++] < t) ; if(i < j) swap(a[j], a[i]); }while(i < j);
// 折半查找 if(i == k) return t; if(i > k) high = i - 1; if(i < k) low = i + 1; }while(low < high); return a[low];
代碼:
const int n = 5; void main() { int a[5] = {3,1,4,6,2}; int low,high,k; low = 0; high = n - 1; printf("請輸入查找第K小的數:\n"); scanf("%d",&k); find(a,low,high,k); } int find(int a[],int low,int high,int k) { int t = a[low]; int i = low; int j = high; while(low < high) { while(low < high && a[high] >= t) --high; a[low] = a[high]; while(low < high && a[low] <= t) low++; a[high] = a[low]; } a[low] = t; // 折半查找 if(low == k) { return a[low]); return 0; } else if(low > k) return find(a,i,low - 1,k); else return find(a,low + 1,j,k - low); }
二、⼀個包含9個數的⾮降序數列存儲在數組中,如今插⼊⼀個數到合適位置,使序列保持⾮降序(插⼊的數⼤於第⼀個數,⼩於第九個數)。
#define N 10 void main() { int a[N] = {1,2,4,8,16,32,64,128,256}; int m,i,d; scanf("%d",&d);
//找到插入點 for(i = 0; i < 9 ; i++) //這裏填N-1也行 if( d < a[i] ) { m = i ; break ; }
// m以後的日後移 for(i = 8; i >= m; i--) //這裏填N-2也行 a[i + 1] = a[i];
// 插入 a[m] = d;
// 打印 for(i = 0;i < N;i++) printf("%d\t",a[i]); }三、凱撒密碼
這道題是⼀道加密解密問題,⼤致的意思就是經過主函數輸⼊兩個字符串,第⼀個字符串做爲加密解密的⽬標
字符串,第⼆個字符串經過函數轉換爲整型數據做爲解密加密的key,這道題也不難推導,以上是我在⽹絡上找到
的⼀個類似版本。
凱撒加密(Caesarcipher)是⼀種簡單的消息編碼⽅式:它根據字母表將消息中的每一個字母移動常量位k。
舉個例⼦若是k等於3,則在編碼後的消息中,每一個字母都會向前移動3位:
a會被替換爲d;b會被替換成e;依此類推。字母表末尾將回捲到字母表開頭。
因而,w會被替換爲z,x會被替換爲a。代碼:
#include <stdio.h> #include <stdlib.h> int main () { char small_letter[26] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; char big_letter[26] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; char text[1000], result[1000]; int c, count = 0, k, p,i; char function; printf("Insert Text:"); c = getchar(); while (1) // 讀取字符串 { if (c == '\n') break; text[count] = c; printf("%c", text[count]); count++; c = getchar(); //讀取下一個字符 } printf("\n"); printf("Encrypt or Decrypt? E or D :"); scanf("%c", &function); // 加密 if (function == 'E') { printf("Insert Key :" ); scanf("%d", &k); for (i = 0; i < count; i++) { if (text[i] >= 'A' && text[i] <= 'Z') { result[i] = big_letter[((text[i] - 'A') + k) % 26]; // 向前挪k位 } //找出加密後字符在字符數組裏的對應位置 else if (text[i] >= 'a' && text[i] <= 'z') { result[i] = small_letter[((text[i] - 'a') + k) % 26]; // 向前挪k位 } else result[i] = text[i]; printf("%c", result[i]); } } // 解密 else { printf("Insert Key :" ); scanf("%d", &k); for (i = 0; i < count; i++) { if (text[i] >= 'A' && text[i] <= 'Z') { p = ((text[i] - 'A') - k); // 解碼涉及 字母表末尾將回捲到字母表開頭 while (p < 0) p += 26; result[i] = big_letter[p]; // 向後挪k位 } //找出解密後字符在字符數組⾥裏里的對應位置 //這裏要注意不要讓它超出範圍(下表位置爲負數) else if (text[i] >= 'a' && text[i] <= 'z') { p = ((text[i] - 'a') - k); while (p < 0) p += 26; result[i] = small_letter[p]; // 向後挪k位 } else result[i] = text[i]; printf("%c", result[i]); } printf("\n"); } return 0; }
5、程序設計(共20分)
輸⼊若⼲個整數(以0結束)如何逆序構建雙向鏈表
代碼:
#include <stdio.h> #include <stdlib.h> //雙鏈表結構定義 typedef struct DNode { int data; struct DNode *pre; struct DNode *next; } DNode; int main() { DNode *head, *s; int t; // 定義頭節點 head = (DNode*)malloc(sizeof(DNode)); head->pre = NULL; head->next = NULL; // 輸入 scanf("%d", &t); while (t != 0) { s = (DNode*)malloc(sizeof(DNode)); s->data = t; s->next = NULL; s->pre = NULL; if (head->next == NULL) { head->next = s; s->pre = head; } else { // 頭插法【逆序】 s->next = head->next; head->next->pre = s; head->next = s; s->pre = head; } scanf("%d", &t); } s = head->next; while (s) { printf("%d ", s->data); s = s->next; } return 0; }