第四章学习小结

一把辛酸泪。。。
不多说,先上题
 
7-2 AI核心代码 (30 分)
 

本题要求你实现一个简易版的 AI 英文问答程序,规则是:

  1. 无论用户说什么,首先把对方说的话在一行中原样打印出来;
  2. 消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
  3. 把原文中所有大写英文字母变成小写,除了 I;
  4. 把原文中所有独立的 I 和 me 换成 you;
  5. 把原文中所有的问号 ? 换成惊叹号 !;
  6. 把原文中所有独立的 can you 换成 I can —— 这里“独立”是指被空格或标点符号分隔开的单词;
  7. 在一行中输出替换后的句子作为 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

输出样例:

在这里给出相应的输出。例如:

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: could you show you 5
What Is this prime? I,don 't know
AI: what Is this prime! you,don't know

然后呢,我在老师课上教给我们的代码的基础上,再去弄了一个将can you转换成I can的函数,然后兴致勃勃地打算要提交代码,结果,出现的是这么一幅画面:

嘻嘻,全部测试点都是格式错误,我还真的以为我是哪里的空格没有处理好。可是明明我在本地运行一切正常呀。

下面附上我这段优秀的代码:

#include <iostream>
#include <cstring>
#include <cstdio> 

using namespace std;

void go(string s);//对输入字符的处理并进行相应转换 
bool isIndependent(char ch);
bool isfuhao(char ch1);//判断后一个是否为标点符号 
bool iscanyou(char t[], int j);//判断can you是否独立 

int main()
{
    int n;
    string s[11];
    cin >> n;
    getchar();//吸收回车键 
    for(int i=0; i<n; i++)
    {
        getline(cin, s[i]);//读入字符 
        
    }
    for(int i=0; i<n; i++)
    {
        cout << s[i] << endl;
        cout << "AI:";
        go(s[i]); //根据s输出AI的回答 
    }
    return 0;
}
void go(string s)
{//根据s输出AI的回答
      char t[3001];//存储字符串s处理后的字符串 
      int i = 0,j = 0;
      for(; s[i]!='\0' && s[i]==' '; ++i);
       while(s[i] != '\0')
       {//把s串copy到t,连续空格只copy一个空格 
           if(s[i] == ' '&&s[i-1] == ' ')//消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
        {
               ++i;
            continue;
        }
           if(s[i] == '?')//把原文中所有的问号 ? 换成惊叹号 !;
        {
               t[j++] = '!';
               i++;
               continue;
           }
           if(s[i] != 'I')//把原文中所有大写英文字母变成小写,除了'I' 
           {
               t[j++] = tolower(s[i++]);
               continue;
           }
           
        t[j++] = s[i++];
       }
       
       t[j] = '\0';
    
    j = 0;
    while(t[j] != '\0')
    {
        if(t[j]=='I' && (j==0 || isIndependent(t[j-1])) && isIndependent(t[j+1]))//将'I'转换成'you' 
        {
            cout << "you";
            ++j;
            continue;
        }
        if(t[j]=='m' && t[j+1]=='e' && (j==0 || isIndependent(t[j-1])) && isIndependent(t[j+2]))//将'me'转换成'you'
        {
            cout << "you";
            j = j+2;
            continue;
        }
        if(t[j]==' '&& isfuhao(t[j+1]))
        {   
            ++j;
            continue;
        }
        if(iscanyou(t, j))//将can you转换成I can 
        {
            cout << "I can";
            j = j+7;
            continue;
        }
        if(s[j]==' '&&s[j+1]=='\0')//处理结尾的空格问题 
        {
            ++j;
            continue;
        }  
        cout << t[j++];
    }  
    cout << endl;          
}


bool isIndependent(char ch)//判断是否独立 
{
    ch = tolower(ch);
    if((ch>'0' && ch<'9') || (ch>'a' && ch<'z'))
        return false;
    else
        return true;
}

bool isfuhao(char ch1)//判断后一个字符是否为标点符号 
{  
    ch1=tolower(ch1);  //先转换成小写方便下面的条件判断 
    if(ch1>='0'&&ch1<='9' || ch1>='a'&&ch1<='z' || ch1=='I' || ch1==' ') 
        return false;
    else
        return true;
}

bool iscanyou(char t[], int j)//判断can you是否独立 
{
    if(t[j]=='c' && t[j+1]=='a' && t[j+2]=='n' && t[j+3]==' ' && t[j+4]=='y' && t[j+5]=='o' && t[j+6]=='u' && (j==0 || isIndependent(t[j-1])) && isIndependent(t[j+7]))
        return true;
    else
        return false;
} 
View Code

最开始我遇到的问题就是我每次只要一输入一个字符串就马上输出答案,我感觉这应该不对,应该是全部的都输入完之后才把结果给输出,所以我在主函数中的代码就是这么写:

int main()
{
    int n;
    string s[11];
    cin >> n;
    getchar();//吸收回车键 
    for(int i=0; i<n; i++)
    {
        getline(cin, s[i]);//读入字符 
        
    }
    for(int i=0; i<n; i++)
    {
        cout << s[i] << endl;
        cout << "AI:";
        go(s[i]); //根据s输出AI的回答 
    }
    return 0;
}
View Code

最开始不确定string类是否可以弄成数组,只是抱着试一试的心态,诶,没想到真的可以!

这里是相关的知识:

https://blog.csdn.net/BlackPlus28/article/details/82949351

之后提交得到0分我也还是没有意识到我主函数里这么操作是不符的

直到实在找不出其他别的问题了,我又回到主函数这里寻找问题

然后觉得可能是这么先全部输入再全部输出的操作存在问题

我才试着将主函数的操作改成这样的代码:

int main()
{
    int n;
    string s;
    cin >> n;
    getchar();//吸收回车键 
    for(int i=0; i<n; i++)
    {
        getline(cin, s);
        cout << s << endl;
        cout << "AI: ";
        go(s);
    }
    return 0;
}
View Code

 

然后再次提交

感动的事情终于发生!

红色的“答案正确”真的超级好看!

原来我一直就是错在了这个地方

唉,真的不应该!

不过经过这次也让我明白了明明你在本地跑全都正确可在pta上全部显示格式错误意味着的意思。

那我先把正确的完整代码发下:

#include <iostream>
#include <cstring>
#include <cstdio> 

using namespace std;

void go(string s);//对输入字符的处理并进行相应转换 
bool isIndependent(char ch);
bool isfuhao(char ch1);//判断后一个是否为标点符号 
bool iscanyou(char t[], int j);//判断can you是否独立 

int main()
{
    int n;
    string s;
    cin >> n;
    getchar();//吸收回车键 
    for(int i=0; i<n; i++)
    {
        getline(cin, s);
        cout << s << endl;
        cout << "AI: ";
        go(s);
    }
    return 0;
}
void go(string s)
{//根据s输出AI的回答
      char t[3001];//存储字符串s处理后的字符串 
      int i = 0,j = 0;
      for(; s[i]!='\0' && s[i]==' '; ++i);
       while(s[i] != '\0')
       {//把s串copy到t,连续空格只copy一个空格 
           if(s[i] == ' '&&s[i-1] == ' ')//消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
        {
               ++i;
            continue;
        }
           if(s[i] == '?')//把原文中所有的问号 ? 换成惊叹号 !;
        {
               t[j++] = '!';
               i++;
               continue;
           }
           if(s[i] != 'I')//把原文中所有大写英文字母变成小写,除了'I' 
           {
               t[j++] = tolower(s[i++]);
               continue;
           }
           
        t[j++] = s[i++];
       }
       
       t[j] = '\0';//当string字符串遇到'\0'时会停下来,不会讲'\0'传给t数组,所以需要我们自己给t数组加上'\0' 
    
    j = 0;//将j重新赋值为0 
    while(t[j] != '\0')
    {
        if(t[j]=='I' && (j==0 || isIndependent(t[j-1])) && isIndependent(t[j+1]))//将'I'转换成'you' 
        {
            cout << "you";
            ++j;
            continue;
        }
        if(t[j]=='m' && t[j+1]=='e' && (j==0 || isIndependent(t[j-1])) && isIndependent(t[j+2]))//将'me'转换成'you'
        {
            cout << "you";
            j = j+2;
            continue;
        }
        if(t[j]==' '&& isfuhao(t[j+1]))
        {   
            ++j;
            continue;
        }
        if(iscanyou(t, j))//将can you转换成I can 
        {
            cout << "I can";
            j = j+7;
            continue;
        }
        if(s[j]==' '&&s[j+1]=='\0')//处理结尾的空格问题 
        {
            ++j;
            continue;
        }  
        cout << t[j++];
    }  
    cout << endl;          
}


bool isIndependent(char ch)//判断是否独立 
{
    ch = tolower(ch);
    if((ch>'0' && ch<'9') || (ch>'a' && ch<'z'))
        return false;
    else
        return true;
}

bool isfuhao(char ch1)//判断后一个字符是否为标点符号 
{  
    ch1=tolower(ch1);  //先转换成小写方便下面的条件判断 
    if(ch1>='0'&&ch1<='9' || ch1>='a'&&ch1<='z' || ch1=='I' || ch1==' ') 
        return false;
    else
        return true;
}

bool iscanyou(char t[], int j)//判断can you是否独立 
{
    if(t[j]=='c' && t[j+1]=='a' && t[j+2]=='n' && t[j+3]==' ' && t[j+4]=='y' && t[j+5]=='o' && t[j+6]=='u' && (j==0 || isIndependent(t[j-1])) && isIndependent(t[j+7]))
        return true;
    else
        return false;
} 
View Code

 

下面我来分享一下其他一些部分中存在的一些注意事项:

        t[j] = '\0';//当string字符串遇到'\0'时会停下来,不会讲'\0'传给t数组,所以需要我们自己给t数组加上'\0' 
    
    j = 0;//将j重新赋值为0     
View Code

首先是要记得给t数组最后加上'\0',不然之后的操作会发生错误;

其次要记得将j重新赋值为0。

 

还有:

bool isfuhao(char ch1)//判断后一个字符是否为标点符号 
{  
    ch1=tolower(ch1);  //先转换成小写方便下面的条件判断 
    if(ch1>='0'&&ch1<='9' || ch1>='a'&&ch1<='z' || ch1=='I' || ch1==' ') 
        return false;
    else
        return true;
}
View Code

治理if里的判断条件不能少了对'I'的判断,因为在上述操作中并没有将'I'转换成小写;

然后我们可以发现我们判断其是否为标点符号时

是判断其如果它不是数字不是英文字母或者是'I'或空格

而非直接判断它是否是什么‘,’、‘.’等等的标点符号

省去了一大堆的功夫来判断是否为各种标点符号的麻烦

这种逆思想以后可以试着多用。

 

还有:

bool iscanyou(char t[], int j)//判断can you是否独立 
{
    if(t[j]=='c' && t[j+1]=='a' && t[j+2]=='n' && t[j+3]==' ' && t[j+4]=='y' && t[j+5]=='o' && t[j+6]=='u' && (j==0 || isIndependent(t[j-1])) && isIndependent(t[j+7]))
        return true;
    else
        return false;
} 
View Code

首先if里面的判断条件我个人认为是跟前面跟'me'转成'you'差不多思路的

都要注意临界情况的判断

然后iscanyou后面括号里的形参我最开始没想明白

之后考虑到可以先定义好数组再定义下标

才把这个问题给解决

 

最后给个有关tolower函数和toupper函数知识的链接:

https://blog.csdn.net/laozhuxinlu/article/details/51539737

 

希望下次能够不再把大把时间花在一些很简单但又很难发现的小问题上!!!

加油!!!

 





posted @ 2019-04-14 23:42  07-14  阅读(178)  评论(1编辑  收藏  举报