下面函数是一个加密解密的函数,横线处应该填入的程序段是( )。
#include <iostream>
#include <string>
using namespace std;
int main() {
int key;
cin >> key;
string msg = "Hello GESP";
cout << msg << endl;
for (int i = 0; i < msg.size(); i++) {
msg[i] = msg[i] ^ key;
}
cout << msg << endl;
_________________________________
cout << msg << endl;
return 0;
}A.
for (int i = 0; i < msg.size(); i++) {
msg[i] = msg[i] | key;
}B.
for (int i = 0; i < msg.size(); i++) {
msg[i] = msg[i] >> key;
}C.
for (int i = 0; i < msg.size(); i++) {
msg[i] = msg[i] ^ key;
}D.
for (int i = 0; i < msg.size(); i++) {
msg[i] = msg[i] & key;
}看到加密解密成对出现,立刻想到异或的自反性质。加密时 msg[i] = msg[i] ^ key,解密只需再执行一次同样的异或:(msg[i] ^ key) ^ key = msg[i]。因此横线处必须填与加密完全相同的循环,其他任何位运算都无法保证可逆还原。
A 选项按位或会丢失原字符中为 0 的位信息,无法还原;B 选项右移是数据依赖操作,移位次数不同结果完全不同,且高位信息永久丢失;D 选项按位与同样丢失信息——原字符中为 1 但 key 对应位为 0 的位会全部变成 0。很多考生误以为解密需要"反向操作",其实异或本身就是对称的。
本题考查《GESP C++ 考试大纲》三级"位运算"模块中的异或运算性质。命题人把这道题放在这里,就是要卡住那些只背"异或用于加密"却不懂其数学本质的考生——他们看到加密就以为解密要换操作,却不知异或的自反性决定了加密与解密是同一过程。
完整思考链:看到加密循环 → 识别操作符为异或 → 回忆异或性质 a^b^b = a → 得出结论:解密只需再执行一次相同循环。
关键数值验证(取 msg[0] = 'H' = 0x48 = 72):
这一类题的通法:任何加密算法若使用可逆运算(异或、加减、异或组合等),解密步骤与加密步骤完全相同,只需顺序相反或参数调整。