抛出'std :: out_of_range'实例后调用终止

时间:2015-03-15 14:46:32

标签: c++

我是编程的绝对新手。在构建以下代码时出现此错误。

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 个答案:

答案 0 :(得分:1)

C ++中的数组和向量索引从0运行到大小 - 1.因此当你说

num=planet.size();

以后

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

您正尝试访问向量planet结束之后的at成员函数然后抛出一个永远不会被捕获的类型std::out_of_range的异常,并且程序因此终止。

看起来好像你想要找到与行星名称相对应的矢量索引;您可以使用std::findstd::distance执行此操作,如下所示:

num = std::distance(planet.begin(), std::find(planet.begin(), planet.end(), cPlanet));
如果找不到planet.size()

将返回cPlanet。但是,用std::map实现整个事情可能更好。

答案 1 :(得分:0)

这是一个重现行为的简单程序:

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

如果您尝试访问不存在的元素,at成员函数会抛出异常。

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

你可以catch std::out_of_range例外来回复&#34;恢复&#34;从错误或&#34;句柄&#34;它,但是说真的,你能在如此低水平的程序逻辑上做些什么呢?

对于std::vector,请更喜欢[]运算符。在你的情况下:

tTime = distance[num] / speed;

[]at类似,但对编程错误采取完全不同的立场; at就像&#34;如果你应该用非法索引打电话给我,我会抛出一个例外,这样我们就能以某种方式继续进行,是吗?&#34; ,而对于[]运算符,行为未定义表示非法向量索引。这意味着允许C ++实现只是终止程序而没有任何意外捕获异常的机会并且&#34;继续某种方式&#34;。这取决于您如何调用编译器,通常要求您检查编译器的配置选项(例如those for VC++those for GCC)。

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