CCF编程能力等级认证GESP—C++3级—20240316
单选题(每题 2 分,共 30 分)
1、整数-5的16位补码表示是( )。
A. 1005
B. 1006
C. FFFA
D. FFFB
正确答案:D
| 编码 | -5 |
|---|---|
| 原码 | 1000 0000 0000 0101 |
| 反码 | 1111 1111 1111 1010 |
| 补码 | 1111 1111 1111 1011 |
| 十六进制 | F F F B |
2、如果16位短整数 -2 的二进制是"FFFE",则短整数 -4 的十六进制是( )。
A. FF04
B. FFFA
C. FFFC
D. FFFH
正确答案:C
| 编码 | -2 | -4 |
|---|---|---|
| 原码 | 1000 0000 0000 0010 | 1000 0000 0000 0100 |
| 反码 | 1111 1111 1111 1101 | 1111 1111 1111 1011 |
| 补码 | 1111 1111 1111 1110 | 1111 1111 1111 1100 |
| 十六进制 | F F F E | F F F C |
3、下面C++代码执行后的输出是( )。
int main(){
cout << (3|16) << endl;
cout << endl;
return 0;
}
A. 3
B. 16
C. 19
D. 48
正确答案:C
| 十进制数 | 二进制数 |
|---|---|
| 3 | 0011 |
| 16 | 1 0000 |
| 3 | 16 | 1 0011 |
4、定义整数 int x=-5 ,则执行C++代码 cout << (x == (x<<1>>1)) 输出是( )。
A. 0
B. 1
C. -5
D. 5
正确答案:B
1.x << 1:将整数x的二进制表示向左移动1位。对于x = -5(在16位补码表示下为1111 1011),左移1位后变为1111 1110。
2.(x << 1) >> 1:接着,将上一步的结果向右移动1位。1111 1110右移1位后变为1111 1011,这仍然是-5的16位补码表示。
3.然后,表达式x == (x << 1 >> 1)比较x和(x << 1 >> 1)是否相等。由于两者都表示-5,所以这个比较的结果是true。
在C++中,cout << true会输出1,而cout << false会输出0。因此,执行cout << (x == (x << 1 >> 1))会输出1。
5、已知字符 ‘0’ 的ASCII编码的十进制表示为48,则执行下面C++代码后,输出是( )。
int main(){
string s = "316";
int n = s.length();
int x = 0;
for(int i = 0; i < n; i++)
x += s[i];
cout << x << endl;
cout << endl;
return 0;
}
A. 10
B. 58
C. 154
D. 316
正确答案:C
在C++中,字符串中的字符实际上是字符的ASCII编码值。当我们将字符串中的字符相加时,实际上是将它们的ASCII编码值相加。
给定的字符串 s = "316" 包含三个字符:'3', '1', 和 '6'。这些字符的ASCII编码值分别是:
'3' 的ASCII编码值是 51(十进制)
'1' 的ASCII编码值是 49(十进制)
'6' 的ASCII编码值是 54(十进制)
代码中的循环将这些ASCII编码值相加:x += s[i];
因此,x 的最终值是:
x = 51 (3的ASCII值) + 49 (1的ASCII值) + 54 (6的ASCII值) = 154
所以,程序输出 x 的值,即 154。
6、下面C++代码执行后数组中大于0的数的特征是( )。
int main(){
int a[20],i;
for(i = 0; i < 20; i++)
a[i] = i + 1;
for(int i = 0; i < 20; i++)
if((a[i] % 2) && (a[i] % 3))
a[i] = 0;
for(i = 0; i < 20; i++)
if(a[i])
cout << a[i] << " ";
cout << endl;
return 0;
}
A. 2的倍数
B. 3的倍数
C. 能被2或3整除的数
D. 能被2和3同时整除的数
正确答案:C
a[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
| i | a[i] % 2 | a[i] % 3 | a[i] % 2 && a[i] % 3 | a[i] |
|---|---|---|---|---|
| 0 | 1 | 1 | true | 0 |
| 1 | 0 | 2 | false | 2 |
| 2 | 1 | 0 | false | 3 |
| 3 | 0 | 1 | false | 4 |
| 4 | 1 | 2 | true | 0 |
| 5 | 0 | 0 | false | 6 |
| 6 | 1 | 1 | true | 0 |
| 7 | 0 | 2 | false | 8 |
| 8 | 1 | 0 | false | 9 |
| 9 | 0 | 1 | false | 10 |
| 10 | 1 | 2 | true | 0 |
| 11 | 0 | 0 | false | 12 |
| 12 | 1 | 1 | true | 0 |
| 13 | 0 | 2 | false | 14 |
| 14 | 1 | 0 | false | 15 |
| 15 | 0 | 1 | false | 16 |
| 16 | 1 | 2 | true | 0 |
| 17 | 0 | 0 | false | 18 |
| 18 | 1 | 1 | true | 0 |
| 19 | 0 | 2 | false | 20 |
7、执行下面C++代码后输出的第一个数是( )。
int main(){
int a[20],i;
for(i = 0; i < 20; i++)
a[i] = i + 1;
for(; i > 0; i--)
cout << a[i - 1] << " ";
cout << endl;
return 0;
}
A. 20
B. 19
C. 1
D. 不确定
正确答案:A
1.第一个循环将数组a的每个元素初始化为它的索引值加1。因此,数组a的元素将按顺序包含值1到20。
2.第二个循环从i的当前值(在第一个循环结束后,i的值是20)开始,并在i大于0的条件下继续执行。在每次迭代中,它输出数组a中索引为i - 1的元素的值,并将i减1。
由于i的初始值是20,第一次迭代将输出a[19]的值,即20。接下来的迭代将依次输出19、18、…、1。因此,输出的第一个数是20。
8、在下列代码的横线处填写( ),可以使得输出是 GESP IS INTERESTING 。
int main(){
string str = "gEsP is Interesting";
int x = str.length();
for(int i = 0; i < x; i++)
if ((str[i] >= 'a') && (str[i] <= 'z'))
________________________;
cout << str << endl;
cout << endl;
return 0;
}
A. str[i] += 'a' - 'A'
B. str[i] += 20
C. str[i] += 'A' - 'a'
D. 无法实现
正确答案:C
为了将字符串str中的所有小写字母转换为大写字母,我们需要将每个小写字母的ASCII值减去'a'的ASCII值,然后加上'A'的ASCII值。这是因为小写字母在ASCII表中的值比对应的大写字母的值大32。
9、假设英文句子由若干词构成。下面C++代码统计输出的词数是( )。
int main() {
string str="gEsP is Interesting !";
int x = str.length();
int nwords = 0;
for(int i = 0; i < x; i++)
if (str[i]==' '){
nwords++;
while(str[++i]==' ') ;
}
cout << nwords << endl;
cout << endl;
return 0;
}
A. 1
B. 2
C. 3
D. 4
正确答案:C
代码逻辑如下:
1.初始化字符串str,长度为x,单词计数器nwords为0。
2.遍历字符串str的每个字符。
3.如果当前字符是空格,则增加nwords的值。
4.使用while循环跳过所有连续的空格。
5.继续遍历字符串,直到遍历完所有字符。
6.输出nwords的值。
现在,让我们分析字符串"gEsP is Interesting !"中的单词:
第一个单词是"gEsP"。
第二个单词是"is"。
第三个单词是"Interesting"。
注意,字符串中有两个连续的空格,但它们只应该计算为一个单词之间的分隔符。
由于代码在每次遇到空格时都会增加nwords的值,并且使用while循环跳过所有连续的空格,因此它不会为连续的空格增加nwords的值。这意味着,即使有两个连续的空格,它们也只会被视为一个分隔符,因此不会增加nwords的值。
因此,代码将正确地统计出字符串中的单词数量为3,并且输出将是3。
10、C++的字符变量的码值是整数,下面字面量形式的字符码值最大的是( )。
A. 100
B. 075
C. 0x70
D. 0x60
正确答案:C
在C++中,字符字面量可以表示为十进制、八进制或十六进制数。这些数字表示的是字符在ASCII码表中的值。ASCII码表中,数值越大,对应的字符在字母表中的位置越靠后。
A选项:这是一个十进制字面量,它表示ASCII码表中值为100的字符,即字符’d’。
B选项:这是一个八进制字面量,它表示ASCII码表中值为7 * 8 + 5 = 61的字符,即字符’=‘。
C选项:这是一个十六进制字面量,它表示ASCII码表中值为7 * 16 + 0 = 112的字符,即字符’p’。
D选项:这是一个十六进制字面量,它表示ASCII码表中值为6 * 16 + 0 = 96的字符,即字符’`‘。
在ASCII码表中,字符’p’(ASCII值为112)的位置是最靠后的,因此它的码值是最大的。
11、下面C++程序执行的结果是( )。
int main(){
int a[20],i;
int cnt = 0;
for(i = 0; i < 20; i++)
a[i] = i + 1;
for(; i > 1; i--)
if((a[i - 1] + a[i - 2]) % 3)
cnt++;
cout << cnt << endl;
cout << endl;
return 0;
}
A. 5
B. 6
C. 10
D. 12
正确答案:D
a[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
| i | (a[i - 1] + a[i - 2]) % 3 | cnt |
|---|---|---|
| 20 | 0 | |
| 19 | 1 | 1 |
| 18 | 2 | 2 |
| 17 | 0 | |
| 16 | 1 | 3 |
| 15 | 2 | 4 |
| 14 | 0 | |
| 13 | 1 | 5 |
| 12 | 2 | 6 |
| 11 | 0 | |
| 10 | 1 | 7 |
| 9 | 2 | 8 |
| 8 | 0 | |
| 7 | 1 | 9 |
| 6 | 2 | 10 |
| 5 | 0 | |
| 4 | 1 | 11 |
| 3 | 2 | 12 |
| 2 | 0 |
12、定义字符数组 char str[20] = {‘G’, ‘E’, ‘S’, ‘P’}; ,则 str 的字符串长度为( )。
A. 4
B. 5
C. 19
D. 20
正确答案:A
在C++中,当你定义一个字符数组并初始化它时,数组的大小是你指定的那个大小,但字符串的长度是由数组中的字符数量决定的,不包括末尾的空字符(null terminator)\0。
给定的字符数组char str[20] = {'G', 'E', 'S', 'P'};定义了一个大小为20的字符数组,但只初始化了前4个字符。数组的大小是固定的,为20个字符,但字符串的长度是由实际存储的字符数量决定的。因此,字符串 “GESP” 的长度是4。
13、定义整型变量 int a=3, b=16 ,则 a|b 的值和 a+b 的关系是( )。
A. 大于
B. 等于
C. 小于
D. 等于或小于
正确答案:B
在C++中,|符号表示按位或(bitwise OR)操作,而+符号表示加法操作。
对于整型变量int a=3, b=16,它们的二进制表示分别是:
a(3)的二进制是0000 0011(假设是32位整数,前面补0)
b(16)的二进制是0001 0000
按位或(bitwise OR)操作a | b会对每一位执行逻辑或操作:
对于每一位,如果a或b中至少有一个是1,则结果是1;否则结果是0。所以,a | b的二进制结果是0001 0011,这等于十进制的 19。
另一方面,加法操作a + b就是简单的数值相加:a + b= 3 + 16 = 19
因此,a | b的值和a + b的值都是19,它们相等。
14、小杨的父母最近刚刚给他买了一块华为手表,他说手表上跑的是鸿蒙,这个鸿蒙是( )。
A. 小程序
B. 计时器
C. 操作系统
D. 神话人物
正确答案:C
华为手表上运行的鸿蒙(HarmonyOS)是一个分布式操作系统,由华为公司开发并发布。这个操作系统被设计为面向全场景的,可以链接手机、汽车、智能音箱、可穿戴设备等多种终端设备,并通过多设备交互让消费者能够像操作一台设备一样简单地操控多个设备。因此,鸿蒙在这里是一个操作系统。
15、中国计算机学会(CCF)在2024年1月27日的颁奖典礼上颁布了王选奖,王选先生的重大贡献是( )。
A. 制造自动驾驶汽车
B. 创立培训学校
C. 发明汉字激光照排系统
D. 成立方正公司
正确答案:C
王选先生是中国计算机汉字激光照排技术的创始人,被誉为“汉字激光照排系统之父”。他的这项发明对中国印刷出版业产生了深远影响,极大地提高了印刷质量和效率。
判断题(每题 2 分,共 20 分)
1、任意整数 a 的二进制反码与补码都有1位不同。 ( )
正确答案:错误
对于正整数,其二进制反码和补码是相同的,都是原码本身。
对于负整数,其二进制反码是原码除符号位外各位取反,而补码是反码加1。
因此,对于负整数,反码和补码有多位不同,而不仅仅是1位。
2、对整型变量int a = 3,执行C++代码a<<2将把2输出到a中。( )
正确答案:错误
a << 2 是将变量 a 的值左移2位。对于 a = 3(二进制为 0011),左移2位后变为 1100,即十进制的12。
3、下面C++代码可以计算1到100的累加和,采用的是穷举法。
int main(){
int i, sum = 0;
for(int i = 1; i <= 100; i++)
sum += i;
cout << sum << endl;
cout << endl;
return 0;
}
正确答案:错误
穷举法,也被称为枚举法,是一种基于问题部分条件来确定答案大致范围,并在此范围内逐一验证所有可能情况的解题方法。
这种方法的核心思想是通过列举所有可能的答案来找到符合所有条件的解。如果某个情况符合所有条件,那么它就被视为问题的一个解。如果在验证完所有情况后都没有找到符合条件的解,则问题无解。
在这个例子中,由于累加和的计算是直接的,并且没有需要穷举的多个可能解,因此使用穷举法来描述这个计算过程是不准确的。代码中的for循环从1迭代到100,每次迭代都将当前的i值累加到sum变量中。这是一种直接且高效的计算累加和的方法,而不是穷举法。
4、一个 int 类型变量 a ,执行操作 (a<<2>>2) 后的值一定是 a 。( )
正确答案:错误
(a << 2 >> 2) 这个操作实际上是先将 a 左移2位,然后再右移2位。对于正数,这个操作的结果通常等于 a,因为左移和右移相同位数会抵消。但是,对于负数,由于二进制表示中的符号位和溢出问题,结果可能不等于 a。
5、在C++语言中, (010 << 1) 执行结果是 100 。( )
正确答案:错误
在C++中,以0开头的数字常量被视为八进制(octal)数。因此,010 表示八进制的10,等于十进制的8(二进制为 1000)。执行 010 << 1(即 8 << 1)后,结果是将8的二进制表示左移1位,得到 10000,即十进制的16,而不是100。
6、执行下面C++代码后将输出 2 。( )
int main(){
string str = "gEsP is Interesting";
int x = str.find("s");
cout << x << endl;
cout << endl;
return 0;
}
正确答案:正确
str.find("s") 方法在字符串 str 中查找第一个出现的子字符串 "s" 的位置。在这个例子中,"s" 第一次出现在索引位置 2(从0开始计数)。因此,x 的值将是 2,代码将输出 2。
7、在C++语言中,字符数组被定义时,它的大小可以调整。( )
正确答案:错误
在C++中,字符数组(或任何数组)的大小在定义时是固定的,不能在运行时调整。
8、对定义的数组 int a[7]={2,0,2,4,3,1,6} ,可以用简单循环就找到其中最小的整数。( )
正确答案:正确
首先初始化一个变量min,用来存储数组中的第一个值,然后通过循环遍历数组的剩余部分。在每次迭代中,我们都检查当前元素是否比 min 更小,如果是,则更新 min 的值。最后,我们输出找到的最小整数。
9、小杨今年春节回奶奶家了,奶奶家的数字电视要设置ip地址并接入到WIFI盒子才能收看节目,那这个WIFI盒 子具有路由器的功能。( )
正确答案:正确
如果数字电视需要通过设置IP地址并接入到WIFI盒子才能收看节目,那么这个WIFI盒子很可能具有路由器的功能,因为它提供了网络连接并允许设备通过它来访问互联网。
10、任何一个 for 循环都可以转化为等价的 while 循环( )。
正确答案:正确
for 循环的结构可以分解为初始化、条件和迭代三个部分。这些部分可以重写为 while 循环的形式。
编程题 (每题 25 分,共 50 分)
字母求和
【问题描述】
小杨同学发明了一种新型密码,对于每一个小写英文字母,该小写字母代表了一个正整数,即该字母在字母顺序中 的位置,例如字母 a 代表了正整数 1,字母 b 代表了正整数 2;对于每一个大写英文字母,该大写字母代表了一个负 整数,即该字母的 ASCII 码的相反数,例如字母 A 代表了正整数 -65。小杨同学利用这种方式对一个整数进行了加密 并得到了一个由大写字母和小写字母组成的字符串,该字符串中每个字母所代表数字的总和即为加密前的整数,例 如 aAc 对应的加密前的整数为 1+(-65)+3=-61。
对于给定的字符串,请你计算出它对应的加密前的整数是多少。
【输入描述】
第一行一个正整数n ,表示字符串中字母的个数。 第二行一个由大写字母和小写字母的字符串T ,代表加密后得到的字符串。
【输出描述】
输出一行一个整数,代表加密前的整数。
【样例输入 1】
3
aAc
【样例输出 1】
-61
对于全部数据,保证有
1
<
=
n
<
=
1
0
5
1 <= n <= 10^5
1<=n<=105
#include <iostream>
using namespace std;
int main() {
int n, ans = 0;
string str;
cin >> n >> str;
for (int i = 0; i < n; i++){
if (str[i] >= 'a' && str[i] <= 'z'){
ans += str[i] - 'a' + 1;
}else{
ans -= str[i];
}
}
cout << ans;
return 0;
}
完全平方数
【问题描述】
小杨同学有一个包含n 个非负整数的序列 A,他想要知道其中有多少对下标组合<i, j> (1 <= i, j <= n, i < j ),使得
A
i
+
A
j
A_i + A_j
Ai+Aj
是完全平方数。
如果x是完全平方数,则存在非负整数y使得y * y = x。
【输入描述】
第一行一个非负整数n ,表示非负整数个数。
第二行包含n 个非负整数
A
1
,
A
2
,
.
.
.
,
A
n
A_1, A_2, ..., A_n
A1,A2,...,An ,表示序列A 包含的非负整数。
【输出描述】
输出一个非负整数,表示和是完全平方数的非负整数对数。
【样例输入 1】
5
1 4 3 3 5
【样例输出 1】
3
对于全部数据,保证有
1
<
=
n
<
=
1000
,
0
<
=
A
i
<
=
1
0
5
1 <= n <= 1000, 0 <= A_i <= 10^5
1<=n<=1000,0<=Ai<=105
#include <iostream>
#include <cmath>
using namespace std;
const int maxn = 1010;
int arr[maxn], n, cnt;
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> arr[i];
for (int i = 1; i <= n; i++){
for (int j = i + 1; j <= n; j++){
int x = arr[i] + arr[j];
int sq = sqrt(x);
if (sq * sq == x){
cnt++;
}
}
}
cout << cnt << endl;
return 0;
}

该博客包含C++知识的单选题、判断题及编程题。单选题涉及整数补码、代码输出等;判断题考查二进制反码、补码等知识;编程题有字母求和与完全平方数问题,前者根据字母规则计算加密前整数,后者求序列中和为完全平方数的非负整数对数。
3715





