【问题标题】:Segmentation fault when reading text file读取文本文件时出现分段错误
【发布时间】:2021-03-28 22:40:38
【问题描述】:

我正在尝试运行一个代码,从文本文件中对泰坦尼克号幸存者的年龄进行排序。它编译得很好,但是当我选择选项 B(选项 A 尚未编写)时,程序终止只是说“分段错误”。 这是文本文件的一个小样本供参考。

29 1stClass 正确

0.9 第一类为真

2 1stClass FALSE

30 一等假

我已将错误隔离到处理文件的块(//实际处理),但我不确定究竟是什么错误。

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <fstream>
#include <ctype.h>

void sortSurvivors();
void sortAgesLiving();

int main()
{
    char options;
    std::cout << "Titanic Data \nOptions \nA) Display count of people who lived and died... \nB) Display count of people who lived by age... \nPlease select option (A-B)...";
    std::cin >> options;
    switch (options)
    {
        case 'A':
            sortSurvivors();
            break;
        case 'B':
            sortAgesLiving();
            break;
    }
}

void sortSurvivors()
{

}

void sortAgesLiving()
{
    std::ifstream inputFile;
    std::string filename = "TitanicData.txt";
    std::string age;
    std::string classBoat;
    std::string survival;
    bool survived;
    int eldest = 0;

    //pre-sort processing
    while (inputFile >> age >> classBoat >> survival)
    {
        int ageConv = stoi(age);
        //G is for the ghetto fix I am pulling here, because I recieve an error when using "TRUE" as a string
        char gchar = 'G';
        survival += gchar;
        if (survival == "TRUEG")
        {
            survived = true;
        }
        else
        {
            survived = false;
        }
        if (eldest < ageConv) 
        {
            eldest = ageConv;
        }
    }

    //initialize vector
    std::vector<int> survivorVector;
    for (int i = 0; i < eldest; i++)
    {
        survivorVector.push_back(0);
    }

    inputFile.open(filename);
    //actual processing (ERROR HERE)
    if (inputFile)
    {
        while (inputFile >> age >> classBoat >> survival)
        {
            int ageConv = stoi(age);

            if (survived = true)
            {
                survivorVector[ageConv] = survivorVector[ageConv] + 1;
            }
            for (int j = 0; j <= eldest; j++)
            {
                std::cout << j << "\t" << survivorVector[j] << "\n";
            }
        }

        // Close the file.
        inputFile.close();
    }
    else
    {
        std::cout << "I don't know what broke, but uhhhhhhhhhh oops.";
    }
}

像往常一样,我确定这是我忽略的一些愚蠢的事情。

【问题讨论】:

  • 你能证明你在任何地方都在使用[] 运算符,比如survivorVector[ageConv]survivorVector[j] -- 你能从逻辑上证明你是不是 i> 访问数组中的负数或不存在的索引,它总是在 0 到小于向量大小的 1 之间?除非您能证明这一点,否则这是可能导致崩溃的原因之一。 ...实际上我可以看到这个错误。

标签: c++ fstream


【解决方案1】:

sortAgesLiving() 中,您忘记在开始预排序处理之前打开文件。结果,您的第一个阅读循环将根本无法阅读任何内容。因此eldest 将保持为 0。

然后你构造一个向量并填充它。但由于循环基于eldest,因此向量survivorVector 将保持为空。

当你最终打开文件并阅读它时,第一行将被视为幸存者,因为你不小心用 true 覆盖了布尔值(即if (survived = true) 而不是if (survived == true) 或简单的if (survived)。然后你会尝试越界访问向量。

即使你纠正了这个错误,在第一个幸存者时你也会再次出界。越界访问向量是 UB,许多可能的症状之一可能是分段错误。

其他建议(与您的问题无关)

  • 您的年龄模棱两可,0.9。将其转换为 int 将导致其为 0。这样可以吗,还是需要四舍五入?
  • 如果是向上取整,您可以将年龄变量设为double 并直接读取它而无需转换。然后,您可以根据需要将其数学转换为整数年龄,将其向上舍入或截断。如果您确定只有整数,您可以将变量设置为 int,完全不用担心。
  • 信任文件中的值直接索引向量是不安全的。如果在两个读取阶段之间,其他人会在文件中添加一个值高于 eldest 的附加行怎么办?如果读取的值为负数怎么办?在将值用作索引之前,最好始终检查它是否在可接受的范围内。它可以为您节省数小时的调试时间,并为您的客户节省一些噩梦。
  • 最后,两阶段读取不是必需的:您可以只读取年龄,在检查它是正数并且小于 150 岁(非常乐观)之后,如果需要,您可以调整向量的大小,如果年龄等于或大于当前向量大小。为什么?想象一下,有一天你为美国人口普查工作,文件有数百万行:文件越少越好;-)

【讨论】:

  • 很抱歉很久没有注意到您回复的第二部分。
  • 是的,int 是允许为 0 的,我把寻找最大年龄的方法作为安全实践,以防以后数字发生变化。谁知道呢,也许泰坦尼克号上有一个 151 岁的外星人。
猜你喜欢
  • 1970-01-01
  • 2020-08-14
  • 2015-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
相关资源
最近更新 更多