#C1102. 府学集训试题2

府学集训试题2

本卷共 50 题:单项选择题 30 题(每题 2 分)、多项选择题 10 题(每题 3 分)、判断题 10 题(每题 1 分),满分 100 分。

一、单项选择题(每题 2 分)

  1. 执行下面程序后,输出为( )。
int mul(int a = 3) {
    return a * 5;
}
int main() {
    cout << mul() << " " << mul(2);
}

{{ select(1) }}

  • 3 2
  • 15 10
  • 10 15
  • 15 2
  1. 执行下面代码后,输出为( )。
int main() {
    int a = 4;
    int* p = &a;
    *p += 6;
    cout << a << " " << *p;
}

{{ select(2) }}

  • 4 4
  • 10 10
  • 10 4
  • 4 10
  1. 已知:
int a[3][4] = {
    {3,6,9,12},
    {15,18,21,24},
    {27,30,33,36}
};
int (*p)[4] = a;

则表达式 *(*(p + 2) + 1) 的值为( )。

{{ select(3) }}

  • 18
  • 30
  • 27
  • 33
  1. 执行下面程序后,输出为( )。
void change(int a, int &b, int *c) {
    a += 2;
    b += 4;
    *c += 6;
}
int main() {
    int x = 1, y = 1, z = 1;
    change(x, y, &z);
    cout << x << " " << y << " " << z;
}

{{ select(4) }}

  • 3 5 7
  • 1 5 7
  • 3 1 7
  • 1 1 1
  1. 执行下面程序后输出为( )。
int x = 2;
void test(int &x) {
    x += 4;
}
int main() {
    int x = 7;
    test(x);
    cout << x << " " << ::x;
}

{{ select(5) }}

  • 11 2
  • 7 6
  • 11 6
  • 7 2
  1. 下列关于结构体初始化的写法,正确的是( )。

{{ select(6) }}

  • struct Student { string name; int age; }; Student s = ("Tom", 18);
  • struct Student { string name; int age; }; Student s = {"Tom", 18};
  • struct Student { string name; int age; }; Student s = new Student("Tom", 18);
  • struct Student { string name; int age; }; Student s = <"Tom", 18>;
  1. 执行下面代码后输出为( )。
struct Rect { int w; int h; };
void setW(Rect r) { r.w = 10; }
void setH(Rect &r) { r.h = 10; }
int main() {
    Rect r{4, 5};
    setW(r);
    setH(r);
    cout << r.w << " " << r.h;
}

{{ select(7) }}

  • 10 10
  • 4 10
  • 10 5
  • 4 5
  1. 关于递推算法的描述,正确的是( )。

{{ select(8) }}

  • 递推必须使用递归调用实现
  • 递推从已知初始条件出发,通过递推关系逐步求解
  • 递推只能用于指数复杂度问题
  • 递推一定需要回溯
  1. 执行 steps(8) 的返回值为( )。
int steps(int n) {
    if(n <= 2) return n;
    int a = 1, b = 2, c = 0;
    for(int i = 3; i <= n; i++) {
        c = a + b;
        a = b;
        b = c;
    }
    return c;
}

{{ select(9) }}

  • 13
  • 21
  • 8
  • 34
  1. 已知 int arr[4][3];,下面说法正确的是( )。

{{ select(10) }}

  • 数组一共包含 7 个元素
  • 二维数组初始化时允许省略行数,不可省略列数
  • arr 代表数组第一个元素的数值
  • arr[0] 存储整个二维数组全部数据
  1. 下面代码试图把数组按升序进行"插入排序",横线处应填写( )。
void sortInsert(int arr[], int n) {
    for(int i = 1; i < n; i++) {
        int cur = arr[i];
        int j = i - 1;
        while(j >= 0 && ______) {
            arr[j+1] = arr[j];
            j--;
        }
        arr[j+1] = cur;
    }
}

{{ select(11) }}

  • arr[j] < cur
  • arr[j] > cur
  • arr[j+1] > cur
  • arr[j] == cur
  1. 下列代码段的时间复杂度为( )。
int count = 0;
for(int i = 0; i < n; i++) {
    for(int j = 0; j < n; j++) {
        if((i + j) % 2 == 1) count++;
    }
}

{{ select(12) }}

  • O(n)
  • O(n log n)
  • O(n²)
  • O(2n)
  1. 执行下面程序后,输出结果是( )。
int main() {
    int a = 5;
    int b = 10;
    int* p = &a;
    p = &b;
    *p = 20;
    cout << a << " " << b;
    return 0;
}

{{ select(13) }}

  • 5 10
  • 5 20
  • 20 10
  • 20 20
  1. 执行下面程序,输出结果是( )。
int cal(int a, int b) {
    if(b == 0) throw 2;
    return a / b;
}
int main() {
    try {
        cout << cal(6, 0);
    } catch(const char* msg) {
        cout << "ErrA";
    } catch(int) {
        cout << "ErrB";
    }
}

{{ select(14) }}

  • ErrA
  • ErrB
  • 程序崩溃
  • 无输出
  1. 下列函数实现数组中元素的向前移动(类似插入排序的相邻搬移)。当某元素值增大需要前移时,while 循环的条件应为( )。
void moveFront(int arr[], int n, int idx) {
    int cur = arr[idx];
    int i = idx;
    while(______) {
        arr[i] = arr[i - 1];
        i--;
    }
    arr[i] = cur;
}

{{ select(15) }}

  • i > 0 && cur > arr[i - 1]
  • i > 0 && cur < arr[i - 1]
  • i < n - 1 && cur > arr[i + 1]
  • i < n - 1 && cur < arr[i + 1]
  1. 下列关于指针的说法,正确的是( )。

{{ select(16) }}

  • 指针变量存储的是变量的值
  • 通过指针可以间接访问和修改它指向的变量
  • 指针变量只能指向整型变量
  • 指针变量一旦定义就不能改变指向
  1. 已知:
int a[3][3] = {
    {2,4,6},
    {8,10,12},
    {14,16,18}
};
int (*p)[3] = a;

则表达式 *(*(p + 0) + 2) 的值为( )。

{{ select(17) }}

  • 4
  • 6
  • 8
  • 10
  1. 执行下面程序后,输出为( )。
void update(int a, int &b, int *c) {
    a += 1;
    b += 2;
    *c += 3;
}
int main() {
    int x = 5, y = 5, z = 5;
    update(x, y, &z);
    cout << x << " " << y << " " << z;
}

{{ select(18) }}

  • 6 7 8
  • 5 7 8
  • 6 5 8
  • 5 5 5
  1. 执行下面程序后输出为( )。
int x = 6;
void add(int &x) {
    x += 5;
}
int main() {
    int x = 9;
    add(x);
    cout << x << " " << ::x;
}

{{ select(19) }}

  • 14 6
  • 9 11
  • 14 11
  • 9 6
  1. 下列关于结构体初始化的写法,正确的是( )。

{{ select(20) }}

  • struct Book { string title; int price; }; Book b = ("C++", 50);
  • struct Book { string title; int price; }; Book b = {"C++", 50};
  • struct Book { string title; int price; }; Book b = new Book("C++", 50);
  • struct Book { string title; int price; }; Book b = <"C++", 50>;
  1. 执行下面代码后输出为( )。
struct Score { int math; int eng; };
void changeMath(Score s) { s.math = 100; }
void changeEng(Score &s) { s.eng = 100; }
int main() {
    Score s{80, 90};
    changeMath(s);
    changeEng(s);
    cout << s.math << " " << s.eng;
}

{{ select(21) }}

  • 100 100
  • 80 100
  • 100 90
  • 80 90
  1. 关于递推算法的描述,正确的是( )。

{{ select(22) }}

  • 递推必须使用递归调用实现
  • 递推从已知边界条件出发,按递推关系逐步推出后续结果
  • 递推只能解决指数复杂度问题
  • 递推一定需要回溯
  1. 下面关于递归与递推的说法,正确的是( )。

{{ select(23) }}

  • 递归算法一定比递推算法效率更高
  • 递推算法通常使用循环结构实现,从已知条件逐步推导到目标
  • 递归算法不需要定义终止条件
  • 所有递归算法都可以直接改写为递推算法且复杂度不变
  1. 某排序算法对如下数据排序(按 value 升序),则关于该排序算法稳定性的描述中,说法正确的是( )。
初始: (88, 'A'), (88, 'B'), (76, 'C'), (88, 'D')
排序后: (76, 'C'), (88, 'A'), (88, 'B'), (88, 'D')

{{ select(24) }}

  • 不稳定,因为出现了相同value
  • 稳定,因为相同value的原始相对顺序得到保持
  • 不稳定,因为C被移到了最前面
  • 无法判断
  1. 下面代码试图把数组按升序进行"插入排序",横线处应填写( )。
void insertionSort(int a[], int n) {
    for(int i = 1; i < n; i++) {
        int key = a[i];
        int j = i - 1;
        while(j >= 0 && ______) {
            a[j+1] = a[j];
            j--;
        }
        a[j+1] = key;
    }
}

{{ select(25) }}

  • a[j] < key
  • a[j] > key
  • a[j+1] > key
  • a[j] == key
  1. 下列代码段的时间复杂度为( )。
int total = 0;
for(int i = 0; i < n; i++) {
    for(int j = 0; j < n; j++) {
        if((i * j) % 2 == 0) total++;
    }
}

{{ select(26) }}

  • O(n)
  • O(n log n)
  • O(n²)
  • O(2n)
  1. 在 C++ 中,ofstream 以默认方式打开文件时,若文件不存在,则( )。

{{ select(27) }}

  • 报错并终止程序
  • 自动创建新文件
  • 返回空指针
  • 跳过该操作
  1. 执行下面程序,输出结果是( )。
int divideNum(int a, int b) {
    if(b == 0) throw 5;
    return a / b;
}
int main() {
    try {
        cout << divideNum(12, 0);
    } catch(const char* msg) {
        cout << "ErrorX";
    } catch(int) {
        cout << "ErrorY";
    }
}

{{ select(28) }}

  • ErrorX
  • ErrorY
  • 程序崩溃
  • 无输出
  1. 下列函数实现数组中元素的向前移动(类似插入排序的相邻搬移)。当某元素值增大需要前移时,while 循环的条件应为( )。
void moveUp(int a[], int n, int pos) {
    int cur = a[pos];
    int i = pos;
    while(______) {
        a[i] = a[i - 1];
        i--;
    }
    a[i] = cur;
}

{{ select(29) }}

  • i > 0 && cur > a[i - 1]
  • i > 0 && cur < a[i - 1]
  • i < n - 1 && cur > a[i + 1]
  • i < n - 1 && cur < a[i + 1]
  1. 执行下面代码后,输出为( )。
int main() {
    int a = 9;
    int* p = &a;
    *p += 5;
    cout << a;
}

{{ select(30) }}

  • 9
  • 11
  • 12
  • 14

二、多项选择题(每题 3 分)

  1. 下列关于 C++ 函数参数传递的说法,正确的有( )。

{{ multiselect(31) }}

  • 值传递会在函数内部生成实参的独立副本,修改形参不影响实参
  • 引用传递允许函数直接修改实参的值,且无需拷贝开销
  • 指针传递可以通过解引用操作修改实参的值
  • 引用传递一旦绑定变量后,可以重新绑定到另一个变量
  1. 关于二维数组与指针的说法,正确的有( )。

{{ multiselect(32) }}

  • 二维数组名本质上是指向第一行的指针
  • int (*p)[4] 表示 p 是一个指向包含 4 个 int 元素的一维数组的指针
  • 指针算术运算 p + 1 在二维数组中会跳过一整行
  • int* p = a[0] 可以正确获取二维数组首行首元素的地址
  1. 下面关于结构体(struct)的描述,正确的有( )。

{{ multiselect(33) }}

  • 结构体可以使用列表初始化 { } 进行初始化
  • 结构体变量作为函数参数进行值传递时,函数内修改不会影响外部实参
  • 结构体变量作为函数参数进行引用传递时,函数内修改会影响外部实参
  • 结构体内部不能定义另一个结构体类型
  1. 关于递推与迭代的描述,正确的有( )。

{{ multiselect(34) }}

  • 递推是从已知初始条件出发,逐步推导出后续结果的过程
  • 迭代是重复执行某段代码,通常用循环结构实现
  • 所有递归算法都可以转化为递推实现
  • 递推算法的时间复杂度一定比递归算法低
  1. 关于排序算法及其稳定性,说法正确的有( )。

{{ multiselect(35) }}

  • 如果两个相等元素在排序后相对顺序保持不变,则称该排序算法是稳定的
  • 冒泡排序在相邻元素相等时不进行交换,可以保证稳定性
  • 选择排序通过交换操作将最小值放到前面,可能会破坏稳定性
  • 插入排序在相等元素的处理上,不会将它们交换到彼此前面,因此是稳定的
  1. 关于插入排序算法的描述,正确的有( )。

{{ multiselect(36) }}

  • 插入排序每次将当前元素插入到已排序部分的合适位置
  • 插入排序在数组接近有序时效率较高
  • 插入排序的时间复杂度始终为 O(n²)
  • 插入排序的 while 循环中,条件 j >= 0 && a[j] > key 用于为升序排序找到插入位置
  1. 关于时间复杂度分析,正确的有( )。

{{ multiselect(37) }}

  • 单层 for 循环从 0 到 n-1 的时间复杂度为 O(n)
  • 双层完全嵌套循环的时间复杂度为 O(n²)
  • 循环体内部的 if 条件语句不会改变循环整体的时间复杂度量级
  • 所有递归算法的时间复杂度都是 O(2ⁿ)
  1. 关于 C++ 流操作与文件重定向,正确的有( )。

{{ multiselect(38) }}

  • freopen("file.txt", "w", stdout) 可以将 cout 的输出重定向到文件
  • 使用 streambuf 可以临时替换 cout 的缓冲区实现输出重定向
  • cout << "text" 默认输出到标准输出(屏幕),除非进行了重定向
  • ofstream 类对象可以通过 << 操作符向文件写入数据
  1. 关于 C++ 异常处理,正确的有( )。

{{ multiselect(39) }}

  • try 块中抛出异常后,程序会立即跳出 try 块并匹配对应的 catch
  • catch 语句可以根据抛出的数据类型进行匹配捕获
  • 一个 try 块可以搭配多个不同类型的 catch 块
  • 如果异常没有被任何 catch 块捕获,程序会继续正常运行
  1. 关于 C++ 指针的操作,正确的有( )。

{{ multiselect(40) }}

  • & 运算符用于获取变量的内存地址
    • 运算符用于解引用指针,访问指向的内容
  • 指向指针的指针(如 int**)可以用于多级间接访问
  • 指针变量必须使用 & 取地址符才能赋值

三、判断题(每题 1 分)

  1. 执行下面代码后,变量 a 的值最终为 28。
void modify(int &x) {
    x += 13;
}
int main() {
    int a = 15;
    modify(a);
    return 0;
}

{{ select(41) }}

  • 正确
  • 错误
  1. 执行下面代码后,输出结果为 7。
int main() {
    int a[2][4];
    cout << &a[1][2] - &a[0][3] << endl;
    return 0;
}

{{ select(42) }}

  • 正确
  • 错误
  1. 执行下面程序后,输出结果为 30 8。
int x = 8;
void output() {
    int x = 30;
    cout << x << " ";
}
int main() {
    output();
    cout << x;
    return 0;
}

{{ select(43) }}

  • 正确
  • 错误
  1. 执行下面程序后,变量 num 的值最终为 25。
void change(int* p) {
    *p = 25;
}
int main() {
    int num = 10;
    change(&num);
    return 0;
}

{{ select(44) }}

  • 正确
  • 错误
  1. 执行下面代码后,输出结果为 5。
int main() {
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    cout << a[2][1] - a[1][2] << endl;
    return 0;
}

{{ select(45) }}

  • 正确
  • 错误
  1. 在 C++ 中,引用一旦绑定到某个变量后,就无法再重新绑定到其他变量。

{{ select(46) }}

  • 正确
  • 错误
  1. 在 C++ 中,值传递方式下,函数内部对形参的修改会影响外部实参的值。

{{ select(47) }}

  • 正确
  • 错误
  1. 在 C++ 中,结构体内部可以定义另一个结构体类型,并声明该类型的成员变量。

{{ select(48) }}

  • 正确
  • 错误
  1. 由于选择排序和插入排序的时间复杂度均为 O(n²),因此任何实际场景下两者的性能表现完全相同,可以互相替代。

{{ select(49) }}

  • 正确
  • 错误
  1. 下面程序能够将字符串 "CSP Exam" 写入到 exam.txt 文件中。
ofstream fout("exam.txt");
cout << "CSP Exam";
fout.close();

{{ select(50) }}

  • 正确
  • 错误