L1-064 估值一亿的AI核心代码 (20 分)

文章目录

  • 1.题目
  • 2.解题思路
  • 3.代码
  • 4.与字符串处理操作有关的一些总结
  • 5.参考博客

1.题目

本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:

  • 无论用户说什么,首先把对方说的话在一行中原样打印出来;
  • 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
  • 把原文中所有大写英文字母变成小写,除了 I;
  • 把原文中所有独立的 can you、could you 对应地换成 I can、I could—— 这里“独立”是指被空格或标点符号分隔开的单词;
  • 把原文中所有独立的 I 和 me 换成 you;
  • 把原文中所有的问号 ? 换成惊叹号 !;
  • 在一行中输出替换后的句子作为 AI 的回答。
    输入格式:
    输入首先在第一行给出不超过 10 的正整数 N,随后 N 行,每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话,对话为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。
    输出格式:
    按题面要求输出,每个 AI 的回答前要加上 AI: 和一个空格。
输入样例:
6
Hello ?
 Good to chat   with you
can   you speak Chinese?
Really?
Could you show me 5
What Is this prime? I,don 't know
结尾无空行
输出样例:
Hello ?
AI: hello!
 Good to chat   with you
AI: good to chat with you
can   you speak Chinese?
AI: I can speak chinese!
Really?
AI: really!
Could you show me 5
AI: I could show you 5
What Is this prime? I,don 't know
AI: what Is this prime! you,don't know
结尾无空行

2.解题思路

首先自己做的时候感觉无从下手,这道题从多方面考察了对字符串的处理,哎,自己这方面还是不行。参考网上的代码,发现需要用到许多关于字符串处理的函数以及字符串的一些类,正好通过这道题可以总结学习一下,此外还有的代码使用的是正则表达式,关于这种解法没有做深入了解。第一种解题的大致思想是在每个非数字字母之前添加上空格,将单词、数字以及符号分成一个个的块依次进行处理。具体思路详见代码及注释。

3.代码

 #include 
 using namespace std;
 int main()
 {
     
 	int n;
 	cin>>n;
 	getchar();
 	for(int i=0;i<n;i++)
 	{
     
 		string s;
 		getline(cin,s);
 		cout<<s<<endl;
 		cout<<"AI:";
 		for(int i=0;i<s.length();i++)
 		{
     
 			if(isalnum(s[i]))//isalnum()用来判断一个字符是否为数字或者字母,也就是说判断一个字符是否属于a~z||A~Z||0~9。
		 	{
     
		 		//把原文中所有大写英文字母变成小写,除了 I
			 	if(s[i]!='I') s[i]=tolower(s[i]);
			 }
			 else {
     
			 	s.insert(i," ");//对每个非字母和数字之前加空格
			 	i++;
			 }
			 if(s[i]=='?')s[i]='!';
		 }
		 stringstream ss(s);//将s复制到ss字符串中
		 string s1;
		 vector<string> str;
		 while(ss>>s1)//相当于输入一个个的单词,这样就可以消掉句子前的空格以及单词间多余的空格 
		 {
     
		 	str.push_back(s1);
		  }
		  str.push_back("");//多向容器中加入一个元素,防止下面i+1溢出 
		  if(!isalnum(str[0][0]))cout<<" ";//若第一个字符串的第一个字符是符号,则需要先输出一个空格,因为题目要求"AI:"后面要有一个空格。
		  for(int i=0;i<str.size()-1;i++)
		  {
     
		  	string s2=str[i]; 
	  		if(s2.find("can")!=s2.npos && str[i+1]=="you" )
			{
     //can和could前面可能会有符号 
	            if(!isalnum(s2[0]))cout<<s2[0];
	            else cout<<" ";
			    cout<<"I can";
	  		    i++;
			}
			else if(s2.find("could")!=s2.npos && str[i+1]=="you")
			{
     
				if(!isalnum(s2[0]))cout<<s2[0];
		        else cout<<" ";
			  	cout<<"I could";
				i++;
			}
			else if(str[i]=="I" || str[i]=="me") cout<<" you";
			else if(!isalnum(str[i][0])) cout<<str[i];
			else cout<<" "<<str[i];
		  }
		  cout<<endl;
	 }
 	return 0;
 }

4.与字符串处理操作有关的一些总结

  1. 用于进行字符判断的函数,若是则返回非0,不是则返回0:
  • isalnum()
    判断输入的字符是否为字母或者数字,即是否在 “A – Z” 或者 “a – z” 或者"0 – 9"之间
  • isdigit()
    判断输入的字符是否是数字
  • isalpha()
    判断输入的字符是否为字母,即是否在 “A – Z” 或者 "a – z"之间
  • islower()
    判断字符是否小写字母
  • isupper()
    判断字符是否大写字母
  • isblank()
    判断输入字符是否为空格,或者tab键制表符,即space 和 \t
  • isspace()
    判断输入字符是否为 空格,或者tab键制表符,’\r’ 或 ‘\n’ 等
  1. 用于进行字符转换的函数,使用时参数输入为字符类型:
  • toupper()
    将一个字符转换为大写
  • tolower()
    将一个字符转换为小写
  1. stringstream的妙用:
    istringstream、ostringstream 和 stringstream三个类分别用来进行流的输入、输出和输入输出操作。 stringstream 类主要用来进行数据类型的转换,由于使用string对象来代替字符数组(snprintf方式),就避免缓冲区溢出的危险;而且,因为传入参数和目标对象的类型会被自动推导出来,所以不存在错误的格式化符的问题。简单说,相比c库的数据类型转换而言, 更加安全、自动和直接。
#include 
#include 
using namespace std;
int main()
{
     
	string str = "hello world";
	cout << str << endl;
	stringstream ss(str); //将str复制到ss
	string abc;
	while(ss >> abc) //相当于输入一个个的单词
	{
     
		cout << abc <<endl;
	}
	return 0;
}

代码输出结果:

4. string的find函数:
该函数用于在字符串s中查找子字符串s1,若能找到则返回s1在s中首次出现时其首字符的索引(从0开始);否则,返回string::npos,对应上面的代码为:

else if(s2.find("could")!=s2.npos && str[i+1]=="you")

5.参考博客

1.PTA 估值一亿的AI核心代码(全网最短的代码)不到50行,一看就会
2.C++中toupper、tolower 、isalpha、isalnum、isdigit、islower、isupper、isblank、isspace的用法
3.c++ stringstream ss()

你可能感兴趣的:(C++编程题,c++)