1 單選題(每題 2 分,共 30 分)
第1題 在C++中,聲明一個指向整型變量的指針的正確語法是( ??)。
A. int* ptr;????????????????? B. *int ptr;??????????????? C. int ptr*;??????????????????????????? D. ptr int;
解析:答案:A。指針變量定義語法:?數據類型 * 變量名; 所以int* ptr; 語法正確。故選A。
第2題 下面的函數接收一個3行4列的二維數組并輸出其中元素,則橫線上不能填寫( ??)。
- void printArray(________) {
- ????for (int i = 0; i < 3; ++i)
- ????????for (int j = 0; j < 4; ++j)
- ????????????std::cout << arr[i][j] << " ";
- }
A. int arr[3][4]???????????? B. int arr[][4]??????????? C. int (*arr)[4]?????????????????????? D. int** arr
解析:答案:D。在C++中,“**”通常表示“指針的指針”。例如,在int** ptr; 中,ptr是一個指向“指針”的指針,而不是二維數組。A. 接收3行4列數組,符合要求;B. 接收二維數組行可省略、列必須給出,可以接收3行4列數組,符合要求;C. *arr接收行指針,每行4列,可以接收3行4列數組,符合要求。故選D。
第3題 在C++中,int arr[3][4]和int* arr = new int[12]均可模擬一個行列的二維數組。關于這兩種方式,下面說法錯誤的是( ??)。
A. int arr[3][4]在棧上分配空間,適合數組較小的情況;
B. int* arr = new int[12] 在堆上分配空間,數組較大時也適用;
C. 這兩種方式申請的內存空間都是連續的。
D. 這兩種方式申請的內存都能自動釋放。
解析:答案:D。在C++中,常規類型變量定義在棧上,內存自動管理,超出作用域自動釋放,適合小型數組(通常幾KB以內),訪問速度快,但大小必須在編譯時確定;動態分配內存定義在堆上,需要手動管理內存(new分配的必須使用delete[]釋放),適合大型數組(可達GB級別),大小可以在運行時確定,訪問速度稍慢于棧內存。A.、B.正確。C.靜態和動態分配內存都連續的,正確。D. 靜態申請的內存會自動釋放,動態申請的內存要手動管理、手動釋放,錯誤。故選D。
第4題 關于以下C++代碼,說法正確的是( ??)。
- int main() {
- ?greet();
- ?return 0;
- }
- void greet() {
- ?cout << "Hello!" << endl;
- }
A. 正確編譯并輸出Hello!????????????????????????? B. 編譯錯誤:找不到函數greet()
C. 編譯警告但可以運行??????????????????????????????? D. 鏈接錯誤
解析:答案:B。在C++中,函數引用必須在函數定義或聲明函數原型之后,如函數引用前未進行函數原型聲明,函數雙定義在引用之后,編譯時會引發“xxx未在此范圍內聲明”,其中xxx為函數名,B.正確。因不能完成編譯A.、C.、D.錯誤。故選B。
第5題 在C++中,如果希望通過函數修改傳入的結構體對象的內容,應該使用哪種參數傳遞方式?( ??)
A. 值傳遞或引用傳遞? ???????????????????????????????? B. 值傳遞或指針傳遞
C. 引用傳遞或指針傳遞??????????????????????????????? D. 僅指針傳遞
解析:答案:C。在C++中,函數用值傳遞,形式參數(形參)與實際參數(實參)獨立,形參的改變不影響實參。函數用指針傳遞,形式參數(形參)獲得的是實際參數(實參)的地址,形參與實參為同一地址,對形參的修改就是對實參修改。函數用引用傳遞,形式參數(形參)是實際參數(實參)的別名,兩者為不同名稱的同一變量,對形參的修改就是對實參修改。希望通過函數修改傳入的結構體對象的內容用指針傳遞和引用傳遞均可。故選C。
第6題 以下哪個選項正確描述了C++中形參和實參的區別?( ??)
A. 形參是函數調用時傳遞給函數的具體值,實參是函數定義中聲明的變量。
B. 形參是函數定義中聲明的變量,實參是函數調用時傳遞給函數的具體值。
C. 形參和實參在函數調用時是完全相同的。
D. 形參只在函數內部可見,實參在函數外部可見。
解析:答案:B。在C++中,實參是函數調用時傳遞給函數的具體值,形參是函數定義中聲明的變量,A.錯誤、B.正確、C.錯誤。在C++中,形參只在函數定義內部可見,是函數聲明時括號內定義的變量,作用域僅限于該函數體內,函數調用時由實參初始化,函數返回后形參就被銷毀;實參在函數調用處可見,是調用函數時傳入的具體值或變量,作用域取決于它原本的定義位置,可以是常量、變量或表達式,函數調用后仍然存在(除非是臨時對象或常量)D.錯誤。故選B。
第7題 運行如下代碼會輸出( ??)。
- int value = 100;
- void print1() {
- ????int value = 50;
- ????cout << value << " ";
- ????cout << ::value << " ";
- }
- void print2() {
- ????cout << value << " ";
- }
- print1();
- print2();
A. 100 100 100?????????? B. 50 50 50?????????????? C. 50 100 100????????????????????????????? D. 50 50 100
解析:答案:C。在C++中,在函數print1()中,第5行輸出的是第4行定義的局部變量value,::value是批全局變量,即第1行定義的value,所以print1()輸出“50 100 ”。 在函數print1()中,沒有定義同名局部變量value,所以第10行輸出的是全局變量value(全局變量所有函數可見),所以print2()輸出“100 ”,合起來輸出“50 100 100”。故選C。
第8題 小楊在整理一副撲克牌的所有紅心撲克牌,使其從小到大排列。他的做法是:最開始抓到第1張撲克牌被認為已經排好序;然后抓第2張撲克牌,將其插入至有序部分的正確位置;不斷循環步驟,每次將新抓到撲克牌插入至有序部分,直至抓完所有撲克牌,這樣抓牌結束時就完成了撲克牌的排序。小楊這種整理撲克牌的方式與( ??)排序 的方式最接近。
A. 冒泡排序??????????????? B. 插入排序????????????? C. 選擇排序??????????????????????????????????? D. 直接排序
解析:答案:B。冒泡排序是兩兩交換將最大(升序)的元素交換到最右側,然后對剩下n-1個元素用同樣方法將次大元素交換到n-1的最右側,以此類推。插入排序將有序無序兩部分,初始時選第1個元素為有序,將無序中的第1個元素插入到有序中正確位置,以此類推。選擇排序從未排序中選出一個歸小值交換到未排序的最左側,以此類推。直接排序算法分為直接插入排序算法和直接選擇排序算法兩種。故選B。
第9題 以下哪種情況是使用插入排序的合適場景?
A. 數據量非常大,且亂序嚴重???????????????????? B. 希望獲得穩定排序,但不要求實時性
C. 數據幾乎有序,只需少量調整????????????????? D. 想在交換次數最少的前提下排好大數組
解析:答案:C。A.數據量非常大,且亂序嚴重 用 歸并排序,時間復雜度穩定為?O(n log n)?,不受數據分布影響(快速排序在亂序時最壞可能退化到 O(n2))。B.?希望穩定排序,不要求實時性 用 歸并排序,歸并排序是?穩定排序?(相同元素相對位置不變),滿足核心需求,在穩定排序算法中,歸并排序是?唯一達到 O(n log n) 復雜度?的算法(冒泡/插入排序為 O(n2),效率過低)。?C. 數據幾乎有序,只需少量調整 用 插入排序,?最佳時間復雜度 O(n)?:當數據接近有序時,插入排序僅需少量比較和移動,效率遠超其他算法,算法簡單且穩定,適合小規模調整。?D. 交換次數最少排好大數組 → 若數組規模 ?n ≤ 10?? 用 選擇排序(優先最小化交換);若數組規模 ?n > 10?? → 堆排序(犧牲少量交換次數換取時間效率)。故選C。
第10題 以下關于遞推算法基本思想的描述,正確的是( ??)。
A. 遞推算法通過將問題分解為相互獨立的子問題來解決。
B. 遞推算法從已知的基礎情況出發,通過某種關系逐步推導出更大規模問題的解。
C. 遞推算法通常用于窮舉所有可能的解決方案。
D. 遞推算法適用于在每一步做出局部最優選擇以達到全局最優。
解析:答案:C。遞推算法的基本思想是利用已知信息(初始條件)和問題中各元素之間的固定關系(遞推關系),按照一定的規律或規則,?從初始狀態開始一步步推導出后續狀態(或目標狀態)的解?。從最簡單、最小規模的子問題(通常是問題的起點或邊界)開始求解;利用規模較小的子問題的解(通常是已經計算并存儲的結果),作為基礎,按照明確的規則(遞推公式、狀態轉移方程)去計算規模稍大的子問題的解。A.錯誤。B.正確。?C.不窮舉所有解,錯誤。?D.遞推不存在局部最優解問題,錯誤。故選B。
第11題 給定如下算法,其時間復雜度為( ??)。
- bool f(int arr[], int n, int target) {
- ????for (int i = 0; i < n; i++) {
- ????????int sum = 0;
- ????????for (int j = 0; j < n; j++) {
- ????????????if (i & (1 << j)) {
- ????????????????sum += arr[j];
- ????????????}
- ????????}
- ????????if (sum == target) return true;
- ????}
- ????return false;
- }
A. O(n)??????????????????????? B. O(n2)??????????????????? C. O(n3)???????????????????????????????? D. O(2?)
解析:答案:B。原則上,幾重循環就是O的n幾次方,兩重循環,時間復雜度為O(n2)。故選B。
第12題 下述斐波那契數列計算的時間復雜度是( ??)。
- int fibonacci(int n) {
- ????if (n == 0) return 0;
- ????if (n == 1) return 1;
- ????return fibonacci(n - 1) + fibonacci(n - 2);
- }
A. O(n)??????????????????????? B. O(n2)??????????????????? C. O(n3)???????????????????????????????? D. O(2?)
解析:答案:D。當參數為n時,時間復雜度為f(n)=f(n-1)+f(n-2),調用形成二叉樹,樹的高度h=n-1,共調用次數,即節點數(按滿二叉樹計)2??1-1=2??2-1個。時間復雜度為f(2??2-1)=O(2?)。故選D。
第 13 題 關于下面 C++ 程序的描述,( ??)最準確。
- ifstream in("data.txt");
- string line;
- while (getline(in, line)) {
- ????cout << line << endl;
- }
A. 將從標準輸入讀取每行,并輸出到屏幕
B. 程序無法運行,因為 getline 只能讀取 cin
C. 將 data.txt 中的每一行讀取并輸出到屏幕
D. 程序將創建 data.txt 并寫入默認文本
解析:答案:C。getline()的原型為istream& getline (istream& is, string& str);,is是一個流,例如cin,str是一個string類型的引用,讀入的字符串將直接保存在str里面。第1行in為從文件data.txt讀入的輸入流,第3、4行為從in(文件data.txt)按行讀入并顯示(輸出到屏幕),直到文件結束。A.錯誤,B.錯誤,D.錯誤。故選C。
第14題 在C++中,異常處理機制(try-catch塊)的主要目的是 (?? )。
A. 提高程序的運行速度。
B. 在程序發生運行時錯誤時,提供一種結構化的錯誤處理方式。
C. 確保程序在編譯時沒有錯誤。
D. 減少程序的內存占用。
解析:答案:B。異常處理機制(try-catch塊)的主要目的是提供一種?結構化、安全且非侵入式的方法來處理程序運行時的錯誤或異常情況?。A.錯誤,C.錯誤,D.錯誤。故選B。
第 15 題 為了提高冒泡排序的效率,如果某輪“冒泡”中沒有執行任何交換操作,說明數組已經完成排序,可直接返 回結果,則兩條橫線上分別應該填寫( )。
- void bubbleSortWithFlag(vector &nums) {
- ????for (int i = nums.size() - 1; i > 0; i--) {
- ????????bool flag;
- ????????________________ // 在此處填入代碼
- ????????for (int j = 0; j < i; j++) {
- ????????????if (nums[j] > nums[j + 1]) {
- ????????????????swap(nums[j], nums[j + 1]);
- ????????????????___________________________ // 在此處填入代碼
- ????????????}
- ????????}
- ????????if (!flag)
- ????????????break;
- ????}
- }
A. |
| B. |
|
C. |
| D. |
|
解析:答案:B。由于第12行中斷條件為!flag,也就是flag=false,即第6-11行如沒有交換flag=false。所以第9行有交換應該填flag=true,而第4行應該填flag=false,如沒有交換不會執行第9行,flag保持flase。故選B。
2 判斷題(每題 2 分,共 20 分)
第1題 下面C++代碼正確聲明了一個返回 int 類型、接受兩個 int 參數的函數。(?? )
- int add(int, int);
解析:答案:正確。函數原型(函數聲明)可以不寫形參變量名,只需各形參的類型即可。故正確。
第2題 下面C++代碼的輸出是15。(?? )
- void foo(int x) {
- ????x += 5;
- }
- int main() {
- ????int a = 10;
- ????foo(a);
- ????cout << a << endl;
- }
解析:答案:錯誤。函數foo()為值傳遞,修改形參不影響實參,所以函數內x=15,但不影響實參a,所以調用函數foo(a)后a仍為10,輸出結果為10。故錯誤。
第3題 下面c++代碼在一個結構體中又定義了別的結構體。這種結構嵌套定義的方式語法不正確。(?? )
- #include <iostream>
- #include <vector>
- using namespace std;
- struct Library {
- ????struct Book {
- ????????struct Author {
- ????????????string name;
- ????????????int birthYear;
- ????????};
- ????????string title;
- ????????int year;
- ????????Author author;
- ????};
- ????string name;
- ????vector<Book> books;
- };
解析:答案:錯誤。C++明確支持結構體類型的嵌套聲明,允許在結構體內定義其他結構體類型,這種嵌套方式類似“俄羅斯套娃”的數據組織方式,能有效處理層級數據關系。?代碼中,最外層Library結構體包含圖書館名稱和書籍集合,中間層Book結構體包含書名、出版年份和作者信息,最內層Author結構體存儲作者姓名和出生年份,所以程序語法正確。故錯誤。
第4題 在C++中,相比于值傳遞,使用引用傳遞作的優點可以直接操作和修改原始變量,避免數據拷貝,提高效率。(?? )
解析:答案:正確。引用傳遞作的形參相當于實參的別名,對形參的操作,就是對實參的操作。在C++中,引用傳遞相比值傳遞確實具有顯著優勢,1.避免數據拷貝:引用傳遞不會創建對象副本,特別是對大型數據結構(如vector/string)能顯著提升性能;2.減少內存開銷:傳遞引用僅傳遞內存地址(通常4/8字節),而值傳遞需要復制整個對象。故正確。
第5題 下面這段代碼不合法,因為每一行都必須顯式初始化3個元素。(?? )
- int arr[2][3] = {{1, 2}, {3}};
解析:答案:錯誤。該代碼是合法的,C++允許部分初始化多維數組,未顯式初始化的元素會自動設為0,題目中代碼等效于:int arr[2][3] ={{1,2,0}, {3,0,0}}。故錯誤。
第6題 以下程序中使用了遞推方式計算階乘(n!=1×2×?×n),計算結果正確。(?? )
- int factorial(int n) {
- ????int res = 1;
- ????for (int i = 0; i < n; ++i) {
- ????????res *= i;
- ????}
- ????return res;
- }
解析:答案:錯誤。該代碼第3行i應該從1到n,從0開始res永遠為0(res=res*0=0, res=res*i=0*i=0),無法得到正確結果,要得到正確結果第3行應修改為for (int i = 1; i <= n; ++i) {。故錯誤。
第7題 無論初始數組是否有序,選擇排序都執行O(n2)次比較。(?? )
解析:答案:正確。選擇排序問題從未排序中選其中最小(或最大)的元素與區域第1個元素交換,與數據是否有序無關,時間復雜度為O(n2)。故正確。
第8題 以下C++代碼,嘗試對有 n 個整數的數組 arr 進行排序。這個代碼實現了選擇排序算法。(?? )
- for (int i = 0; i < n - 1; ++i) {
- ????int minIndex = i;
- ????for (int j = i + 1; j < n; ++j) {
- ????????if (arr[j] < arr[minIndex])
- ????????????minIndex = j;
- ????}
- ????if (minIndex != i)
- ????????swap(arr[i], arr[minIndex]);
- }
解析:答案:正確。外層循環?:控制排序輪數,每次確定一個最小元素的位置i從0遍歷到n-2(共需n-1輪);?內層循環?:在未排序部分(i+1到n-1)中查找最小元素,通過minIndex記錄當前最小元素的下標(初始為i);?元素交換?:每輪結束后,將找到的最小元素與第i個位置交換,swap()函數實現元素位置互換。為是典型的選擇排序,對數組arr進行升序排序。故正確。
第9題 如果一個異常在 try 塊中拋出但沒有任何 catch 匹配,它將在編譯時報錯。(?? )
解析:答案:錯誤。C++編譯器不會因為try塊中拋出的異常未被捕獲而報錯,語法上只要求try必須搭配至少一個catch塊,但不強制catch必須匹配所有可能的異常類型。?運行時,當拋出的異常未被任何catch塊捕獲時,程序會調用std::terminate()終止執行。故錯誤。
第10題 下面C++代碼實現將Hello寫入 data.txt。(?? )
- ofstream out("data.txt");
- out << "Hello";
- out.close();
解析:答案:正確。這段C++代碼的功能是向文件寫入數據:創建ofstream(寫文件輸出流)對象out并關聯到"data.txt"文件,使用流插入運算符<<寫入字符串"Hello",顯式調用close()關閉文件流。若文件不存在會自動創建新文件,若文件已存在會覆蓋原有內容(默認模式),最終文件內容為單行"Hello"字符串。故正確。
3 編程題(每題 25 分,共 50 分)
3.1 編程題1
- 試題名稱:畫布裁剪
- 時間限制:1.0 s
- 內存限制:512.0 MB
3.1.1 題目描述
小A在高為h寬為w的矩形畫布上繪制了一幅畫。由于畫布邊緣留白太多,小A想適當地裁剪畫布,只保留畫的主體。具體來說,畫布可以視為h行w列的字符矩陣,其中的字符均為 ASCII 碼位于33~126之間的可見字符,小A只保留畫布中由第x?行到第x?行、第y?列到第y?列構成的子矩陣。 小A將畫布交給了你,你能幫他完成畫布的裁剪嗎?
3.1.2 輸入格式
第一行,兩個正整數h,w,分別表示畫布的行數與列數。
第二行,四個正整數x?,x?,y?,y?,表示保留的行列邊界。
接下來h行,每行一個長度為w的字符串,表示畫布內容。
3.1.3 輸出格式
輸出共x?-x?+1行、每行一個長度為y?-y?+1的字符串,表示裁剪后的畫布。
3.1.4 樣例
3.1.4.1 輸入樣例1
- 3 5
- 2 2 4
- .....
- .>_<.
- .....
3.1.4.2 輸出樣例1
- >_<
3.1.4.3 輸入樣例2
- 5 5
- 1 2 3 4
- AbCdE
- fGhIk
- LmNoP
- qRsTu
- VwXyZ
3.1.4.4 輸出樣例2
- Cd
- hI
3.1.5 數據范圍
對于所有測試點,保證1≤h,w≤100,1≤x?,x?≤h,1≤y?,y?≤w。
3.1.6 編寫程序思路
分析:本題可以用二維數組來做,先定義二維字符數組,按行、列輸入n行、m列字符(畫布),然后截取x1、y1到x2、y2范圍內的元素輸出。完整程序代碼如下:
#include?<iostream>
using?namespace?std;const?int?N?=?105; //最多100,從1開始并適當留余量
char?a[N][N];
int?main()?{int?n,?m,?x1,?x2,?y1,?y2;cin?>>?n?>>?m;cin?>>?x1??>>?x2?>>?y1?>>?y2;for?(int?i?=?1;?i?<=?n;?i++)?//行從1開始for?(int?j?=?1;?j?<=?m;?j++)?//列也從1開始cin?>>?a[i][j];?//輸入元素for?(int?i?=?x1;?i?<=?x2;?i++)?{?//行從x1到x2for?(int?j?=?y1;?j?<=?y2;?j++)?//列從y1到y2cout?<<?a[i][j];?//輸出指定范圍內元素cout?<<?endl;}return?0;
}
3.2 編程題2
- 試題名稱:排序
- 時間限制:1.0 s
- 內存限制:512.0 MB
3.2.1 題目描述
體育課上有n名同學排成一隊,從前往后數第i位同學的身高為h?,體重為w?。目前排成的隊伍看起來參差不齊,老師希望同學們能按照身高從高到低的順序排隊,如果身高相同則按照體重從重到輕排序。在調整隊伍時,每次只能交換相鄰兩位同學的位置。老師想知道,最少需要多少次交換操作,才能將隊伍調整成目標順序。
3.2.2 輸入格式
第一行,一個正整數n,表示隊伍人數。
接下來n行,每行兩個正整數h?和w?,分別表示第i位同學的身高和體重。
3.2.3 輸出格式
輸出一行,一個整數,表示最少需要的交換次數。
3.2.4 樣例
3.2.4.1 輸入樣例1
- 5
- 1 60
- 3 70
- 2 80
- 4 55
- 4 50
3.2.4.2 輸出樣例1
- 8
3.2.4.3 輸入樣例2
- 5
- 4 0
- 4 0
- 2 0
- 3 0
- 1 0
3.2.4.4 輸出樣例2
- 1
3.2.5 數據范圍
對于所有測試點,保證1≤n≤3000,h?,w?≤10?。
3.2.6 編寫程序思路
分析:本題是成對元素的數組,用vector<pair<int,int>>可變數組是節省空間的,但GESP C++四級標準中未涉及可變數組。由于元素是成對的可考慮用結構體數組。定義兩個成員a、b的結構體數組s[],成員a為身高、成員b為體重,讀入數據,要求按身高從高到低的順序排隊,如果身高相同則按照體重從重到輕排序,交換判斷條件s[i].a<s[j].a || (s[i].a==s[j].a && s[i].b<s[j].b)。完整程序代碼如下:
#include?<iostream>
using?namespace?std;const?int?N?=?3005; //數據范圍不超過3000
struct?{int?a;int?b;
}?s[N]; //定義兩個成員的結構體數組int?main()?{int?n,?cnt?=?0;cin?>>?n; //輸入學生人數for?(int?i?=?0;?i?<?n;?i?++)cin?>>?s[i].a?>>?s[i].b; //輸入每人的身高、體重for?(int?i?=?0;?i?<?n;?i?++)for?(int?j?=?i?+?1;?j?<?n;?j?++)if?(s[i].a?<?s[j].a?||?(s[i].a?==?s[j].a?&&?s[i].b?<?s[j].b))cnt?++;cout?<<?cnt?<<?endl;return?0;
}