单选
1.单选
以下程序的输出结果是()
#include <stdio.h>
main()
{
char a[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', 0};
char *p;
int i;
i = 8;
p = a + i;
printf("%s\n", p - 3);
}
A. 6
B. 6789
C. ‘6’
D. 789
解析
- 定义了一个字符数组,大小为10,并且进行了初始化
- 声明了一个char类型的指针变量,和一个int类型的一个整形变量i,i赋值为8
- p=a+i:a是一个数组名,也是一个指针常量,是指向数组首元素的,+i的话也就是+8,就是向后偏移8个指针类型的大小,指针类型是char,向后偏移8个字节,指针p指向字符9
- print是将从p-3的地址处,使用%s格式化打印,p变量是指向字符9的,p-3向前偏移3个指针类型大小,也就是从6开始向后进行%s打印,遇到\0才会停止打印
- 所以会将6789打印出来,遇到\0停止打印
- 选B
2.单选
以下程序的输出结果是()
#include <iostream.h>
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
解析
- x变量初始化为3,y变量也初始化为3
- switch语句:里面的表达式是x%2=1,进入case1语句
- 里面又是一个switch语句,表达式是y,y的值是3,不会进入case0和1语句,会进入default语句,输出hello,结束这个switch语句
- 因为case1没有break语句,所以不会跳出外层这个switch语句,继续向下执行,直到遇到第一个break语句,或者整个switch语句运行结束,跳出switch语句,所以会继续向下执行case2语句,输出third
- 结果是hellothird
- 选D
3.单选
以下能对二维数组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:二维数组在声明的时候,行可以省略,列不可以省略
B:省略了行,没有省略列,所以是正确答案
C:声明的是两行四列,但初始化的时候初始化了三行,每个大括号就是一行
D:初始化部分有问题,初始化的时候必须连续初始化,中间不能有间隔
- 选B
4.单选
把函数处理结果的二个数据返回给主调函数,在下面的方法中不正确的是()
A. return这二个数
B. 形参用数组
C. 形参用二个指针
D. 用二个全局变量
解析
A:return的时候每次只能return一个数据类型,两个数据是不能return的,除非放到一个数组或容器里面返回
B:用数组的话,在调用函数的时候,需要传递数组的地址,将函数处理的结果放在数组当中,函数调用完以后,可以通过访问数组来获取处理结果
C:两个指针,在调用函数的时候需要传入两个地址变量,将对应的处理结果放在地址的所指空间,在函数调用完以后,主调函数通过两个指针去访问所指空间的值
D:全局变量作用域在整个源文件都是有效的,在这个函数处理完以后,主调函数可以对全局变量进行访问,获取处理结果
- 选A
5.单选
int *p[4]
与选择项中的() 等价
A. int p[4]
B. int *p
C. int *(p[4])
D. int (*p)[4]
解析
int *p[4]
:方括号的运算优先级高于星号,p和方括号先结合,表示它是一个数组,数组里面存放的是int类型的指针,所以它是int类型的指针数组,数组大小为4
A:是一个整形数组,大小为4
B:是一个int类型的指针
C:p是和方括号先结合,表示它是一个数组,里面存放的是int类型的指针,符合题意
D:先和星号去结合,表示是一个指针,是一个数组指针,数组里面存放的是int类型,大小为4- 选C
6.单选
设变量已正确定义,以下不能统计出一行中输入字符个数(不包含回车符)的程序段是
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++);
解析
A:把n初始化为0,有个while循环,条件判断部分是用getchar获取一个字符,将字符赋值给ch变量,再和\n去比较,如果是\n就结束循环,如果不是\n则进行n++,也就是统计字符。第一个字符和\n去比较,不是就n++,直到遇到\n结束循环,此时n的值就是字符的个数
B:没有将getchar获取的值赋给ch,而是直接和\n进行比较,也是可以的
C:用的for循环,初始化部分,n初始化为0,条件判断部分,getchar获取一个字符和\n进行比较,如果不等于\n,则进行循环操作,循环操作完了以后n++,也就是说,当不等于\n,则n++,若等于\n,则结束循环
D:在for循环外面初始化n为0,for循环的初始化部分获取一个字符,for循环的初始化部分只会进行一次,所以for循环只会获取一次字符,不可能去遍历每个字符,去统计,所以不符合题意
- 选D
7.单选
以下代码
char *ptr;
char myString[] = "abcdefg";
ptr = myString;
ptr += 5;
代码执行之后ptr指向的内容是?
A. Compiler error
B. f
C. efg
D. defg
解析
- 声明了一个char类型的指针变量ptr,还有一个指针数组,使用字符串初始化,
- ptr初始化,指向数组的地址,数组首元素的地址指向a,
- ptr+=5,向后偏移5个类型大小,因为是char类型,向后偏移5个字节,指向f,因为是char类型的,指向f这个字母
- 选B
8.单选
下面3段程序代码的效果一样吗()
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修饰的指针变量,
- 常量指针,所指空间的值是一个常量,不能发生改变,不能通过指针解引用修改指针所指空间的值,但是指针的指向可以发生改变
- 指针常量,指针是一个常量,不能改变指针的指向,但是可以指针解引用改变所指空间的值
- 区分const和星号运算符的相对位置,const在
*
左边就是常量指针,否则就是指针常量
- const修饰的是int,并且在星号左边,是一个常量指针,
- const同样在星号左边,是一个常量指针
- const在星号右边,是一个指针常量
1和2效果是一样的
- 选C
9.单选
32位系统中,定义**a[3][4]
,则变量占用内存空间为()。
A. 4
B. 48
C. 192
D. 12
解析
32位系统,
**a[3][4]
:方括号的运算符高于星号,a先和方括号进行结合,表示它是一个数组,是一个3行4列的二维数组,存放的是指针类型,- 3行4列有12个元素,指针类型在32位系统中,每一个指针占4个字节,总共是4
*
12=48个字节 - 选B
10.单选
假设在一个 32 位 little endian 的机器上运行下面的程序,结果是多少?
#include <stdio.h>
int main()
{
long long a = 1, b = 2, c = 3;
printf("%d %d %d\n", a, b, c);
return 0;
}
A. 1,2,3
B. 1,0,2
C. 1,3,2
D. 3,2,1
解析
大小端
- 大端是低位存高地址
- 小端是低位存低地址
int i= 1; - 从左到右是从低地址向高地址增长
大端:00 00 00 01
小端:01 00 00 00
long long类型占8个字节,将a,b,c三个变量的地址写出来
a:01 00 00 00 00 00 00 00
b:02 00 00 00 00 00 00 00
c:03 00 00 00 00 00 00 00
通过printf函数去打印这三个变量的值,
printf是一个库函数,在调用函数的时候,会创建一个函数栈帧,因为是栈,是从高地址向低地址增长,先从高地址开始开辟空间,往低地址去延伸,并且这个函数在调用的时候变量是从右往左入栈的,也就是c,b,a的顺序
先将c变量入函数调用栈
//低地址 <<<<--------------------------------- 高地址
01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00
- 三个变量入栈以后,再进行打印,是%d进行打印的,每次获取4个字节内存的数据,采用10进制整数的形式打印,
- 栈是一个先进后出的容器,最后入的最先出,先打印a变量,会从内存中获取四个字节的数据进行打印,也就是01 00 00 00,作为a的值打印出来,再向后找00 00 00 00打印b的值,依次找四个字节,02 00 00 00来打印c,
- 转换为10进制,就是1,0,2
- 选B
编程
1. 编程题
字符串中找出连续最长的数字串_牛客题霸_牛客网 (nowcoder.com)
知识点
字符串 贪心 模拟
题目
- 描述
读入一个字符串str,输出字符串str中的连续最长的数字串 - 输入描述:
个测试输入包含1个测试用例,一个字符串str,长度不超过255。 - 输出描述:
在一行内输出str中里连续最长的数字串。 - 示例1
输入:
abcd12345ed125ss123456789
输出:
123456789 -
思路
- 给一个例子ab12a 1a 456e,连续最长的应该是456
- 分别定义cur和ret两个字符串,
- i从字符串0下标开始去往后遍历,如果i在走的过程当中,i下标是一个数字字符,就把它放到cur字符串中;如果不是就继续往后遍历
- 此时将1和2放入cur字符串中
- 再往后走发现a是非数字字符,此时cur里面存放的是12,
- ret用来存放结果,cur存起来的和ret去比较,去比较size(),如果cur比ret的size大,此时ret是0,cur是2,就把cur的内容拷贝到ret里
- 下一个数字串是1,把1放到cur里,再往下走遇到a,将cur的size和ret的size相比较,cur小于ret就把cur的内容清掉,
cur.clear()
- 以此类推往后走,遇到456放入cur,遇到e,cur的size比ret大,将cur的内容拷贝覆盖到ret里
- ret里一直存放的是最长的,直到i遇到\0结束,此时ret里存放的就是所要求的结果
代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str, cur, ret;
// 获取用户输入的字符串
cin >> str;
//通过i来遍历当前的字符串,i的范围是从0到字符串的长度(包括字符串末尾的'\0')
for (int i = 0; i <= str.length(); i++)
{
//判定遍历的字符是否是数字
if (str[i] >= '0' && str[i] <= '9')
{
// 如果是数字字符,则将其添加到当前数字串cur中
cur += str[i];
}
// 如果遇到的字符不是数字字符,则进行以下操作:
// 如果当前数字串cur的长度大于之前记录的最长数字串ret的长度,则更新ret为cur
else
{
if (ret.size() < cur.size())
{
ret = cur;
}
else
{
// 否则清空当前数字串cur,以便记录下一个数字串
cur.clear();
}
}
}
// 输出最长的数字串
cour << ret << endl;
}
注意
for (int i = 0; i <= str.length(); i++)
- 这里的i必须是<=str.length,当\0前面一位是数字而不是字母时,如ab12a 1a 456,当i遍历到6时,cur里是45,i=length-1,<length,进入到if循环里,将6也拼接到cur中,再进行i++,到\0,i=str.length,这时不进入循环,最长的应该是456,但cur并没有拷贝覆盖到ret里
- 当i=\0时,\0不是大于0小于9的数字,斜杠0和字符0不一样,if进不去,走else,会判断ret和cur的size,ret比cur小,将cur的内容拷贝覆盖到ret里,走完这次循环,i++,超出length范围,循环结束,此时ret存放的是最长的
2. 编程题
数组中出现次数超过一半的数字_牛客题霸_牛客网 (nowcoder.com)
技能
数组 哈希
题目
- 描述
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]
。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。 - 数据范围:n≤50000,数组中元素的值 0≤val≤10000
- 要求:空间复杂度:O(1),时间复杂度 O(n)
- 输入描述:
保证数组输入非空,且保证有解
示例1
输入:
[1,2,3,2,2,2,5,4,2]
返回值:
2
示例2
输入:
[3,3,3,3,2,2,2]
返回值:
3
示例3
输入:
[1]
返回值:
1
思路一
- 输入一个数组,里面的数字是无序的,12322
- 对整体进行排序,12223,发现数组中间的数字是2,并且是出现次数超过一半的数字
- 找到中间的数字,x,
2 - 再次遍历这个数组,看x出现了多少次,是否大于数组长度的一半
发现2出现了3次,超过了数组长度的一半,
如果大于找到答案
思路二
把出现次数超过数组一半的数字称为众数,其他数字称为非众数
如果两个数不相等,就消去这两个数
最坏的情况下,每次消去一个众数和一个非众数,如果存在众数,最后留下的数肯定是众数
- 分别定义两个变量,一个是result(最终结果),一个是times(出现次数),用i来进行遍历,对于1来说,出现了依次,i从数组的第二个位置开始,判断当前数字和前面的数字是否相同,相同就让times++,不相同让times–,
- i从1下标开始,进入循环以后需要将times分为等于0和不等于0两种情况
如果times不等于0
这个数是1,和下标0的数字相同,times++
这个数是2,和下标0的数字不相同,times–,把众数和非众数消掉
如果times等于0
把这个数赋给result,times置为1 - 此时result=3,times=0
- i走到2,因为times!=0,2!=3,所以times=0
- 下一个还是2,把这个数赋给result,此时result=2,times=1
- 再往后走,i超过数组的长度,此时result最终存的数字2,就是众数
最后拿到2之后,判断2到底是不是众数
如果最后一个数是1的话,虽然result存的是1,但是1不是众数
如果这组数字里面没有众数,最后存住的数字就不是众数
如果存在众数,最后留下的数字一定是众数 - 最后遍历依次数组,看最后留的数字出现的次数是不是超过数组长度的一半
代码
思路一
class Solution {
public:
// MoreThanHalfNum_Solution 函数用于找出给定数组中出现次数超过一半的元素
int MoreThanHalfNum_Solution(vector<int>& numbers) {
// 如果数组为空,则直接返回0
if(numbers.empty())
return 0;
// 对数组进行排序,以便找到中间位置的元素
sort(numbers.begin(), numbers.end());
// 获取中间位置的元素作为候选元素
int midNum = numbers[numbers.size()/2];
// 统计候选元素在数组中出现的次数
int count = 0;
for(int i = 0; i < numbers.size(); i++)
{
// 如果当前元素与候选元素相等,则计数器加一
if (midNum == numbers[i])
{
count++;
}
}
// 如果候选元素出现的次数超过数组长度的一半,则返回候选元素,否则返回0
if (count > number.size()/2)
{
return midNum;
}
return 0;
}
};
这段代码是一个类 Solution
中的一个成员函数MoreThanHalfNum_Solution
,用于找出给定的整数数组中出现次数超过数组长度一半的元素。它采用了排序和计数的方法来实现:首先对数组进行排序,然后找到排序后中间位置的元素作为候选元素,最后遍历数组统计候选元素的出现次数,如果超过了数组长度的一半,则返回该候选元素,否则返回0。
思路二
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int>& numbers) {
// 如果数组为空,则直接返回0
if(numbers.empty())
return 0;
// 初始化候选元素为数组的第一个元素,并初始化计数器为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++;
}
}
// 如果候选元素出现的次数超过数组长度的一半,则返回候选元素,否则返回0
if (times > numbers.size()/2)
{
return result;
}
return 0;
}
};