本题要求你实现一个稍微更值钱一点的 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
这道题运用函数模块化比较方便,首先我定义了四个函数:
空格去除函数,要注意,标点符号前面也可能有空格,如don ’t ,要把标点符号前的空格去除。
替换函数,将要替换的字符都替换的,我把me、I、can you、could you 没有替换只是在字符串中用不同的特殊字符标记一下,只标记单词的首字母,方便在输出函数中替换。标记这些单词时要用判断函数,判断是不是一个独立的单词,就是将单词首字母的前一个字符判断一下,或者该单词就是整个句子的首,单词尾字母的后一位判断一下,符合后在标记。
判断函数,就是用于判断是不是大、小写字母或数字,如果是,返回1,否则返回0,用于替换函数判断是不是独立的单词。
输出函数,就是把标记的单词换成要替换的单词,因为只标记首字母,如果遍历遇到标记的特殊字符,就输出对应的替换单词,然后把遍历的变量(代码中是i),加上相对应单词长度数,如me ,i只需加1,让循环跳过要替换的单词,接着输出后面的单词即可
#include
char ch[1100]; //用于存放没有去除空格的字符串
char x[1100]; //用于存放去除完空格的字符串
//定义三个函数
int judge(char a); //判断字符是不是大小写字母或数字
void replace(); //将要替换的字符替换
void kong(); //去除空格
void print(); //用于输出
int main()
{
int n;
scanf("%d",&n);
getchar();
while(n--)
{
for(int i=0;i<1100;i++)
x[i]='\0'; //将字符串数组置空
gets(ch);
printf("%s\n",ch); //1、将原话输出
kong(); //2、去除空格
replace(); //替换字符
printf("AI: ");
print(); //输出
printf("\n");
}
return 0;
}
void print()
{
for(int i=0;x[i]!='\0';i++)
{
if(x[i]=='^') //如果为 ^
{ //就是me要换成 you
printf("you");
i++; //因为me是两个字母,i加1,跳过e这个字母
continue;
}
if(x[i]=='#')
{
printf("I can");
i+=6; //因为can you字符多,所以跳过后面的不输出
continue;
}
if(x[i]=='$')
{
printf("I could");
i+=8;
continue;
}
if(x[i]=='*')
printf("you");
else //如果不属于以上情况,则输出字符
printf("%c",x[i]);
}
}
void kong()
{ //2、去除空格
int count=0,sum=0,flag=0;
for(int i=0;ch[i]!='\0';i++)
{
if(ch[i]==' ')
sum++; //如果为空则加1
else if(!judge(ch[i]))
{ //如果是标点符号
sum=0; //置空
flag=1;
x[count++]=ch[i]; //将标点符号存入
}
else
{ //如果前一个或连续的几个字符是空格,且不是在开头
if(sum>0 && flag)
x[count++]=' '; //将数组里存入一个空格
sum=0; //置空
flag=1;
x[count++]=ch[i]; //将字符存入数组
}
}
}
void replace()
{ //替换字符
for(int i=0;x[i]!='\0';i++)
{
//3、将?替换成!
if(x[i]=='?')
x[i]='!';
//4、将除了I的大写字母转化成小写字母
if(x[i]>='A'&&x[i]<='Z'&&x[i]!='I')
x[i]=x[i]+32;
/*5、如果是一个独立(I的前一个字母或I为第一个字符和后一个字符是非大小写字母和数字则为独立)的 I,将这个字符变为 *,这样在输出的时候可以换成you */
if(x[i]=='I'&&(i==0||!judge(x[i-1]))&&!judge(x[i+1]))
x[i]='*';
/*5、如果是一个独立(m的前一个字母或m为第一个字符和e的后一个字符是非大小写字母和数字则为独立)的 me,将m字符变为 ^,这样在输出的时候可以换成you */
if(x[i]=='m'&&x[i+1]=='e'&&(i==0||!judge(x[i-1]))&&!judge(x[i+2]))
x[i]='^';
}
for(int i=0;x[i]!='\0';i++)
{
/*6、如果字符是独立(c的前一个字母或c为第一个字符和u的后一个字符是非大小写字母和数字则为独立)的can you将c字符变为 # ,这样在输出的时候可以换成 I can */
if(x[i]=='c'&&x[i+1]=='a'&&x[i+2]=='n'&&x[i+3]==' '&&x[i+4]=='y'&&x[i+5]=='o'&&x[i+6]=='u'&&!judge(x[i+7])&&(i==0||!judge(x[i-1])))
x[i]='#';
/*6、如果字符是独立(c的前一个字母或c为第一个字符和u的后一个字符是非大小写字母和数字则为独立)的could you 将c字符变为 $ ,在输出的时候可以换成 I could */
if(x[i]=='c'&&x[i+1]=='o'&&x[i+2]=='u'&&x[i+3]=='l'&&x[i+4]=='d'&&x[i+5]==' '&&x[i+6]=='y'&&x[i+7]=='o'&&x[i+8]=='u'&&!judge(x[i+9])&&(i==0||!judge(x[i-1])))
x[i]='$';
}
}
int judge(char a)
{ //判断是否为大小写字母和数字
if(a>='a'&&a<='z')
return 1;
if(a>='A'&&a<='Z')
return 1;
if(a>='0'&&a<='9')
return 1;
return 0;
}