题目要求:
以上图片来自新浪微博。
本题要求你实现一个稍微更值钱一点的 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
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
思路:
- 无论用户说什么,首先把对方说的话在一行中原样打印出来;(纯纯废话)
- Hello ?
- 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
- can you speak Chinese ?
- AI: I can speak chinese!
- 把原文中所有大写英文字母变成小写,除了
I
;- Good to chat with you
- AI: good to chat with you
- 把原文中所有独立的
can you
、could you
对应地换成I can
、I could
—— 这里“独立”是指被空格或标点符号分隔开的单词;- What Is this prime? I,don 't know
- AI: what Is this prime! you,don't know
- 把原文中所有独立的
I
和me
换成you
;- 把原文中所有的问号
?
换成惊叹号!
;- can you speak Chinese?
- AI: I can speak chinese!
- 在一行中输出替换后的句子作为 AI 的回答。
- can you speak Chinese?
- AI: I can speak chinese!
(1)定义了一个名为judge
的函数,它接受一个字符c
作为参数,并返回一个整数来标识这个字符的类型。
(2)定义了一个名为 AI
的函数,它接受一个字符串 ask
作为输入,并返回处理后的结果。这个函数主要用于处理输入的字符串,执行一系列转换和替换操作。
头文件和命名空间:
这里包含了<bits/stdc++.h>
头文件,它实际上是一个包含了C++标准库中几乎所有头文件的头文件。使用using namespace std;
为了避免在代码中重复写std::
前缀。
#include <bits/stdc++.h> using namespace std;
主函数:
程序的入口
int main() { .... }
judge
的函数:
(1)判断字母
这里首先判断c
是否是大写字母('A'
到'Z'
之间)或小写字母('a'
到'z'
之间)。如果是,则返回1
,并在注释中说明这是“字母”。
if((c>='A'&&c<='Z')||(c>='a'&&c<='z')) return 1;//字母
(2)判断数字
如果c
不是字母,则判断它是否是数字('0'
到'9'
之间)。如果是,则返回2
,并在注释中说明这是“数字”。
else if(c>='0'&&c<='9') return 2;//数字
(3)判断空格
如果c
既不是字母也不是数字,则判断它是否是空格。如果是,则返回0
,并在注释中说明这是“空格”。
else if(c==' ') return 0;//空格
(4)判断标点符号
如果c
不是上述任何类型(即不是字母、数字或空格),则返回-1
,并在注释中说明这是“标点符号”。
else return -1;//标点符号
AI
的函数:
(1)删除行首和行尾空格:
通过两个while
循环,函数删除了输入字符串ask
开头的所有空格和结尾的所有空格。
//删除行首空格 while(ask[0]==' ') ask.erase(ask.begin()); //删除行尾空格 while(ask[ask.size()-1]==' ') ask.erase(ask.end()-1);
(2)字符转换:
使用for循环遍历字符串中的每个字符。
如果字符是大写字母(除了'I'),则将其转换为小写字母。
如果字符是问号?,则将其替换为叹号!。
遍历过程中,如果遇到空格,则删除该空格之后的所有连续空格,只保留一个。
for(int i=0;i<ask.size();i++) { //大写变小写 if(ask[i]>='A'&&ask[i]<='Z'&&ask[i]!='I') ask[i]+=32; //?->! if(ask[i]=='?') ask[i]='!'; //删除多余空格 if(ask[i]==' ') { int j=i+1; while(ask[j]==' ') j++; ask.erase(ask.begin()+i+1,ask.begin()+j);//此处参数必须为迭代器,int不行 } }
(3)字符串替换:
再次使用for循环遍历字符串。
如果当前字符是字符串的开头,并且为'I',则根据下一个字符的类型(通过judge函数判断)决定是否将'I'替换为'you'。
如果当前字符和下一个字符组成的子串是"me",并且紧接着的字符不是字母或字符串结束,则同样将"me"替换为"you"。
如果当前字符开始的子串是"can you"或"could you",并且紧接着的字符不是字母或字符串结束,则分别替换为"I can"和"I could"。
上述替换操作在字符串的开头以及字母之前都会进行检查。
//替换字符串 for(int i=0;i<ask.size();i++) { if(i==0) { if(ask[i]=='I'&&(judge(ask[i+1])<=0||i+1==ask.size())) ask.replace(i,1,"you"); else if(ask.substr(i,2)=="me"&&(judge(ask[i+2])<=0||i+2==ask.size())) ask.replace(i,2,"you"); else if(ask.substr(i,7)=="can you"&&(judge(ask[i+7])<=0||i+7==ask.size())) ask.replace(i,7,"I can"); else if(ask.substr(i,9)=="could you"&&(judge(ask[i+9])<=0||i+9==ask.size())) ask.replace(i,9,"I could"); } if(judge(ask[i])<=0) { if(judge(ask[i+1])==1)//字母 { if(ask[i+1]=='I'&&(judge(ask[i+2])<=0||i+2==ask.size())) ask.replace(i+1,1,"you"); if(ask.substr(i+1,2)=="me"&&(judge(ask[i+3])<=0||i+3==ask.size())) ask.replace(i+1,2,"you"); if(ask.substr(i+1,7)=="can you"&&(judge(ask[i+8])<=0||i+8==ask.size())) ask.replace(i+1,7,"I can"); if(ask.substr(i+1,9)=="could you"&&(judge(ask[i+10])<=0||i+10==ask.size())) ask.replace(i+1,9,"I could"); } } }
main函数:
(1)声明变量:
int n;
:用于存储用户输入的问题数量。
string ask, ans;
:ask
用于存储用户输入的问题,ans
用于存储AI
函数处理后的答案。
int n; string ask,ans;
(2)读取问题数量:
cin >> n;
:从标准输入读取用户输入的问题数量。
cin.get();
:读取并丢弃一个字符,通常是换行符,用于清除输入缓冲区中残留的换行符,避免影响后续getline
的读取。
cin>>n; cin.get();
(3)处理每个问题:
while(n--):循环n次,每次循环处理一个问题。
getline(cin, ask);:使用getline函数读取一行字符串作为问题,并存储在ask中。
cout << ask << endl;:输出原始问题。
ans = AI(ask);:调用AI函数处理ask,并将结果存储在ans中。
getline(cin,ask); cout<<ask<<endl; ans=AI(ask);
(4)输出处理后的答案:
cout << "AI: ";:输出提示信息。
循环遍历ans中的每个字符,并输出:
if(ans[i]==' ' && judge(ans[i+1])<=0):判断当前字符是否是空格,并且下一个字符是否为非字母数字字符(通过judge函数判断)。如果是,则跳过该空格不输出。
else cout << ans[i];:否则,输出当前字符。
cout << endl;:每个问题处理完后输出换行符。
cout<<"AI: "; for(int i=0;i<ans.size();i++) { //判断符号+空格+符号的特殊情况 if(ans[i]==' '&&judge(ans[i+1])<=0) continue; else cout<<ans[i]; } cout<<endl;
相关好用函数介绍:
字符函数:
erase函数的三种使用方法:
(1)erase(pos,n); 删除从pos开始的n个字符,比如erase(0,1)就是删除第一个字符
(2)erase(position);删除position处的一个字符(position是个string类型的迭代器)
(3)erase(first,last);删除从first到last之间的字符(first和last都是迭代器)
#include<string> #include<iostream> using namespace std; int main () { string str ("This is an example phrase."); string::iterator it; //第(1)种方法 str.erase (10,8); cout << str << endl; // "This is an phrase." //第(2)种方法 it=str.begin()+9; str.erase (it); cout << str << endl; // "This is a phrase." //第(3)种方法 str.erase (str.begin()+5, str.end()-7); cout << str << endl; // "This phrase." return 0; }
replace() 函数用法
(1)用str替换指定字符串从起始位置pos开始长度为len的字符
string& replace (size_t pos, size_t len, const string& str);
#include<iostream> #include<string> using namespace std; int main() { string str = "he is@ a@ good boy"; str=str.replace(str.find("a"),2,"#"); //从第一个a位置开始的两个字符替换成# cout<<str<<endl; //he is@ # good boy return 0; }
(2) 用str替换迭代器起始位置 和 结束位置 的字符
string& replace (const_iterator i1, const_iterator i2, const string& str);
#include<iostream> #include<string> using namespace std; int main() { string str = "he is@ a@ good boy"; str=str.replace(str.begin(),str.begin()+5,"#"); //用#替换从begin位置开始的5个字符 cout<<str<<endl; //#@ a@ good boy return 0; }
(3)用substr的指定子串(给定起始位置和长度)替换从指定位置上的字符串
string& replace (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);
#include<iostream> #include<string> using namespace std; int main() { string str = "he is@ a@ good boy"; string substr = "12345"; str=str.replace(0,3,substr,substr.find("2"),4); //用substr的指定字符串替换str指定字符串 cout << str << endl; //2345 is@ a@ good boy //从 str 的开始位置(即 "he")提取前3个字符, //并用 "2345"(从 "12345" 的第2个字符开始,提取4个字符)进行替换。 //所以,str 的新值变为 "2345 is@ a@ good boy"。 return 0; }
(4)用重复n次的c字符替换从指定位置pos长度为len的内容
string& replace (size_t pos, size_t len, size_t n, char c);
#include<iostream> #include<string> using namespace std; int main() { string str = "he is@ a@ good boy"; char str1 = '#'; str = str.replace(0,6,3,str1); //用重复3次的str1字符替换的替换从位置0~6的字符串 cout<<str<<endl; //### a@ good boy return 0; }
(5) 用重复n次的c字符替换从指定迭代器位置(从i1开始到结束)内容
string& replace (const_iterator i1, const_iterator i2, size_t n, char c);
#include<iostream> #include<string> using namespace std; int main() { string str = "he is@ a@ good boy"; char str1 = '#'; str = str.replace(str.begin(),str.begin()+6,3,str1); //用重复3次的str1字符替换的替换从指定迭代器位置的内容 cout<<str<<endl; //### a@ good boy return 0; }
代码:
#include <bits/stdc++.h> using namespace std; int judge(char c) { //判断传入的字符是什么 if((c>='A'&&c<='Z')||(c>='a'&&c<='z')) return 1;//字母 else if(c>='0'&&c<='9') return 2;//数字 else if(c==' ') return 0;//空格 else return -1;//标点符号 } string AI(string ask) {//返回处理结果 //删除行首空格 while(ask[0]==' ') ask.erase(ask.begin()); //删除行尾空格 while(ask[ask.size()-1]==' ') ask.erase(ask.end()-1); for(int i=0;i<ask.size();i++) { //大写变小写 if(ask[i]>='A'&&ask[i]<='Z'&&ask[i]!='I') ask[i]+=32; //?->! if(ask[i]=='?') ask[i]='!'; //删除多余空格 if(ask[i]==' ') { int j=i+1; while(ask[j]==' ') j++; ask.erase(ask.begin()+i+1,ask.begin()+j);//此处参数必须为迭代器,int不行 } } //替换字符串 for(int i=0;i<ask.size();i++) { if(i==0) { if(ask[i]=='I'&&(judge(ask[i+1])<=0||i+1==ask.size())) ask.replace(i,1,"you"); else if(ask.substr(i,2)=="me"&&(judge(ask[i+2])<=0||i+2==ask.size())) ask.replace(i,2,"you"); else if(ask.substr(i,7)=="can you"&&(judge(ask[i+7])<=0||i+7==ask.size())) ask.replace(i,7,"I can"); else if(ask.substr(i,9)=="could you"&&(judge(ask[i+9])<=0||i+9==ask.size())) ask.replace(i,9,"I could"); } if(judge(ask[i])<=0) { if(judge(ask[i+1])==1)//字母 { if(ask[i+1]=='I'&&(judge(ask[i+2])<=0||i+2==ask.size())) ask.replace(i+1,1,"you"); if(ask.substr(i+1,2)=="me"&&(judge(ask[i+3])<=0||i+3==ask.size())) ask.replace(i+1,2,"you"); if(ask.substr(i+1,7)=="can you"&&(judge(ask[i+8])<=0||i+8==ask.size())) ask.replace(i+1,7,"I can"); if(ask.substr(i+1,9)=="could you"&&(judge(ask[i+10])<=0||i+10==ask.size())) ask.replace(i+1,9,"I could"); } } } return ask; } int main() { int n; string ask,ans; cin>>n; cin.get(); while(n--) { getline(cin,ask); cout<<ask<<endl; ans=AI(ask); cout<<"AI: "; for(int i=0;i<ans.size();i++) { //判断符号+空格+符号的特殊情况 if(ans[i]==' '&&judge(ans[i+1])<=0) continue; else cout<<ans[i]; } cout<<endl; } return 0; }
测试结果:
合作/推广/交流/技术学习
微信名片