简体   繁体   English

控制台输出不断崩溃

[英]Console output keeps crashing

Trying to solve this Problem . 试图解决这个问题 I have written the code which looks like this: 我编写了如下代码:

#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;
}

It works perfectly, at least on the given example when I run it using file I/O(fstream) but when i use console I/O as is the code given it crashes after reading the second number for test case. 它运行良好,至少在给定的示例中,当我使用文件I / O(fstream)运行它时,但是当我使用控制台I / O时,给定的代码在读取测试用例的第二个数字后崩溃。

Like this: 像这样:
2 2
4 4
Begin on Road A 在路A开始
Right on Road B 在B路右
Right on Road C 在C路右
Left on Road D (reads and prints what should be printed until here) 留在D路(读取并打印在此之前应打印的内容)
6 (reads this and goes to new line) 6 (阅读并转到新行)
(crashes) Begin on Old Madras Road (崩溃)从老马德拉斯路开始
Left on Domlur Flyover 左转到Domlur天桥
Left on 100 Feet Road 左转至100英尺路
Right on Sarjapur Road 就在Sarjapur Road
Right on Hosur Road 就在Hosur路上
Right on Ganapathi Temple Road 就在Ganapathi Temple Road上

Where is my mistake? 我的错误在哪里?

Welcome to SO. 欢迎来到SO。

If you say that your program "crashes", you should also say how it crashes and if possible quote the exact output that shows how it is crashing. 如果您说程序“崩溃”,则还应该说它是如何崩溃的,并且如果可能,请引用显示它崩溃的确切输出。 Many people who might be able to help will not bother if they have to work out what the problem really is as well as solve it. 许多人谁可能是能够帮助不会打扰他们是否有制定出真正的问题什么,以及解决它。

If your question is about a coding problem, like yours, it is also important to tag your question with the name of the programming language you are coding in - in your case C++. 如果您的问题是关于编码的问题,例如您的问题,则使用您正在编码的编程语言的名称(对于您的C ++)标记问题也很重要。 If you don't, then most C++ programmers who could help will simply never notice your question. 如果您不这样做,那么大多数可以提供帮助的C ++程序员将永远不会注意到您的问题。 (I have now tagged your question C++.) (我现在标记了您的问题C ++。)

And if you are programming in a compiled language, like C++, it is also helpful to say what compiler you are using, and what version of that compiler, - eg "GCC 4.7.2", "MS VC++ 2012" - because then programmers can try to reproduce the problem using the same one. 而且,如果您使用的是C ++之类的编译语言进行编程,那么说出您使用的是哪个编译器以及该编译器的哪个版本(例如“ GCC 4.7.2”,“ MS VC ++ 2012”)也很有帮助,因为程序员可以尝试使用相同的方法重现该问题。 It is quite common for coding problems to be in some way dependent on the compiler or compiler version being used. 编码问题在某种程度上取决于所使用的编译器或编译器版本是很常见的。

I have built your program with GCC 4.7.2 and clang 3.2 on Linux and it executes the test case that you have given with no problems when I enter the input lines from the console. 我已经在Linux上使用GCC 4.7.2和clang 3.2构建了您的程序,当我从控制台输入输入行时,它可以毫无问题地执行您给出的测试用例。

This leaves me to speculate what you mean when you say it "crashes", and this is what I speculate: 这使我可以推测您说“崩溃”时的意思,这就是我的推测:

I think you may mean that after you enter "6", the program terminates with an error diagnostic something like: 我认为您的意思可能是,输入“ 6”后,程序将终止并显示以下错误诊断信息:

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

If I am wrong about that, feel free to stop reading now. 如果我对此有误,请立即停止阅读。

If I am right about that, then the diagnostic is telling you that in your call a.substr(j,a.size()-1) , the index j is out of range. 如果我对此表示正确,那么诊断将告诉您在调用a.substr(j,a.size()-1) ,索引j超出范围。

If j is out of range at that point, then it must have got out of range as a result of the preceding line j=a.find(" on ") . 如果j在那一点超出范围,那么由于前一行j=a.find(" on ")的结果,它一定已经超出范围。 And that can only mean that a.find(" on ") failed to find " on " at any place in a . 这只能意味着a.find(" on ")未能找到" on "在任何地方a

Look up the documentation of std::string::find , eg here and read about the returned value: 查找std::string::find的文档,例如此处,并了解返回的值:

If no matches were found, the function returns string::npos. 如果未找到匹配项,则该函数返回string :: npos。

which is (size_t)-1 , and is assuredly out of range. 这是(size_t)-1 ,并且肯定超出范围。

Next, if a.find(" on ") is failing, that can only mean that the preceding line getline(cin,a) is failing at that point to read a line from cin that contains " on " . 接下来,如果a.find(" on ")失败,那仅意味着前一行getline(cin,a)在该点上无法从cin读取包含" on " And we know that is true! 我们知道这是真的! Because you say that the program crashes right after it has read "6" and printed the required newline. 因为您说程序在读取“ 6”并打印所需的换行符后立即崩溃。

So that getline(cin,a) must be reading a line from the console after the "6" but before "Begin on Old Madras Road". 这样getline(cin,a)必须读从控制台线 ,“6”,但之前 “开始对旧马德拉斯路”。 An empty line. 空行。 And that is what it would do if you happened to press [Enter] just a bit too long when entering the "6", so that the keyboard buffer contains "6\\n\\n", or maybe "6\\n\\n\\n", instead of just "6\\n". 这就是如果您在输入“ 6”时碰巧按[Enter]的时间太长会导致键盘缓冲区包含“ 6 \\ n \\ n”或“ 6 \\ n \\ n \\” n”,而不仅仅是“ 6 \\ n”。 Your call to cin.ignore() , after reading the integer, will consume only one following character, because you are accepting the default arguments of: 读取整数后,对cin.ignore()调用将仅占用以下一个字符,因为您接受的默认参数为:

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

As I say, your program works fine for me. 正如我所说,您的程序对我来说很好用。 But I can make it crash in the way I described by pressing [Enter] either too long when I enter the test case line-count - either the first time or the second time - or by pressing [Enter] again after I have done so. 但我可以使它在我描述按下方式崩溃[Enter]或者太长时间,当我进入测试用例行数-无论是第一次还是第二次-或者按[Enter]后,再次我这样做。 Either way, I am inputting an empty line to getline(cin,a) . 无论哪种方式,我都向getline(cin,a)输入一个空行。

If I am right so far, then a serious error in your code is that you are not checking that std::string::find() is successful on an input string and just assuming that it is . 如果到目前为止我是对的,则您的代码中的一个严重错误是您没有检查输入字符串上的std::string::find()是否成功,而只是假设它是 Even if I am not right, that is serious error. 即使我不正确,那也是严重的错误。

You can stop your program from crashing when the user's finger stays too long on [Enter] by ensuring that cin ignores all the newlines it can read after cin>>n . 当用户的手指在[Enter]上停留的时间过长时,可以确保cin忽略cin>>n之后可以读取的所有换行符,从而防止程序崩溃。 You must look at the next character, if any, without extracting it; 您必须查看下一个字符(如果有)而不提取它; check if it is a newline, and if it is then extract it and repeat. 检查它是否为换行符,然后将其提取并重复。 Replace cin.ignore() with: cin.ignore()替换为:

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

However this will not prevent your program from crashing in the same way if the user happens to mistakenly enter a route-line that does not contain " on " : try it with "Left On Domlur Flyover". 但是,如果用户碰巧错误地输入了一个不包含" on "的路线,则这不会阻止您的程序以相同的方式崩溃:尝试使用“ Left On Domlur Flyover”进行尝试。

To fix this bug you must check that j=a.find(" on ") is successful and handle the situation when it is not. 要修复此错误,您必须检查j=a.find(" on ")是否成功,并处理不成功的情况。 Here is complete fix for what I think is the problem, built with GCC 4.7.2 and clang 3.2: 这是我认为是用GCC 4.7.2和clang 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;
}

Notice I have also corrected a couple of minor defects:- 注意,我还纠正了一些小缺陷:

  • No need for any global variables. 不需要任何全局变量。 It is good practice to avoid globals if possible and to declare variables in the smallest possible scope. 最好避免在可能的情况下使用全局变量,并在尽可能小的范围内声明变量。

  • I have changed the type of i,j,n from int to size_t . 我将i,j,n的类型从int更改为size_t Variables that used to hold the return value of some_class::some_method() or the return value of some_function() , or are compared with that return value, are best declared with the same type as that return value to avoid bugs and compiler warnings: string::find() and vector::size() return size_t , which is not the same as int . 最好将用于保存some_class::some_method()的返回值或some_function()的返回值的变量或与该返回值进行比较的变量声明为与该返回值相同的类型,以避免出现错误和编译器警告: string::find()vector::size()返回size_t ,与int

PS Investigate what goes wrong, either with your original program or mine, if the user mistakenly enters one of the integer inputs as, say, "y" or "6y" instead of "6". PS如果用户错误地输入整数输入之一,例如“ y”或“ 6y”而不是“ 6”,请调查原始程序或我的程序出了什么问题。 How could you fix that? 您该如何解决?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM