CSP-J 2020 入门级 第一轮 阅读程序(1)
【题目】
CSP-J 2020 入门级 第一轮 阅读程序(1)
01 #include <cstdlib>
02 #include <iostream>
03 using namespace std;
04
05 char encoder[26] = {'C','S','P',0};
06 char decoder[26];
07
08 string st;
09
10 int main() {
11 int k = 0;
12 for (int i = 0; i < 26; ++i)
13 if (encoder[i] != 0) ++k;
14 for (char x ='A'; x <= 'Z'; ++x) {
15 bool flag = true;
16 for (int i = 0; i < 26; ++i)
17 if (encoder[i] ==x) {
18 flag = false;
19 break;
20 }
21 if (flag) {
22 encoder[k]= x;
23 ++k;
24 }
25 }
26 for (int i = 0; i < 26; ++i)
27 decoder[encoder[i]- 'A'] = i + 'A';
28 cin >> st;
29 for (int i = 0; i < st.length( ); ++i)
30 st[i] = decoder[st[i] -'A'];
31 cout << st;
32 return 0;
33 }
•判断题
- 输入的字符串应当只由大写字母组成,否则在访问数组时可能越界。( )
- 若输入的字符串不是空串,则输入的字符串与输出的字符串一定不一样。( )
- 将第 12 行的 i < 26 改为 i < 16,程序运行结果不会改变。( )
- 将第 26 行的 i < 26 改为 i < 16,程序运行结果不会改变。( )
•单选题
-
若输出的字符串为 ABCABCABCA,则下列说法正确的是( )。
A. 输入的字符串中既有 S 又有 P
B. 输入的字符串中既有 S 又有 B
C. 输入的字符串中既有 A 又有 P
D. 输入的字符串中既有 A 又有 B -
若输出的字符串为 CSPCSPCSPCSP,则下列说法正确的是( )。
A. 输入的字符串中既有 P 又有 K
B. 输入的字符串中既有 J 又有 R
C. 输入的字符串中既有 J 又有 K
D. 输入的字符串中既有 P 又有 R
【题目考点】
1. 字符串
2. 映射关系
【解题思路】
05 char encoder[26] = {'C','S','P',0};
06 char decoder[26];
07
08 string st;
首先看数组名字,encoder是加密器的意思,大概是通过该数组可以对字符串进行加密。decode是解密器的意思,大概是通过该数组可以将一个加密后的字符串解密。一个逻辑清晰、工整的代码的变量名都是有意义的,我们可以通过其名字推测它的实际作用。
已知encoder数值:encoder[0]:'C'
,encode[1]:'S'
,encode[2]:'P'
。
11 int k = 0;
12 for (int i = 0; i < 26; ++i)
13 if (encoder[i] != 0) ++k;
encoder下标范围为0到25,共26个位置。k为encoder数组中不为0的元素的数量,有encoder[0]~encoder[2]
不为0,共3个元素,因此k的值为3。encode的下标从0开始,因此下标k是encoder数组最后一个元素的下一个位置,也是下一次要填充的元素的位置。
14 for (char x ='A'; x <= 'Z'; ++x) {
15 bool flag = true;
16 for (int i = 0; i < 26; ++i)
17 if (encoder[i] ==x) {
18 flag = false;
19 break;
20 }
21 if (flag) {
22 encoder[k]= x;
23 ++k;
24 }
25 }
字符型变量x从A循环到Z,对于每个x,遍历encoder数组,看是否存在一个元素的值为x:
- 如果encoder中存在x,则将flag设为false,跳出循环。此处flag为true表示encoder中没有x,flag为false表示encoder中存在x。
- 如果encoder中不存在x,则将x填充至encoder数组的末尾,k表示encoder数组中元素的个数,也是待填充元素的位置。
完成填充后,encoder数组为
下标i | 值encoder[i] |
---|---|
0 | C |
1 | S |
2 | P |
3 | A |
4 | B |
5 | D |
6 | E |
7 | F |
8 | G |
9 | H |
10 | I |
11 | J |
12 | K |
13 | L |
14 | M |
15 | N |
16 | O |
17 | Q |
18 | R |
19 | T |
20 | U |
21 | V |
22 | W |
23 | X |
24 | Y |
25 | Z |
26 for (int i = 0; i < 26; ++i)
27 decoder[encoder[i]- 'A'] = i + 'A';
自然,这里的i是字母对应的数字,0对应A,1对应B,…,25对应Z。
此时decoder数组的值为i+'A'
。该值是通过encoder[i]
这个字符转成的编号在decoder数组中得到的。
结合encoder的意思是加密器,decoder的意思是解密器,该代码应该是完成了对字符的加密和解密的过程。
为方便理解:设原字符为i+'A'
,加密后的字符为j+'A'
。
那么有:encoder[i] = j+'A'
根据:decoder[encoder[i]-'A'] = decoder[j+'A'-'A'] = decoder[j] = i+'A'
所以有:decoder[j] = i+'A'
。
因此可以理解为:
- 如果原字符为
i+'A'
,那么加密后的字符为encoder[i] = j+'A'
。使用encoder数组可以通过原字符找到加密后的字符。 - 如果加密后的字符为
j+'A'
,那么解密后的字符为decoder[j] = i+'A'
。使用decoder数组可以通过加密后的字符找到原字符。
原字符和加密后的字符就是一组映射关系。根据encoder数组,把encoder数组的下标i
变为字符i+'A'
,就能得到原字符和加密后的字符的对应关系。
原字符 | 加密后的字符 |
---|---|
A | C |
B | S |
C | P |
D | A |
E | B |
F | D |
G | E |
H | F |
I | G |
J | H |
K | I |
L | J |
M | K |
N | L |
O | M |
P | N |
Q | O |
R | Q |
S | R |
T | T |
U | U |
V | V |
W | W |
X | X |
Y | Y |
Z | Z |
28 cin >> st;
29 for (int i = 0; i < st.length( ); ++i)
30 st[i] = decoder[st[i] -'A'];
31 cout << st;
输入字符串st,将字符串st中每个字符通过decoder数组,从加密后的字符变为原字符,最后输出st。
整篇代码解决的问题是:
输入一个加密后的字符串,根据上述映射表找到每个加密后的字符对应的解密后的字符,完成对字符串的解密,最后输出解密后的字符串。
判断题
1. 输入的字符串应当只由大写字母组成,否则在访问数组时可能越界。( )
答:T
输入st后,有语句st[i] = decoder[st[i] -'A']
;。当st[i]
不是大写字母时,st[i]-'A'
的值会小于0或大于25,会超出decoder数组的下标范围0~25,可能会发生数组越界。
2. 若输入的字符串不是空串,则输入的字符串与输出的字符串一定不一样。( )
答:F
观察映射表,对于字母TUVWXYZ,原字符和加密后的字符是相同的。对于完全由这几个字母组成的加密后的字符串,解密后的字符串与加密后的字符串也是相同的。比如输入“TUVWXYZ”,就会输出“TUVWXYZ”。输入的字符串与输出的字符串可能一样。
3. 将第 12 行的 i < 26 改为 i < 16,程序运行结果不会改变。( )
答:T
12 for (int i = 0; i < 26; ++i)
13 if (encoder[i] != 0) ++k;
第12行和第13行的作用的统计k的值,k的值指的是encoder数组中已有元素的数量。
根据
05 char encoder[26] = {'C','S','P',0};
可知,encoder数组中已有3个元素。第12、13行运行时,只有在i位0、1、2时,encoder[i]
不为0,k会增加1。在i大于等于3的情况下,encoder[i]
都为0,k不会增加。
当i循环到3时,k已经为3了。i无论是循环到15还是25,k的值都为3,没有区别。
因此当第12行for循环第二个表达式改为i < 16
时,结果不变。
4. 将第 26 行的 i < 26 改为 i < 16,程序运行结果不会改变。( )
答:F
26 for (int i = 0; i < 26; ++i)
27 decoder[encoder[i]- 'A'] = i + 'A';
第26~27行完成的对decoder数组的设置。
如果i只循环到15,那么decoder[16]~decoder[25]
都为0。
对于原字符i+'A'
,假设加密后的字符为encoder[i] = j+'A'
。
当i >= 16
时,没有设置decoder[j] = i+'A'
。因此对于i >= 16
的情况,无法通过decoder[encoder[i]-'A']
得到加密后的字符j+'A'
对应的原字符i+'A'
。会导致一些字符无法正确解码,无法正常输出。因此该题选“错误”。
比如将第 26 行的 i < 26 改为 i < 16。已知
encoder[25]='Z'
,那么就没有当i为25时设置decoder[encoder[25]-'A'] = decoder[25] = 25+'A' = 'Z'
。而是保持decoder[25] = '\0'
。当输入的加密后的字符串st中存在Z
时,无法将Z
解密为Z
,而是解密为\0
,导致该字符无法输出。
•单选题
5. 若输出的字符串为 ABCABCABCA,则下列说法正确的是( )。
A. 输入的字符串中既有 S 又有 P
B. 输入的字符串中既有 S 又有 B
C. 输入的字符串中既有 A 又有 P
D. 输入的字符串中既有 A 又有 B
答:A
输入的字符串为加密后的字符串,输出的字符串为原字符串。给输出字符串,询问输入字符串的请,进行的就是加密的过程。
对字符"ABCABCABCA"加密,观察上述映射表,A加密为C,B加密为S,C加密为P,因此加密后的字符串,也就是输入字符串为"CSPCSPCSPC"。
该字符串中既有S又有P,选A。
6. 若输出的字符串为 CSPCSPCSPCSP,则下列说法正确的是( )。
A. 输入的字符串中既有 P 又有 K
B. 输入的字符串中既有 J 又有 R
C. 输入的字符串中既有 J 又有 K
D. 输入的字符串中既有 P 又有 R
答:D
输入的字符串为加密后的字符串,输出的字符串为原字符串。给输出字符串,询问输入字符串的请,进行的就是加密的过程。
对字符"CSPCSPCSPCSP"加密,观察上述映射表,C加密为P,S加密为R,P加密为N,因此加密后的字符串,也就是输入字符串为PRNPRNPRNPRN"。. 输入的字符串中既有 P 又有 R。因此选D。
【答案】
- T
- F
- T
- F
- A
- D