在抛出“std::out_of_range”实例后终止调用

时间:2022-01-31 01:24:24

I'm a absolute beginner for programming. I got this error while building up the following code.

我是编程的绝对初学者。在构建以下代码时,我得到了这个错误。

error: terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check: __n (which is 8) >= this->size() (which is 8) Aborted (core dumped)

#include<iostream>
#include<vector>
#include<string>
#include<iomanip>
using namespace std;
int main()
{
    cout<<"\n Welcome to space travel calculation program";

    string cPlanet, name;
    double weight, speed, tTime, nWeight;
    int num;
    vector<string> planet;
    vector<int> distance;
    vector<double> sGravity;

    planet.push_back("Mercury");
    distance.push_back(36);
    sGravity.push_back(0.27);

    planet.push_back("Venus");
    distance.push_back(67);
    sGravity.push_back(0.86);

    planet.push_back("Earth");
    distance.push_back(93);
    sGravity.push_back(1.00);

    planet.push_back("Mars");
    distance.push_back(141);
    sGravity.push_back(0.37);

    planet.push_back("Jupiter");
    distance.push_back(483);
    sGravity.push_back(2.64);

    planet.push_back("Saturn");
    distance.push_back(886);
    sGravity.push_back(1.17);

    planet.push_back("Uranus");
    distance.push_back(1782);
    sGravity.push_back(0.92);

    planet.push_back("Neptune");
    distance.push_back(2793);
    sGravity.push_back(1.44);
    num=planet.size();

    cout<<"\n Please tell me your name: ";
    getline(cin,name);


    cout<<"\n Please choose which planet you want to travel to from the following list:"
        <<"\n 1.Mercury"
        <<"\n 2.Venus"
        <<"\n 3.Earth"
        <<"\n 4.Mars"
        <<"\n 5.Jupiter"
        <<"\n 6.Saturn"
        <<"\n 7.Uranus"
        <<"\n 8.Neptune       :";
    getline(cin,cPlanet);

    cout<<"\n What is your weight on Earth?";
    cin>>weight;

    cout<<"\n At what speed do you wish to travel? :";
    cin>>speed;

    if(cPlanet==planet.at(num))
    {
        tTime=(distance.at(num))/speed;
        nWeight=weight*sGravity.at(num);

        cout<<"\n Your Name: "<<name
            <<"\n Weight On Earth: "<<weight
            <<"\n Planet you wish to visit: "<<cPlanet
            <<"\n The speed you will be travelling at: "<<speed
            <<"\n Total time it will take to reach "<<planet.at(num)<<": "<<tTime
            <<"\n Your weight on "<<planet.at(num)<<": "<<nWeight;
    }

    return 0;
}

2 个解决方案

#1


1  

Array and vector indices in C++ run from 0 to size - 1. Thus when you say

在c++中,数组和向量索引从0到size - 1。因此当你说

num=planet.size();

and later

后来

if(cPlanet==planet.at(num))

you are trying to access one past the end of the vector planet. The at member function then throws an exception of type std::out_of_range that is never caught, and your program terminates because of that.

你正试图进入矢量行星的末端。然后,在成员函数中抛出一个类型std::out_of_range,它不会被捕获,您的程序会因此终止。

It looks as though you wanted to find the vector index corresponding to a planet name; you could do that with std::find and std::distance as follows:

看起来你想要找到对应于行星名称的矢量指数;你可以用std::find和std::距离如下:

num = std::distance(planet.begin(), std::find(planet.begin(), planet.end(), cPlanet));

this will return planet.size() if cPlanet is not found. However, it would probably be nicer to implement the whole thing with a std::map.

如果没有找到cPlanet,这将返回planet.size()。但是,用std::map来实现整个过程可能会更好。

#2


0  

Here's a simpler program to reproduce the behaviour:

这里有一个简单的程序来重现这种行为:

#include <vector>

int main()
{
    std::vector<int> v;
    v.push_back(123); // v has 1 element  [0 to 0]
    v.push_back(456); // v has 2 elements [0 to 1]
    v.push_back(789); // v has 3 elements [0 to 2]
    int x1 = v.at(0); // 123
    int x2 = v.at(1); // 456
    int x3 = v.at(2); // 789
    int x4 = v.at(3); // exception
}

The at member function throws an exception if you try to access a non-existing element.

如果您试图访问一个非现有元素,那么at成员函数将抛出一个异常。

While that principally sounds like a good thing, it turns out to be pretty useless in practice. Using an illegal vector index is almost surely a programming error, and exceptions should not be thrown for programming errors.

虽然这听起来像是一件好事,但在实践中却毫无用处。使用非法的向量索引几乎肯定是一个编程错误,并且不应该抛出异常来处理编程错误。

You could catch the std::out_of_range exception to "recover" from the error or "handle" it, but seriously, what could you possibly do at such a low level of program logic?

您可以捕获std::out_of_range异常以从错误中“恢复”或“处理”它,但认真地说,您可能在如此低的程序逻辑级别上做什么?

For std::vector, prefer the [] operator. In your case:

对于std::vector,更喜欢[]操作符。在你的例子:

tTime = distance[num] / speed;

[] is like at, but takes an entirely different stance on programming errors; at is like "if you should ever call me with an illegal index, I'll throw an exception so that we can somehow carry on, shall we?", whereas with the [] operator the behaviour is undefined for illegal vector indices. This means a C++ implementation is allowed to just terminate the program without any chance of accidentally catching an exception and "continuing somehow". It depends on how you invoke the compiler and generally requires you to examine your compiler's configuration options (for example those for VC++ or those for GCC).

[]就像,但对编程错误采取完全不同的立场;就像“如果你应该给我一个非法的索引,我就会抛出一个异常,这样我们就可以继续下去了,对吗?”而对于[]运算符,则不为非法向量索引定义行为。这意味着允许一个c++实现终止程序,而不可能意外地捕获异常并“以某种方式继续”。这取决于您如何调用编译器,通常要求您检查编译器的配置选项(例如,vc++或GCC的配置选项)。

Terminating as quickly as possible is the right thing to do when you find out that your own code is wrong. Do not get used to at's behaviour.

当您发现您自己的代码是错误的时,尽快终止是正确的做法。不要习惯at的行为。

#1


1  

Array and vector indices in C++ run from 0 to size - 1. Thus when you say

在c++中,数组和向量索引从0到size - 1。因此当你说

num=planet.size();

and later

后来

if(cPlanet==planet.at(num))

you are trying to access one past the end of the vector planet. The at member function then throws an exception of type std::out_of_range that is never caught, and your program terminates because of that.

你正试图进入矢量行星的末端。然后,在成员函数中抛出一个类型std::out_of_range,它不会被捕获,您的程序会因此终止。

It looks as though you wanted to find the vector index corresponding to a planet name; you could do that with std::find and std::distance as follows:

看起来你想要找到对应于行星名称的矢量指数;你可以用std::find和std::距离如下:

num = std::distance(planet.begin(), std::find(planet.begin(), planet.end(), cPlanet));

this will return planet.size() if cPlanet is not found. However, it would probably be nicer to implement the whole thing with a std::map.

如果没有找到cPlanet,这将返回planet.size()。但是,用std::map来实现整个过程可能会更好。

#2


0  

Here's a simpler program to reproduce the behaviour:

这里有一个简单的程序来重现这种行为:

#include <vector>

int main()
{
    std::vector<int> v;
    v.push_back(123); // v has 1 element  [0 to 0]
    v.push_back(456); // v has 2 elements [0 to 1]
    v.push_back(789); // v has 3 elements [0 to 2]
    int x1 = v.at(0); // 123
    int x2 = v.at(1); // 456
    int x3 = v.at(2); // 789
    int x4 = v.at(3); // exception
}

The at member function throws an exception if you try to access a non-existing element.

如果您试图访问一个非现有元素,那么at成员函数将抛出一个异常。

While that principally sounds like a good thing, it turns out to be pretty useless in practice. Using an illegal vector index is almost surely a programming error, and exceptions should not be thrown for programming errors.

虽然这听起来像是一件好事,但在实践中却毫无用处。使用非法的向量索引几乎肯定是一个编程错误,并且不应该抛出异常来处理编程错误。

You could catch the std::out_of_range exception to "recover" from the error or "handle" it, but seriously, what could you possibly do at such a low level of program logic?

您可以捕获std::out_of_range异常以从错误中“恢复”或“处理”它,但认真地说,您可能在如此低的程序逻辑级别上做什么?

For std::vector, prefer the [] operator. In your case:

对于std::vector,更喜欢[]操作符。在你的例子:

tTime = distance[num] / speed;

[] is like at, but takes an entirely different stance on programming errors; at is like "if you should ever call me with an illegal index, I'll throw an exception so that we can somehow carry on, shall we?", whereas with the [] operator the behaviour is undefined for illegal vector indices. This means a C++ implementation is allowed to just terminate the program without any chance of accidentally catching an exception and "continuing somehow". It depends on how you invoke the compiler and generally requires you to examine your compiler's configuration options (for example those for VC++ or those for GCC).

[]就像,但对编程错误采取完全不同的立场;就像“如果你应该给我一个非法的索引,我就会抛出一个异常,这样我们就可以继续下去了,对吗?”而对于[]运算符,则不为非法向量索引定义行为。这意味着允许一个c++实现终止程序,而不可能意外地捕获异常并“以某种方式继续”。这取决于您如何调用编译器,通常要求您检查编译器的配置选项(例如,vc++或GCC的配置选项)。

Terminating as quickly as possible is the right thing to do when you find out that your own code is wrong. Do not get used to at's behaviour.

当您发现您自己的代码是错误的时,尽快终止是正确的做法。不要习惯at的行为。