控制台输出不断崩溃

时间:2013-05-04 19:02:11

标签: c++ string console iostream getline

尝试解决此问题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时,给定的代码在读取测试用例的第二个数字后崩溃。 / p>

像这样:
2
4
从A路开始 就在B路上 就在C路上 离开道路D (读取并打印应该打印的内容直到此处)
6 (读取并转到新行)
(崩溃)从Old Madras Road开始 留在Domlur天桥上 离开100英尺路 就在Sarjapur路上 就在Hosur Road上 就在Ganapathi Temple Road上

我的错误在哪里?

1 个答案:

答案 0 :(得分: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 ")" on "的任何地方a未能找到std::string::find

查看(size_t)-1的文档,例如 here 并阅读有关返回值的信息:

  

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

a.find(" on "),并且肯定超出了范围。

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

所以[Enter]必须在之后从控制台读取一行 “6”但之前“从马德拉斯老路开始”。空行。那是什么 如果你碰巧按cin.ignore()时间太长,它会怎么做 进入“6”,键盘缓冲区包含“6 \ n \ n”,或者可能 “6 \ n \ n \ n”,而不只是“6 \ n”。阅读后,您致电std::istream& std::istream::ignore(std::streamsize n = 1, int delim = EOF) 整数,只会消耗一个后面的字符,因为你是 接受默认参数:

[Enter]

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

如果我到目前为止是正确的,那么代码中的一个严重错误就是你不是 检查[Enter]在输入字符串上是否成功 假设它是。即使我不对,那也是严重的错误。

当用户的手指停留时,您可以阻止程序崩溃 cin确保cin>>n忽略所有新行,cin.ignore()for ( ;cin.peek() == '\n'; cin.ignore()){} 之后阅读。你必须看下一个角色,如果有的话, 没有提取它;检查它是否是换行符,如果是,则将其解压缩 并重复。将" on "替换为:

j=a.find(" on ")

但是,这不会阻止您的程序以相同的方式崩溃 用户碰巧错误地输入了不包含#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; } 的路线: 尝试使用“Left On Domlur Flyover”。

要修复此错误,您必须检查i,j,n是否成功 处理不是的情况。这是完全解决我认为的问题,用GCC 4.7.2构建 和铿锵3.2:

int

注意我还纠正了一些小缺陷: -

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

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

P.S。使用原始程序调查出错的地方 我的,如果用户错误地输入了一个整数输入,比方说, “y”或“6y”而不是“6”。你怎么能解决这个问题?