本题考查字符串,字符及相关输入操作
1.输入数据带有干扰项(即不会用于接下来操作)
如本题输入格式为[<] 其中, [ 与 ] 即干扰项
第一次的错误尝试:
使用cout将[]输出于屏幕
错误原因: 注意,[ ]是输入项所,cout提取输出没有解决问题
cout << '[';
cin >> str[i];
cout << "] ";
第二次的错误尝试:
使用c语言的scanf函数(scanf可以带特定字符输出)
错误原因:scanf("[%s]",str); 这里的'[',前面正常输入,但后面的']'会进入str数组内
#include<stdio.h>
int main() {
char str[4];
scanf_s("[%s]", str, 4);
printf("%s", str);
}
总结,需要一个输入方式,兼顾cin和scanf,即能只储存目标字符,也能输入干扰项[与]而不影响目标字符读写,
同时,也不会像for循环一样,出现不利情况: 输入次数小于规定次数
注:上述情况解决办法使用while(scanf("%d",&a)==1){}不行,因为每次输入数据都是合法的,无法因为输入数据不合法而跳出while循环
解决方法: 使用getchar函数,逐项输入并赋值 (getchar一次只能提取一个字符)
注意:逐个字符输入,记得带结束符\0
符号集创建及输入函数:
#include<stdio.h>
int add(char str[11][5]) {
char c;
int i = 0, j = 0; //i: 第几个小集合 j: 符号储存
//输入 [或者\n
c = getchar();
while (c != '\n') {
//输入目标字符
c = getchar();
while (c != ']') {
str[i][j++] = c;
//输入 ]或者目标字符
c = getchar();
}
//逐个字符输入,记得带结束符\0
str[i][j++] = '\0';
i++;
j = 0;
//输入 [或者\n
c = getchar();
}
return i;
}
int main() {
char s[11][5];
int ans;
ans = add(s);
for (int i = 0; i < ans; i++) {
printf("%s", s[i]);
}
}
结果展示:
第三次的尝试及解决的问题:
首先考虑了在线处理,即随着输入的位置,输出对应符号集元素,但是运行后发现,如果遇到需输出are u kidding me的输入值,已经打印到屏幕的值无法取消
故采用将输出操作储存进二维数组的方式,再在进行打印操作时使用循环输出,并在输出前先判断二维数组内符号集是否合法
相关操作实现代码:
int n = 0;
cin >> n;
int** num1 = new int* [n];
for (int i = 0; i < n; i++) {
num1[i] = new int[5];
for (int j = 0; j < 5; j++) {
cin >> num1[i][j];
}
}
//接下来输出模块:
//for循环内使用if-else语句,对合法情况判断后再进行cout
最后,使用for循环输出储存的用户操作,经历if-else判断之后进行cout操作:
及该操作内的注意事项:
//测试点1:数组中含有0值 测试点2:数组中含有负数值
for (int t = 0; t < n; t++) {
//这里if与else if的先后顺序不可以改变,因为当num1<num时,包括num1小于0的情况,一但满足就会进入if循环,其他的条件就不会看了
if (num1[t][0] <= 0 || num1[t][1] <= 0 || num1[t][2] <= 0 || num1[t][3] <= 0 || num1[t][4] <= 0) {
cout << "Are you kidding me? @\\/@" << endl;
}
else if (num1[t][0] <= num[0] && num1[t][1] <= num[1] && num1[t][2] <= num[2] && num1[t][3] <= num[1] && num1[t][4] <= num[0]) {
cout << hand[num1[t][0] - 1] << '(' << eye[num1[t][1] - 1] << mouth[num1[t][2] - 1] << eye[num1[t][3] - 1] << ')' << hand[num1[t][4] - 1] << endl;
}
else {
// \ 这个斜杠在字符串里必须输入两次才可以被输出
cout << "Are you kidding me? @\\/@" << endl;
}
}
2.完成基本代码后的易错点:
(1) 本题还需注意各个for循环从0开始与switch-case从1开始与num函数将储存的位置(0还是1)
(2) 输出'\'时,使用\\实现
(3)if-else语句,如果条件有相交关系,注意一下各条件的先后顺序
(4)逐个字符输入,要在最末带上结束符'\0'
(5)在线处理有适用条件
3.其他写法分析:
还需注意,本题将输入的集合元素个数未知,故这种情况,多以输入数据的重复项作为每个集合的判断依据,比如本题的干扰项 '[' 与 ']'
比如第二种写法,使用flag变量进行判断,比如说:
遇到 [ 时flag=0; 遇到 ] 时,flag=1
正确代码:
#include<iostream>
#include<cstring>
using namespace std;
#include<cstdio>
//符号集输入函数
int add(char str[11][5]) {
char c;
int i = 0, j = 0; //i: 第几个小集合 j: 符号储存
//输入 [或者\n
c = getchar();
while (c != '\n') {
//输入目标字符
//这个if(c==']')如果没有,测试点0会出现段错误,因为给定输入样例,显然含有[]外的字符,如空格或者省略号
if (c == '[') {
c = getchar();
while (c != ']') {
str[i][j++] = c;
//输入 ]或者目标字符
c = getchar();
}
str[i][j] = '\0';
i++;
j = 0;
//输入 [或者\n
}
c = getchar();
}
return i;
}
int main() {
char hand[11][5];
char eye[11][5];
char mouth[11][5];
int num[3] = { 0 }; //动态记录手眼鼻中符号集个数
for (int i = 1; i <= 3; i++) {
switch (i) {
//新错误!!! for循环从0开始switch函数从1开始,二者交错,导致mouth无法被赋值
case 1:
num[0] = add(hand);
break;
case 2:
num[1] = add(eye);
break;
case 3:
num[2] = add(mouth);
break;
}
}
//二维数组记录用户输入操作
int n = 0;
cin >> n;
int** num1 = new int* [n];
for (int i = 0; i < n; i++) {
num1[i] = new int[5];
for (int j = 0; j < 5; j++) {
cin >> num1[i][j];
}
}
//开始按储存的用户输入操作进行输出
//测试点1:数组中含有0值 测试点2:数组中含有负数值
for (int t = 0; t < n; t++) {
//这里if与else if的先后顺序不可以改变,因为当num1<num时,包括num1小于0的情况,一但满足就会进入if循环,其他的条件就不会看了
if (num1[t][0] <= 0 || num1[t][1] <= 0 || num1[t][2] <= 0 || num1[t][3] <= 0 || num1[t][4] <= 0) {
cout << "Are you kidding me? @\\/@" << endl;
}
else if (num1[t][0] <= num[0] && num1[t][1] <= num[1] && num1[t][2] <= num[2] && num1[t][3] <= num[1] && num1[t][4] <= num[0]) {
cout << hand[num1[t][0] - 1] << '(' << eye[num1[t][1] - 1] << mouth[num1[t][2] - 1] << eye[num1[t][3] - 1] << ')' << hand[num1[t][4] - 1] << endl;
}
else {
// \ 这个斜杠在字符串里必须输入两次才可以被输出
cout << "Are you kidding me? @\\/@" << endl;
}
}
}