【C++笔试强训】第三天

文章讨论了C++中的数组、指针和字符串的基本概念和操作,包括字符数组的末尾0、switchcase语句的执行流程、二维数组的初始化、返回值限制、指针数组的理解,以及如何处理字符串中的连续数字串。此外,还介绍了查找数组中出现次数超过一半的数字的方法,包括排序和众数的概念。
摘要由CSDN通过智能技术生成

选择题

image-20230324182546232

解析:字符数组里面的最后一个字符是0,说明里面本身就是一个字符串——"123456789",数组名表示数组首元素的地址,那么p = a + i指向的就是字符数组中元素'9',那么p - 3就是指向元素'6'的地址,%s打印的是字符串,所以从'6'开始向后打印。

解析:本题考查switch和case语句,如果在switchcase语句中没有遇见break,就默认往下继续执行。x%2为1,指向case 1y=3,执行case 3,但是没有就执行defalut,此时输出hello,没有遇见break,继续执行case 2,打印third。即选D。

image-20230324200144123

解析:对于二维数组,可以不指定具体行,但是必须指定具体列,行可以根据初始化自动判断,A选项中没有指定具体的列;C选项,初始化的行数超过预定的值;D选项中两个,之间的{}中没有数,这是语法错误。所以选B。

image-20230324200415032

解析:return只能返回一个值。

image-20230324201417607

解析:本题主要考查指针数组。p先和[]结合,所以选C。A是整形数组;B是指针;C是整形指针数组,存放整型指针的数组;D是数组指针,指向数组的指针,存放数组的地址,p是数组指针变量。

image-20230324201449853

解析:D中ch = getchar()是初始条件,不是判断条件,第一次输入之后ch的值就不会发生改变了,陷入死循环。

image-20230324201500051

解析:数组名是数组首元素的地址,ptr = myString表示ptr指向数组首元素的地址;ptr += 5表示ptr向后移动5个字节,即指向f的地址。所以选B。

image-20230324201516417

解析:考查的constday01中有讲过。(1)中const修饰的是*a,表示的是常量指针;(2)中const修饰的也是*a,也表示常量指针;(3)中const修饰的是a,表示的是指针常量。所以选C。

image-20230324201552909

解析:数组里面有12个元素,每个元素都是指针类型,在32位系统中,指针的大小是4个字节的大小。所以占48个字节的大小。

image-20230324201610799

解析:本题考查小端存储

小端字节序存储:数据的低位保存在内存的低地址中,数据的高位保存在内存的高地址中。

大端字节序存储:数据的高位保存在内存的低地址中,数据的低位保存在内存的高地址中。

long long类型在内存中占8个字节,而输出的时候是以%d形式,也就是输出的时候读取4个字节,见下图:

image-20230324205529253

编程题

1.字符串中找出连续最长的数字串

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JG9rFG7C-1680404974946)(https://raw.githubusercontent.com/Niu-Max/typora/main/img/image-20230322171136537.png)]

解析:答案解析和这个一样。设置两个string类s2,s3专门用来存放s1中的数字串,刚开始的时候s2和s3的size都为0,所以第一次遇到数字串直接放入s2中,然后将s2的数字串赋值给s3,再清空s2;当下次遇到数字串时还放入s2中,拿s2的size大小和s3比较,如果比之前的数字串大则赋值给s3新的数字串,如果没有之前的数字串大则直接将s2清空,等待下次重新存放数字串再进行比较。当s1字符串结尾部分为数字串最大时,此时已经跳出循环,还要单独进行一次比较。

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s1;
    cin >> s1;//一个字符串不包含空格所以不用使用getline函数
    string s2;
    string s3;
    for (int i = 0; i < s1.size(); i++)
    {
        if (s1[i] >= '0' && s1[i] <= '9')//如果是数字就加进去
            s2 += s1[i];
        else {//不是数字的时候比较size大小
            if (s2.size() > s3.size()) //当新数字串大时,将其赋给s3
                s3 = s2;
            else
                s2.clear(); //新数字串小时,清空
        }
    }
    if (s2.size() > s3.size())//可能字符串结尾部分的数字串最大,所以还要再次进行比较
        s3 = s2;
    else
        s2.clear();
    cout << s3;//每次都赋值给s3,所以直接输出s3就可以
    return 0;
}

自己写的存在一些问题

1.为什么结束条件用it!=s1.end()不能判断?

2.怎么判断是否需要在最后加上数字?

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s1;
    getline(cin, s1);//输入字符串
    string s2;//记录数字字符串
    string s3;//记录数字字符串
    int count = 0;//用来记录,当新的数字串比s2的size大时,将新的数字串尾插到s3中
    int flag = 0;//用来记录是否需要在最后将s1字符串尾插到较长数字串中
    int flag1 = 0;//记录当flag1 = 0时将连续数字串尾插到s2中,当flag=1时,不对s2做处理
	string::iterator it = s1.begin();//迭代器
    while (it != s1.end())//循环的控制条件
    {
        count = 0;
        string::iterator it1 = it;//记录下次从哪里开始对s3进行尾插
        
        //当*it为数字时进入循环,注意这里的条件不能设置为it != s1.end(),会报错,具体原因未知,所以设置为it != s1.end()-1 ,在后面再对最后一个字符进行处理
        while (it != s1.end()-1  && (*it >= '0' && *it <= '9')) 
        {
            count++;
            if (flag1 == 0) //第一次对s2进行处理
                s2.push_back(*it); //尾插
            it++; //向后进行处理
        }
        if (s2.size() > 0) //当对s2进行处理之后,flag1 = 1
            flag1 = 1;
        
        //?那假如s3已经有数字串,且比s2大,那么每次都将覆盖上次s3的数字,所以最好加上it - it1 > s3.size(),但是加上之后就不能根据flag =1 判断最后是不是要加字符串中最后一个数字,所以此处有bug
        if(count > s2.size()  ) //判断当count大于s2.size()时,将数字串插入s3
        {
            s3.clear();//每次对s3处理之前将s3中之前的内容清空
            while (count > 0) {
                s3.push_back(*it1); //从it1记录的地方开始插入
                count--; //一共插入count个数据
                it1++;
            }
            //abcd12345ed125ss123 中当s2为12345时,如果不在最后加一个条件判断是否需要将最后一个数字字符加上,会出现结果为123453的情况,而当设置了一个flag条件时,当flag不满足条件时,不需要将最后一个数字字符加上。
            flag = 1;//当对s3处理说明有比s2更长的数字串,且在s2数字串的后面
            
        }
        it++;//向后判断
    }
    if (s2.size() > s3.size()) { //判断谁大
        if ((*(it - 1) >= '0' && *(it - 1) <= '9') && flag == 1 ) { //判断是否需要加上最后一个数字
            s2.push_back(*(it - 1));
        }
        cout << s2;
    }
    else {
        if (*(it - 1) >= '0' && *(it - 1) <= '9' && flag == 1) {
            s3.push_back(*(it - 1));
        }
    cout << s3;
    }
    return 0;
}

2.数组中出现次数超过一半的数字

image-20230322204519522

解析:要找出在数组中出现次数超过数组长度的一半,那么利用sort函数将数组排序后中间的数据就是要找的数据,我们再对数组进行遍历确认是否超过数组长度一半。时间复杂度O(NlgN)并非最优。

#include <vector>
class Solution {
public:
    int MoreThanHalfNum_Solution(vector<int> numbers) {
        sort(numbers.begin(),numbers.end());//先排序
        int num = numbers[numbers.size()/2];//得到中间数据
        int count = 0;
        for(int i = 0; i < numbers.size(); i++) //对数组进行遍历
        {
            if(numbers[i] == num)
            {
                count++;//统计num出现次数
            }
        }
        if(count > numbers.size()/2)//确认是否超过一半
            return num;
        return 0;
    }
};

答案解析:一种和上面一样,另一种就是这个。

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

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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不 良

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值