2024届 C++ 刷题 笔试强训 Day 03

选择题

01

以下程序的输出结果是()

cpp 复制代码
#include <stdio.h>
void main()
{
    char a[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', 0}, *p;
    int i;
    i = 8;
    p = a + i;
    printf("%s\n", p - 3);
}

A 6

B 6789

C '6'

D 789


题目解析:

  • 题目中定义了一个字符数组和字符类型的指针 p。数组名 a 表示数组首元素地址,p = a + 8 说明 p 指向的是数组中下标为 8 的元素。
  • 以字符串的形式打印 p-3 地址为起始的内容。首先 p - 3 指向的是下标为 5 的元素,也就是 6;以字符串的形式打印,知道遇到 \0 才会停止,字符 \0 对应的 ASCII 码就是 0 哈!

答案:B


知识点总结:

  • 数组名代表数组首元素的地址。但在 &数组名 以及 sizeof 数组名 的时候,数组名表示的是整个数组。
  • %s 的形式打印,会向后打印字符,直到遇到 \0

02

以下程序的输出结果是()

cpp 复制代码
#include <iostream>
using namespace std;
int main()
{
    int x = 3, y = 3;
    switch (x % 2)
    {
    case 1:
        switch (y)
        {
        case 0:
            cout << "first";
        case 1:
            cout << "second";
            break;
        default:
            cout << "hello";
        }
    case 2:
        cout << "third";
    }

    return 0;
}

A second third

B hello

C first second

D hellothird


题目解析:

  • 首先进入第一层 switchx % 2 的值为 1,进入 case 1:;y 的值为 3 进入 default 此时会输出 hello
  • 执行完 case 1 之后,我们发现并没有 break 语句,那么就会进入 case 2 继续执行,然后输出 third

答案:D


知识点总结:

  • 理解 switch 语句的执行原理:

    switch语句中的表达式与某个case标签的值匹配时,程序会执行该case下的代码。如果在这个case的代码块中没有遇到break语句,那么程序会继续执行下一个case的代码块,这种行为称为"贯穿"。

    这个过程会一直持续下去,直到遇到break语句或者执行完所有的case。如果在switch语句的末尾有一个default标签,且之前没有遇到break语句,那么程序还会执行default标签下的代码。

03

以下能对二维数组a进行正确初始化的语句是()

A int ta[2][]={{0,1,2},{3,4,5}};

B int ta[][3]={{0,1,2},{3,4,5}};

C int ta[2][4]={{0,1,2},{3,4},{5}};

D int ta[][3]={{0,2},{},{3,4,5}};


题目解析:

  • A:定义二维数组的时候,行数可以不指定,当时列数必须指定。A 错误。

  • B:定义二维数组,行数可以不指定,B 选项中只初始化了两行数据,那么 ta 变量实际上就是:ta[2][3]。当不指定行数会根据你的初始化推导。

    因此,如果不指定行数,就必须在定义的时候初始化数组,不然编译器没法给你的数组开辟空间,就会报错。B 正确

  • C:这个选项显然是错误的,二维数组定义了两行,却初始化了三行的数据,越界访问。

  • D:初始化第一行的时候 {0,,2} 试图跳过一个元素的初始化也是不合法的。D 错误。

答案:B


知识点总结:

  • 二维数组定义的时候可以不指定行数。如果不指定行数就必须显示初始化。
  • 二维数组定义的时候不可以不指定列数。
  • 数组部分初始化元素时,未显示初始化的部分会补零。

04

能把函数处理结果的二个数据返回给主调函数,在下面的方法中不正确的是()

A return这二个数

B 形参用数组

C 形参用二个指针

D 用二个全局变量


题目解析:

  • return 返回的话,只能返回一个数哈,显然不能返回函数中的两个数据。

答案:A


知识点总结:

将函数内的局部变量带出函数的作用域的方法:

  1. 形参使用数组。因为数组就是传递地址的嘛,就类似指针的效果。因此形参使用数组和使用指针是相同的效果。
  2. 全局变量。全局变量自然不用说,因为他的作用域是在全局和声明周期是随进程的,能够轻易做到。
  3. 通过返回值。通过返回值也能将函数内部的数据带出来,如果需要返回多个数据,可以使用结构体。但是返回值的本质其实是拷贝嘛,效率自然没有指针高,因此,更加推荐使用指针哈!

05

int *p[4] 与选择项中的() 等价

A int p[4]

B int *p

C int *(p[4])

D int (*p)[4]


题目解析:

首先题目表示的是指针数组哈!指针的类型是 int

  • A:选项 A 表示的是一个 int 类型的数组。
  • B:选项 B 表示的是一个 int 类型的指针。
  • C:选项 C 和题目是一个意思哈,这个括号加不加一个效果。
  • D:选项 D 表示的是一个数组指针哈,该指针指向的数组是:有四个元素的 int 类型的数组。

知识点总结:

熟练掌握各种类型指针的书写方法。

  1. 普通指针:指向特定数据类型的指针。例如,int *ptr; 定义了一个指向整数的指针。
  2. 空指针:不指向任何地方的指针。例如,int *ptr = NULL; 将指针设置为 NULL。
  3. 野指针:指向未知内存地址的指针,应尽量避免使用。例如,未初始化的指针。
  4. 指向指针的指针:也称为二级指针。例如,int **ptr; 定义了一个指向整型指针的指针。
  5. 指针数组:一个数组,其中的每个元素都是指针。例如,int *ptrArray[5]; 定义了一个包含5个整型指针的数组。
  6. 数组指针:指向数组的指针。例如,int (*ptr)[5]; 定义了一个指向包含5个整数的数组的指针。
  7. 函数指针:指向函数的指针。例如,int (*funcPtr)(int, int); 定义了一个指向接受两个整数参数并返回整数的函数的指针。
  8. 常量指针:指针指向的值不能被修改。例如,const int *ptr; 定义了一个指向整数常量的指针。
  9. 指针常量:指针本身的值不能被修改。例如,int *const ptr; 定义了一个指向整数的常量指针

06

设变量已正确定义,以下不能统计出一行中输入字符个数(不包含回车符)的程序段是()

A n=0;while(ch=getchar()!='\n')n++;

B n=0;while(getchar()!='\n')n++;

C for(n=0;getchar()!='\n';n++);

D n=0;for(ch=getchar();ch!='\n';n++);


题目解析:

D:在 for 循环中,第一个分号前面的表示循环条件的初始化,也就是说,D 选项仅仅会输入一次!如果这次输入的字符不是 \n 循条件就会一直判断成立,从而陷入死循环。

答案:D


知识点总结:

  • getchar 函数用于向标准输入读取一个字符,返回值是读到字符的 ASCII 码。

07

以下代码

cpp 复制代码
char *ptr;
char myString[] = "abcdefg";
ptr = myString;
ptr += 5;

代码执行之后ptr指向的内容是?

A Compiler error

B fg

C efg

D defg


题目解析:

第一行定义了一个 char* 的指针变量 ptr。第二行定义了一个字符数组。第三行将数组赋值给 ptr 这个指针变量。第四行将 ptr += 5 那么 ptr 将指向字符数组下标为 5 的元素。因为 ptr 本身是一个字符指针,结合题目选项,他应该指向的是一个字符串,因此就是 fg

答案:B


知识点总结:

  • 使用字符串常量初始化一个字符数组,其实就是将字符串常量中的每个字符拷贝到栈空间,然后用来初始化定义的数组。在本题中数组的等价定义为:char myString[8] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', '\0'};
  • 字符串在 C/C++ 中以字符 \0 结尾。

08

下面3段程序代码的效果一样吗()

cpp 复制代码
int b;
(1)const int *a = &b;
(2)int const *a = &b;
(3)int *const a = &b;

A (2)=(3)

B (1)=(3)

C (1)=(2)

D 都不一样


题目解析:

const 修饰指针变量无非三种情况:

  1. 指针变量本身不可改变。例如:int * const a
  2. 指针变量指向的内容不可以改变。例如:const int* a 或者 const int *a
  3. 指针变量本身和指向的内容都不可以改变。例如:const int * const a

答案:C


知识点总结:

  • 看是哪种情况其实只要看 const* 的左边还是在 * 的右边哈!
  • 如果 const 在 * 的左边,那么就是指针指向的内容不可变。
  • 如果 const 在 * 的右边,那么就是指针本身不可以改变。

09

32位系统中,定义int **a[3][4],则变量占用内存空间为()

A 4

B 48

C 192

D 12


题目解析:

32 位系统下,指针变量是 4 个字节。a 数组一共是 12 个元素,因此总大小就是 48 个字节。

答案:B


知识点总结:

  • 在32位系统中,指针变量的大小为 4 字节,这主要是因为 32 位系统的地址总线宽度为32位。地址总线负责在CPU与内存之间传递地址信息,其宽度决定了CPU可以寻址的最大内存范围。

    在32位系统中,地址总线的32位可以表示2^32个不同的地址,即最多可以寻址4GB的内存。由于每个地址都需要一个唯一的标识,因此需要一个足够大的空间来存储这些地址。在大多数情况下,一个字节(Byte)由8位(bit)组成,所以32位需要4个字节(4 * 8 = 32)来存储。

  • 可以看到,指针变量的大小与是什么类型的指针是没有关系的。与系统有关。

编程题

01

原题链接:`https://www.nowcoder.com/practice/bd891093881d4ddf9e56e7cc8416562d?tpId=85\&\&tqId=29864\&rp=1\&ru=/activity/oj\&qru=/ta/2017test/question-ranking)

题目描述:

读入一个字符串str,输出字符串str中的连续最长的数字串。


解题思路:

遍历字符串,使用cur去记录连续的数字串,如果遇到不是数字字符,则表示一个连续的数字串结束了,则将数字串跟之前的数字串比较,如果更长,则更新更长的数字串更新到res。

可以用双指针,但是没必要!因为题目的数据范围很小。


完整代码:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
    string str, res, cur;
    cin >> str;
    for (int i = 0; i <= str.length(); i++)
    {
        // 数字+=到cur
        if (str[i] >= '0' && str[i] <= '9')
        {
            cur += str[i];
        }
        else
        {
            // 找出更长的字符串,则更新字符串
            if (res.size() < cur.size())
                res = cur;
            else
                cur.clear();
        }
    }
    cout << res;
    return 0;
}

02

原题链接:https://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163?tpId=13&tqId=11181&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述:

给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。

例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

数据范围: n ≤ 50000 n≤50000 n≤50000,数组中元素的值 0 ≤ v a l ≤ 10000 0≤val≤10000 0≤val≤10000

要求:空间复杂度: O ( 1 ) O(1) O(1),时间复杂度: O ( n ) O(n) O(n)


题目解析:

  • 思路一:数组排序后,如果符合条件的数存在,则一定是数组中间那个数。这种方法虽然容易理解,但由于涉及到快排sort,其时间复杂度为O(NlogN)并非最优;

  • 思路二:众数:就是出现次数超过数组长度一半的那个数字。如果两个数不相等,就消去这两个数,最坏情况下,每次消去一个众数和一个非众数,那么如果存在众数,最后留下的数肯定是众数。

我们这里只写第二种思路的代码哈:


完整代码:

cpp 复制代码
class Solution
{
public:
    int MoreThanHalfNum_Solution(vector<int> numbers)
    {
        if (numbers.empty())
            return 0;
        // 遍历每个元素,并记录次数;若与前一个元素相同,则次数加1,否则次数减1
        int result = numbers[0];
        int times = 1; // 次数
        for (int i = 1; i < numbers.size(); ++i)
        {
            if (times != 0)
            {
                if (numbers[i] == result)
                {
                    ++times;
                }
                else
                {
                    --times;
                }
            }
            else
            {
                result = numbers[i];
                times = 1;
            }
        }
        // 判断result是否符合条件,即出现次数大于数组长度的一半times = 0;
        for (int i = 0; i < numbers.size(); ++i)
        {
            if (numbers[i] == result)
                ++times;
        }
        return (times > numbers.size() / 2) ? result : 0;
    }
};
相关推荐
ELI_He999几秒前
PHP中替换某个包或某个类
开发语言·php
Lenyiin1 分钟前
01.02、判定是否互为字符重排
算法·leetcode
小林熬夜学编程5 分钟前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
m0_748236118 分钟前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
倔强的石头10616 分钟前
【C++指南】类和对象(九):内部类
开发语言·c++
鸽鸽程序猿16 分钟前
【算法】【优选算法】宽搜(BFS)中队列的使用
算法·宽度优先·队列
Jackey_Song_Odd17 分钟前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
Watermelo61720 分钟前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
乐之者v26 分钟前
leetCode43.字符串相乘
java·数据结构·算法
A懿轩A1 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组