【问题标题】:Console output keeps crashing控制台输出不断崩溃
【发布时间】:2013-04-28 23:27:52
【问题描述】:

试图解决这个问题Problem。 我编写了如下代码:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int i,j,n,t;

int main()
{
cin>>t;

while(t--)
{
    vector <string> dr,rd;
    string a,b;
    cin>>n;
    cin.ignore();

    for(i=0;i<n;i++)
    {
        a.clear(),b.clear();
        getline(cin,a);
        j=a.find(" on ");
        b=a.substr(j,a.size()-1);
        a.resize(j);
        dr.push_back(a);
        rd.push_back(b);
    }

    for(i=0,j=rd.size()-1;i<rd.size();i++,j--)
    {
        cout<<dr[i]<<rd[j]<<endl;
    }
    cout<<endl;
}

return 0;
}

它完美地工作,至少在给定的示例中,当我使用文件 I/O(fstream) 运行它时,但是当我使用控制台 I/O 时,给出的代码在读取测试用例的第二个数字后崩溃。

像这样:
2
4
从 A 路开始
就在 B 路
就在 C 路
在 D 路左转(读取并打印应该打印到这里的内容)
6 (阅读此内容并换行)
(崩溃) 从旧马德拉斯路开始
离开 Domlur 立交桥
离开 100 英尺路
就在 Sarjapur 路
就在 Hosur 路
就在 Ganapathi Temple Road

我的错误在哪里?

【问题讨论】:

    标签: c++ string console iostream getline


    【解决方案1】:

    欢迎来到 SO。

    如果你说你的程序“崩溃”,你也应该说如何它崩溃了 如果可能的话,引用显示它是如何崩溃的确切输出。许多 如果他们必须工作,可能能够提供帮助的人不会打扰 找出真正的问题是什么并解决它。

    如果您的问题是关于编码问题的,就像您的问题一样,这也很重要 用您所使用的编程语言的名称标记您的问题 编码 - 在你的情况下是 C++。如果你不这样做,那么大多数 C++ 程序员 可以帮助根本不会注意到您的问题。 (我现在已经标记了你的 问题 C++。)

    如果您使用编译型语言(如 C++)进行编程,它也是 有助于说明您正在使用什么编译器,以及该编译器的版本, - 例如“GCC 4.7.2”、“MS VC++ 2012”——因为那时程序员可以尝试 使用相同的问题重现问题。编码很常见 问题在某种程度上取决于编译器或编译器版本 用过。

    我在 Linux 上使用 GCC 4.7.2 和 clang 3.2 构建了您的程序,它执行了测试 当我从 控制台。

    这让我猜测你说它“崩溃”是什么意思,而这 是我推测的:

    我想你的意思可能是在你输入“6”后,程序以 错误诊断类似于:

    terminate called after throwing an instance of 'std::out_of_range'
      what():  basic_string::substr
    Aborted
    

    如果我对此有误,请立即停止阅读。

    如果我的判断是正确的,那么诊断会告诉您,在您的 调用a.substr(j,a.size()-1),索引j超出范围。

    如果此时j 超出范围,那么它一定超出范围 上一行 j=a.find(" on ") 的结果。这只能意味着 a.find(" on ") 在a 的任何地方都找不到" on "。

    查找std::string::find 的文档,例如 here 并阅读返回值:

    如果未找到匹配项,则该函数返回 string::npos。

    这是(size_t)-1,肯定超出范围。

    接下来,如果a.find(" on ") 失败,那只能意味着 前一行getline(cin,a) 无法从cin 读取一行 包含" on "。我们知道这是真的!因为你说程序 在读取“6”并打印所需的换行符后立即崩溃。

    所以getline(cin,a) 必须从控制台读取一行之后 “6”但之前“从旧马德拉斯路开始”。一个空行。这就是 如果你碰巧按下[Enter] 有点太长了 输入“6”,以便键盘缓冲区包含“6\n\n”,或者可能 “6\n\n\n”,而不仅仅是“6\n”。阅读后致电cin.ignore() 整数,只会消耗 一个 跟随字符,因为你是 接受以下默认参数:

    std::istream& std::istream::ignore(std::streamsize n = 1, int delim = EOF)  
    

    正如我所说,您的程序对我来说很好。但我可以让它在 我在进入测试时按[Enter] 描述的方式太长了 case line-count - 第一次或第二次 - 或按 在我这样做之后再次[Enter]。无论哪种方式,我都在输入一个空行 到getline(cin,a)。

    如果到目前为止我是对的,那么您的代码中的一个严重错误是 您不是 检查std::string::find() 在输入字符串上是否成功并且只是 假设它是。即使我说的不对,那也是严重的错误。

    当用户的手指也停留时,您可以阻止程序崩溃 通过确保 cin 忽略 all 它可以忽略的换行符,长期坚持 [Enter] 在cin&gt;&gt;n 之后阅读。你必须看看下一个字符,如果有的话, 不提取它;检查它是否是换行符,如果是则提取它 并重复。将cin.ignore() 替换为:

    for (   ;cin.peek() == '\n'; cin.ignore()){}
    

    但是,这不会阻止您的程序以同样的方式崩溃,如果 用户碰巧错误地输入了不包含" on " 的路由行: 试试“Left On Domlur Flyover”。

    要修复此错误,您必须检查 j=a.find(" on ") 是否成功并且 处理情况,当它不是。这是我认为是问题的完整解决方案,使用 GCC 4.7.2 构建 和铿锵3.2:

    #include <iostream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
    
    int t;
    
    cin>>t;
    
    while(t--)
    {
        vector <string> dr,rd;
        string a,b;
        size_t i,j,n;
        cin>>n;
        for (   ;cin.peek() == '\n'; cin.ignore()){}
    
        for(i=0;i<n;i++)
        {
            a.clear(),b.clear();
            getline(cin,a);
            j=a.find(" on ");
            if (j == string::npos) {
                cout << "Invalid direction. Try again" << endl;
                --i;
                continue;
            }
            b=a.substr(j,a.size()-1);
            a.resize(j);
            dr.push_back(a);
            rd.push_back(b);
        }
    
        for(i=0,j=rd.size()-1;i<rd.size();i++,j--)
        {
            cout<<dr[i]<<rd[j]<<endl;
        }
        cout<<endl;
    }
    
    return 0;
    }
    

    请注意,我还纠正了几个小缺陷:-

    • 不需要任何全局变量。避免全局变量是一个好习惯 如果可能,并在尽可能小的范围内声明变量。

    • 我已将i,j,n 的类型从int 更改为size_t。变量 用于保存some_class::some_method() 的返回值或 some_function() 的返回值,或与该返回值进行比较, 最好使用与返回值相同的类型声明以避免错误和 编译器警告:string::find() 和 vector::size() 返回 size_t, 这与int 不同。

    P.S. 调查问题所在,无论是使用您的原始程序还是 我的,如果用户错误地输入整数输入之一,例如, “y”或“6y”而不是“6”。你怎么能解决这个问题?

    【讨论】:

      猜你喜欢
      • 2017-04-09
      • 1970-01-01
      • 1970-01-01
      • 2012-06-03
      • 2022-12-21
      • 2014-04-23
      • 1970-01-01
      • 2021-10-05
      • 1970-01-01
      相关资源
      最近更新 更多