// 未精简代码
#include <bits/stdc++.h>
using namespace std;
int main() {
// 给出符号集合 按要求输出
// []内为符号 每个集合至少一个符号 ? 左手
// 集合不超过10 个 符号不超过4个字符
string h, e, m, tmp;
// 定义三个 map 容器存不同符号
map<int, string> hand, eye, mouth;
// 读取三行符号集
getline(cin, h);
getline(cin, e);
getline(cin, m);
// 处理集合得到符号
for(int i = 0, num = 1; i < h.size(); i++){
// 如果是 '['则重置字符串
if(h[i] == '['){
tmp = "";
}
// 如果是 ']'字符 将字符串放入 map 容器
else if(h[i] == ']'){
hand[num++] = tmp;
}
else{
// 拼接符号
tmp = tmp + h[i];
}
}
// 处理集合得到符号
for(int i = 0, num = 1; i < e.size(); i++){
// 如果是 '['则重置字符串
if(e[i] == '['){
tmp = "";
}
// 如果是 ']'字符 将字符串放入 map 容器
else if(e[i] == ']'){
eye[num++] = tmp;
}
else{
// 拼接符号
tmp = tmp + e[i];
}
}
// 处理集合得到符号
for(int i = 0, num = 1; i < m.size(); i++){
// 如果是 '['则重置字符串
if(m[i] == '['){
tmp = "";
}
// 如果是 ']'字符 将字符串放入 map 容器
else if(m[i] == ']'){
mouth[num++] = tmp;
}
else{
// 拼接符号
tmp = tmp + m[i];
}
}
// 读取请求个数
int k;
cin >> k;
int num[k][5];
for(int i = 0; i < k; i++)
for(int j = 0; j < 5; j++)
cin >> num[i][j];
for(int i = 0; i < k; i++){
// 判断是否可以输出表情
bool flag = true;
// 0 1 2 3 4
// [左手] ([左眼] [口] [右眼]) [右手]
for(int j = 0; j < 5; j++){
if(j == 0 || j == 4){
if(hand.find(num[i][j]) == hand.end()) {
flag = false;
break;
}
}
else if(j == 1 || j == 3){
if(eye.find(num[i][j]) == eye.end()) {
flag = false;
break;
}
}
else if(j == 2){
if(mouth.find(num[i][j]) == mouth.end()) {
flag = false;
break;
}
}
}
if(flag == true)
for(int j = 0; j < 5; j++){
if(j == 0 || j == 4){
cout << hand[num[i][j]];
}
else if(j == 1 || j == 3){
if(j == 1) cout << '(';
cout << eye[num[i][j]];
if(j == 3) cout << ')';
}
else if(j == 2){
cout << mouth[num[i][j]];
}
// 序号不存在输出
}
else
cout << "Are you kidding me? @\\/@";
cout << endl;
}
}
// 精简后代码
#include <bits/stdc++.h>
using namespace std;
void process(map<int, string>& mp){
string tmp, str;
// 读取符号集字符串
getline(cin, str);
for(int i = 0, num = 1; i < str.size(); i++){
// 如果是 '['则重置字符串
if(str[i] == '['){
tmp = "";
}
// 如果是 ']'字符 将字符串放入 map 容器
else if(str[i] == ']'){
mp[num++] = tmp;
}
else{
// 拼接符号
tmp = tmp + str[i];
}
}
}
bool numIsTrue(int num, map<int, string>& mp){
if(mp.find(num) == mp.end())
return false;
return true;
}
int main() {
// 给出符号集合 按要求输出
// []内为符号 每个集合至少一个符号 ? 左手
// 集合不超过10 个 符号不超过4个字符
// 定义三个 map 容器存不同符号
map<int, string> hand, eye, mouth;
// 读取并处理符号集
process(hand);
process(eye);
process(mouth);
// 读取请求个数
int k, num[5];
cin >> k;
for(int i = 0; i < k; i++){
// 读取一行序号
for(int i = 0; i < 5; i++)
cin >> num[i];
// 0 1 2 3 4
// [左手] ([左眼] [口] [右眼]) [右手]
if(numIsTrue(num[0], hand) &&
numIsTrue(num[1], eye) &&
numIsTrue(num[2], mouth) &&
numIsTrue(num[3], eye) &&
numIsTrue(num[4], hand))
cout << hand[num[0]] << '(' << eye[num[1]] << mouth[num[2]]
<< eye[num[3]] << ')' << hand[num[4]];
else
cout << "Are you kidding me? @\\/@";
cout << endl;
}
}
当时不会函数传递引用,只能考复制粘贴和改变量名将就,所以代码写得臭长。看了下别人的文章,原来容器传递参数跟基本变量类型是类似的,而不是数组,直接就是地址。所以在函数参数类型后加一个 & 即可。
参考别人更好的写法。原来判断符号是否存在,只需要对比读取进来的序号是否在容器元素个数的范围内。这个除了大于还得考虑小于的负数的情况(没想到还有负数的情况)。
这样写起来到时比我之前通过搜索容器的 key 的方式简洁不少。
if (a[0] > hand.size() || a[4] > hand.size() || a[1] > eye.size() || a[3] > eye.size() || a[2] > mouth.size()
|| a[0] < 1 || a[1] < 1 || a[2] < 1 || a[3] < 1 || a[4] < 1) //测试点2
cout << "Are you kidding me? @\\/@" << endl;
关于错误信息的输出里面有一个需要特殊处理,当时想不清楚到底是 \ 还是 / ,当然试了试可以发现 \ 反斜杠作为转义字符是需要变成 \\ 的。
int a[5];
for (int i = 0; i < 5; ++i)
cin >> a[i];
本来写的方式以二维数组的方式读取进来,然后也是以二维数组来输出。参考别人可以在循环里面读取一行的数据,放在一维数组里面。想了想,直接命名5个变量并读取也不是不可以。
这样的后面也不需要搞一个循环变量来输出,直接读取下标就可以了。搞一个循环还要写判断语句,反而更麻烦。
也就说这种数据比较小的,直接手动给出下标输出就可以了,没必要搞一个判断。可能是前面的题目很多都是需要判断的,都成为下意识了。