【问题标题】:Input 7 letter word, output 7 digit phone number输入7个字母单词,输出7位电话号码
【发布时间】:2021-01-02 23:19:05
【问题描述】:

我正在为作业编写代码。我输入 7 个字母,它会在小键盘上输出相应的数字。到目前为止,它可以很好地转换字母,它忽略了我想要的第 7 个字母之后的所有内容,并在您键入 stop 时停止。但是,如果我包含空格(这是分配所必需的)它会引发错误,我写了一些应该让它忽略它们但它不起作用的东西。此外,如果我输入的任何内容少于 7​​ 个字母,我也会收到错误消息。 “在抛出 'std::out_of_range' 的实例后调用终止 what(): basic_string::at: _n (which is 1) >= this->size() (which is 1) Aborted (core dumped)

我很确定这是因为 while 循环,在调试器中,它总是停在那里,但我不知道如何解决这个问题。我期待收到任何人的来信。提前谢谢!

#include <iostream>
#include <string>

using namespace std;

int main(){
    //declares variables
    string str1, str2;
    int i;
    //first input
    cout << "Type 'stop' to stop or type your 7 letter message to be converted to numbers: " << endl;
    cin >> str1;
    
    //while loop so that you can input multiple numbers one after the other until stop is read
    while (str1 != "stop"){
        //resets i if str1 does not equal stop
        i=0;
        while(str2.length() != 7){
            //determines what number to assign to the charcter at the index of the i variable
            if (str1.at(i) == 'a' || str1.at(i) == 'A' || str1.at(i) == 'b' || str1.at(i) == 'B' || str1.at(i) == 'c' || str1.at(i) == 'C'){
                str2 = str2 + '2';
                i=i+1;
            }else if (str1.at(i) == 'd' || str1.at(i) == 'D' || str1.at(i) == 'e' || str1.at(i) == 'E' || str1.at(i) == 'f' || str1.at(i) == 'F'){
                str2 = str2 + '3';
                i=i+1;
            }else if (str1.at(i) == 'g' || str1.at(i) == 'G' || str1.at(i) == 'h' || str1.at(i) == 'H' || str1.at(i) == 'i' || str1.at(i) == 'I'){
                str2 = str2 + '4';
                i=i+1;
            }else if (str1.at(i) == 'j' || str1.at(i) == 'J' || str1.at(i) == 'k' || str1.at(i) == 'K' || str1.at(i) == 'l' || str1.at(i) == 'L'){
                str2 = str2 + '5';
                i=i+1;
            }else if (str1.at(i) == 'm' || str1.at(i) == 'M' || str1.at(i) == 'n' || str1.at(i) == 'N' || str1.at(i) == 'o' || str1.at(i) == 'O'){
                str2 = str2 + '6';
                i=i+1;
            }else if (str1.at(i) == 'p' || str1.at(i) == 'P' || str1.at(i) == 'q' || str1.at(i) == 'Q' || str1.at(i) == 'r' || str1.at(i) == 'R'|| str1.at(i) == 's' || str1.at(i) == 'S'){
                str2 = str2 + '7';
                i=i+1;
            }else if (str1.at(i) == 't' || str1.at(i) == 'T' || str1.at(i) == 'u' || str1.at(i) == 'U' || str1.at(i) == 'v' || str1.at(i) == 'V'){
                str2 = str2 + '8';
                i=i+1;
            }else if (str1.at(i) == 'w' || str1.at(i) == 'W' || str1.at(i) == 'x' || str1.at(i) == 'X' || str1.at(i) == 'y' || str1.at(i) == 'Y'|| str1.at(i) == 'z' || str1.at(i) == 'Z'){
                str2 = str2 + '9';
                i=i+1;
            }else if(str1.at(i) == ' '){
                //if there is a space, it is ignored
                i=i+1;
            }else{
                //in case they put somthing weird, sets str2 to length of 7 to end while
                cout << "incorrect input";
                str2 = "abcdefg";
            }
        }
        //outputs converted number
        cout << str2.substr(0,3) << "-" << str2.substr(3,7) << endl << endl;
        cout << "Type 'stop' to stop or type your 7 letter message to be converted to numbers: " << endl;
        cin >> str1;
        //resets str2
        str2 = "";
        
    }
    return 0;
}

【问题讨论】:

  • 您应该使用std::getline() 并检查输入的长度以避免错误。
  • while(str2.length() != 7){ 将循环直到长度为 7。如果输入字符串少于 7 个字符,这是您想要的吗?
  • 我在底部添加了一个 if 语句,如果遇到任何错误输入,将 str2 设置为 7 长度的字符串以结束 while 循环,但它不起作用。
  • getline 帮助解决了空格问题,谢谢!它现在忽略空格并正确输出。但是,如果字符串太短,我仍然会收到错误。
  • 如果我添加了一个 if 语句来检查以确保 str1 的长度大于 7,输入“asdf”将触发 if 语句,但仍然会发生错误,因为 while 循环忽略了空格.

标签: c++ string error-handling c++14


【解决方案1】:
  • 您应该使用std::getline() 来读取整行,即使它包含空白字符。
  • 您应该检查输入字符串的长度并在字符串末尾停止以避免出现std::out_of_range 错误。
#include <iostream>
#include <string>

using namespace std;

int main(){
    //declares variables
    string str1, str2;
    int i;
    //first input
    cout << "Type 'stop' to stop or type your 7 letter message to be converted to numbers: " << endl;
    getline(cin, str1); // *** use std::getline()
    
    //while loop so that you can input multiple numbers one after the other until stop is read
    while (str1 != "stop"){
        //resets i if str1 does not equal stop
        i=0;
        while(str2.length() != 7){
            //determines what number to assign to the charcter at the index of the i variable
            if (i >= str1.length()) { // *** length check
                cout << "input too short";
                str2 = "abcdefg";
            }else if (str1.at(i) == 'a' || str1.at(i) == 'A' || str1.at(i) == 'b' || str1.at(i) == 'B' || str1.at(i) == 'c' || str1.at(i) == 'C'){
                str2 = str2 + '2';
                i=i+1;
            // *** omit ***
            }else{
                //in case they put somthing weird, sets str2 to length of 7 to end while
                cout << "incorrect input";
                str2 = "abcdefg";
            }
        }
        //outputs converted number
        cout << str2.substr(0,3) << "-" << str2.substr(3,7) << endl << endl;
        cout << "Type 'stop' to stop or type your 7 letter message to be converted to numbers: " << endl;
        getline(cin, str1); // *** use std::getline()
        //resets str2
        str2 = "";
        
    }
    return 0;
}

【讨论】:

  • 效果很好,非常感谢!我知道这将是一个我没有想到的简单解决方案。我真的很感激!
【解决方案2】:
  1. 问题是由cin引起的: cin 将空格(空格、制表符等)视为终止字符,这意味着它只能显示一个单词(即使您输入了很多单词)。[https://www.w3schools.com/cpp/ cpp_strings_input.asp]
  2. 您还必须将 while 条件从 while(str2.length() != 7) 更改为 while(i != 7),因为 else if(str1.at(i) == ' ') 只会增加 i 而不是 str2

【讨论】:

    【解决方案3】:

    您的代码中的主要问题是输入,因为当遇到空格字符时 cin 会处理字符串的输入。另一个问题是关于不总是满足的最小长度的假设。

    这不是您的问题的原因,但命名变量可以帮助您的代码更清晰(例如input, output 而不是str1 and str2)。最后,还有比长 if 更简单的方法来获得正确的编码:

    int main(){
        string input, output, mapin ="abcdefghijklmnopqrstuvwxyz", 
                              mapout="22233344455566677778889999";
        cout << "Type 'stop' to stop or type your 7 letter message to be converted to numbers: " << endl;
        
        bool input_ok=true; 
        while (cin >> input) {
            for (auto &c: input)
                c = tolower(c);    // lowercase,  just to simplify
            if (input=="stop" || output.size()==7) 
                break;              // reasons to stop reading 
            
            for (auto &c:input) {
                auto pos=mapin.find(c); 
                if (pos==string::npos) {
                    input_ok=false; 
                    output += '?';
                }
                else output += mapout[pos];
                if (output.size()==7)
                    break;
            }
        }
        if (input_ok) {
            cout << output.substr(0,3)  ;
            if (output.size()>3) 
                cout << "-" << output.substr(3,7) ;
            cout << endl << endl;
        }
        else {
            cout << "incorrect input" << endl <<output<<endl;
        }
        return 0;
    }
    

    Online demo

    为了便于处理,我首先将字符串转换为小写,然后 STOP、StOp 或 stop 都可以。然后我运行几个输入,以捕获可能由空格分隔的几组字母(空白,制表符,换行符,...)。然后对于每个字母,我在输入表中查找它的偏移量,并在输出表中使用相同偏移量的数字。

    另一种变体是计算输出字符:

      for (auto &c:input) {
            if (isalpha(c)) 
                output += (c>='w'? '9' : (c>='p'? "78"[(c-'p')/4]:'2'+(c-'a')/3));
            else {
                input_ok=false; 
                output += '?';
            }
            if (output.size()==7)
                break;
        }
    

    Online demo

    但您也可以坚持原来的版本,但选择 switch 语句而不是长长的 if 级联。

    【讨论】:

      猜你喜欢
      • 2020-06-06
      • 2019-12-27
      • 1970-01-01
      • 1970-01-01
      • 2021-08-15
      • 2021-01-17
      • 1970-01-01
      • 1970-01-01
      • 2022-11-30
      相关资源
      最近更新 更多