PAT1052_乙级_卖个萌

本文讲解了如何在C语言编程中处理输入字符串时,避免干扰字符如[]的影响,通过getchar逐个字符输入并确保目标字符的正确读取。同时介绍了如何使用二维数组存储用户操作,以及在输出时进行合法性检查的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本题考查字符串,字符及相关输入操作

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;
		}
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值