文章目录
- 一、选择题
- 二、编程题
一、选择题
和笔试强训1的知识点考的一样,因为输出的是double类型所以后缀为f,m.n对其30个字符所以m是30,精度是4所以n是4,不加符号默认是右对齐,左对齐的话前面加-号,所以答案是-30.4f,答案选c
- %s:就是字符串的转换说明符
- %ms:输出字符串宽度为m,如果字符串本身实际宽度大于m,那么就用字符串的实际宽度。如果字符串的实际宽度小于m,则左补空格。可以理解成m前面有个省略了的+号,所以字符串右对齐;
- %-ms:规则基本上面一样,不一样的是字符串左对齐,右补空格;
- %m.ns;输出宽度占m,但是只取字符串中左端的n个字符。这n个字符排列在m宽度的右侧,如果n小于m则左补空格,如果n大于m,那么m失效,字符的输出宽度就是n。
- %-m.ns;规则和上面基本一样,不一样的地方在于,如果n小于m那么需要左对齐,右补空格。
本题主要考察指针常量和常量指针的概念。可以通过观察const和*的位置来区分指针常量和常量指针
如果const在的左边比如:const int p或者int const p都表示常量指针
如果const在的右边比如:int* const p表示指针常量
对上述题目进行分析(1)是常量指针,不能修改它指向的数据,但能修改指向的地址。(2)也是常量指针,因为const在*的左边。(3)修改了p2的指向,常量指针可以修改指向。(4)是指针常量,不能修改指针的指向的地址,但可以修改指向的数据。(5)修改了指针常量p3指向的数据,没问题。(6)修改了常量指针p2指向的数据,错误。(7)修改了指针常量p3指向的地址,错误。
故(6)(7)错误,本题选C。
指针常量(Pointer to Constant)
指针常量指的是指针的值(即它所指向的地址)不能被修改,但是通过这个指针可以修改它所指向的数据。指针常量通常用const
关键字来修饰指针本身,而不是指针所指向的数据类型。
int a = 10;
int *const ptr = &a; // ptr 是一个指针常量,指向整数 a
// *ptr = 20; // 这是合法的,因为 ptr 指向的数据(a)是可以被修改的
// ptr = &b; // 这是非法的,因为 ptr 是一个指针常量,它的值(即它所指向的地址)不能被修改
常量指针(Constant Pointer)
常量指针指的是通过该指针不能修改它所指向的数据,但是指针的值(即它所指向的地址)是可以被修改的。常量指针通常用const
关键字来修饰指针所指向的数据类型,而不是指针本身。
int a = 10;
const int *ptr = &a; // ptr 是一个常量指针,指向整数 a
//该语句等价与下面这条语句,都表示常量指针
//int const *ptr = &a;
// ptr = &b; // 这是合法的,因为 ptr 的值(即它所指向的地址)是可以被修改的
// *ptr = 20; // 这是非法的,因为 ptr 是一个常量指针,不能通过它来修改它所指向的数据
两者结合
你也可以创建一个既是常量指针又是指针常量的指针,即它的值和它所指向的数据都不能被修改。这通过在指针声明中同时使用两个const
关键字来实现,一个修饰指针本身,另一个修饰指针所指向的数据类型。
int a = 10;
const int *const ptr = &a; // ptr 既是一个常量指针(不能通过它修改 a),也是一个指针常量(它的值不能被修改)
// ptr = &b; // 这是非法的
// *ptr = 20; // 这也是非法的
A选项:acX和acY是两个普通数组,数组的内容可以修改,A正确。
B选项:在C语言中,对于相同的字符串常量,编译器通常会优化内存使用,使得多个相同的字符串字面量(string literals)在程序中指向同一块内存区域。这意味着,如果代码中有两个或多个指向相同字符串字面量的指针,这些指针的值(即它们所指向的地址)是相同的。
C选项:acX是字符串,以’\0’结尾,故acX比acY多一个字符。
D选项:字面常量不可修改。
故D错误选D。
b=a,b指向数组首元素,b+=2,相当于把首元素加了个2变成了3,2,3,4.(b+2)=2,表示指针先向后偏移两个单位(两个int类型的字节数即8个字节)指向下标为2的内个元素(下标从0开始算),然后赋值成了2即变成了3,2,2,4.b++,即b指向下一个元素即下标为1的元素。打印b和(b+2)即打印下标为1和3的元素即2和4,故答案选C。
不正确的是B,说反了,要尽量使用const常量。
虽然宏定义在某些简单情况下可能看起来更直观,但const提供了更好的类型安全性、作用域控制、调试能力和内存保护。因此,在可以使用const的情况下,通常建议优先使用const。只有在需要定义非类型常量或进行复杂的文本替换时,才考虑使用宏定义。
类型匹配上,数组传参直接传数组名就好,答案是D。
A选项: 指针数组,放指针的数组,该题中A是一个放10个int类型指针的数组
B选项:数组指针,指向数组的指针,该题中B是一个指向一个存放10个int类型数组的指针
C选项:函数指针,指针a指向一个函数,这个函数接受一个int类型的参数,并返回一个 int 类型的值。
D选项:数组a包含10个元素,每个元素都是一个指向函数的指针,这些函数都接受一个 int 类型的参数,并返回一个 int 类型的值。
故选D。
第一个for循环里,先把字符通过字符转换成下标,然后将数组对于下标的元素++,第二个for循环输出每个字符出现的个数,选D。
4字节(32):19+11
4字节(32):4
4字节(32):29
1字节(8):
一共13个字节,但由于对齐得是4的整数倍所以大小为16
故选C
a是数组名,单纯一个a是数组首元素的地址,&a的话是数组的地址,虽然指向的位置和a指向的位置一样,但区别在进行±运算的时候移动的步长不一样。
&a+1移动的步长是一个数组大小,该数组大小为4个int即16个字节,指向数组最后一个元素的下一个元素。int*(&a+1)转换成int*类型的指针,这个时候进行±运算步长就会变成一个int即4个字节,ptr-1就是后移一个int单位指向的是最后一个元素,也就是4,所以选A。
二、编程题
题目链接:
排序子序列
提交代码:
#include<iostream>
#include<vector>
using namespace std;
int main() {
int n;
cin >> n;
// 注意这里多给了一个值,是处理越界的情况的比较,具体参考上面的解题思路
vector<int> a;
a.resize(n + 1);
//这里有个坑,这个题越界了牛客测不出来,给n,并且不写a[n] = 0;不会报错,但是最好写上
a[n] = 0;
//读入数组
int i = 0;
for (i = 0; i < n; ++i)
cin >> a[i];
i = 0;
int count = 0;
while (i < n) {
// 非递减子序列
if (a[i] < a[i + 1]) {
while (i < n && a[i] <= a[i + 1])
i++;
count++;
i++;
} else if (a[i] == a[i + 1]) {
i++;
} else { // 非递增子序列
while (i < n && a[i] >= a[i + 1])
i++;
count++;
i++;
}
}
cout << count << endl;
return 0;
}
运行结果:
题目链接:
倒置字符串
提交代码:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string s;
// 注意这里要使用getline,cin>>s遇到空格就接收结束了
getline(cin, s);
// 翻转整个句子
reverse(s.begin(), s.end());
// 翻转单词
auto start = s.begin();
while (start != s.end()) {
auto end = start;
while (end != s.end() && *end != ' ')
end++;
reverse(start, end);
if (end != s.end())
start = end + 1;
else
start = end;
}
cout << s << endl;
return 0;
}
运行结果: