C ++文件读取程序递增变量循环错误

时间:2019-07-05 17:50:07

标签: c++ while-loop fstream file-handling eof

我正在做一个作业,该作业从文件中读取数据,假设是学生分数(我将在下面列出),然后我的程序应该输出多少分数,范围是0-25、25-50 ,依此类推,直到200。运行代码时,我会得到疯狂的数字,例如,120412409的分数在0-25范围内,但25-50的分数均没有,而75-100的分数约为2000。我相信我的循环结构中有一个错误,当找到与该范围相匹配的变量时,将变量递增错误,但是我无法弄清楚。

我尝试过,未在函数中实现对范围的检查,但这似乎使情况变得更糟。

#include <iostream>
#include <fstream>

int main()
    {
    //Variable Declare
    std::ifstream scores;
    int tastyData;
    int range0to24;
    int range25to49;
    int range50to74;
    int range75to99;
    int range100to124;
    int range125to149;
    int range150to174;
    int range175to200;

    //Opening File
    scores.open("data.txt");

    //Main Loop
    while (scores.fail())
        {
        scores >> tastyData;
        if (tastyData <= 24)
            {
            range0to24 = range0to24 + 1;
            }
            else if (tastyData <= 49 && tastyData > 24)
            {
            range25to49 = range25to49 + 1;
            }
            else if (tastyData <= 74 && tastyData > 49)
            {
            range50to74 = range50to74 + 1;
            }
            else if (tastyData <= 99 && tastyData > 74)
            {
            range75to99 = range75to99 + 1;
            }
            else if (tastyData <= 124 && tastyData > 99)
            {
            range100to124 = range100to124 + 1;
            }
            else if (tastyData <= 149 && tastyData > 124)
            {
            range125to149 = range125to149 + 1;
            }
            else if (tastyData <= 174 && tastyData > 149)
            {
            range150to174 = range150to174 + 1;
            }
            else if (tastyData <= 199 && tastyData > 174)
            {
            range175to200 = range175to200 + 1;
            }
        }
        scores.close();
        std::cout << range0to24 << "\n";
        std::cout << range25to49 << "\n";
        std::cout << range50to74 << "\n";
        std::cout << range75to99 << "\n";
        std::cout << range100to124 << "\n";
        std::cout << range125to149 << "\n";
        std::cout << range150to174 << "\n";
        std::cout << range175to200 << "\n";
    }

这是data.txt

76、89、150、135、200、76、12、100、150、28、178、189、167, 200、175、150、87、99、129、149、176, 200、87、35、157、189

我希望程序输出每个范围内的条目数,例如 range0to24 = 1 range25to49 = 2 等等。

编辑:我的问题现已解决。初始化和解析是主要问题。谢谢所有帮助的人。

4 个答案:

答案 0 :(得分:1)

您尚未初始化变量,从而导致未定义的行为。由于将它们用作计数器,因此应将它们显式初始化为零:

int range0to24 = 0;
int range25to49 = 0;
int range50to74 = 0;
int range75to99 = 0;
int range100to124 = 0;
int range125to149 = 0;
int range150to174 = 0;
int range175to200 = 0;

答案 1 :(得分:0)

当您为变量分配内存而没有给它一个值时,该值将是一个垃圾值。这意味着您不能确定。 在C ++中,您始终应该初始化变量。

Morehover,我想你的意思是onClose()而不是while (!scores.fail())

如果您想以其他方式对分数进行排序,则可以执行以下操作:

while (scores.fail())

哪个输出

#include <iostream>
#include <map>
#include <vector>

int main()
{
    int rangeStep = 10;

    std::map<int, size_t> sortedScores;

    std::vector<int> scores { 76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189, 167, 200, 175, 150, 87, 99, 129, 149, 176, 200, 87, 35, 157, 189 };

    for (int score : scores)
    {
        ++sortedScores[score / rangeStep];
    }

    for (const auto& element : sortedScores)
    {
        std::cout << "Range [" << element.first * rangeStep << "," << (element.first + 1) * rangeStep << "] => " << element.second << std::endl;
    }

    std::cin.get();
    return 0;
}

您的文件解析也是错误的,您可以使用类似:

Range [10,20] => 1
Range [20,30] => 1
Range [30,40] => 1
Range [70,80] => 2
Range [80,90] => 3
Range [90,100] => 1
Range [100,110] => 1
Range [120,130] => 1
Range [130,140] => 1
Range [140,150] => 1
Range [150,160] => 4
Range [160,170] => 1
Range [170,180] => 3
Range [180,190] => 2
Range [200,210] => 3

并将结果存储到std::vector<int> ReadScoresFromFile(const std::string& p_filename) { std::vector<int> result; std::fstream file(p_filename); std::string line; while (getline(file, line)) { std::stringstream linestream(line); std::string value; while (getline(linestream, value, ',')) { result.push_back(std::atoi(value.c_str())); } } return result; } 变量中。

答案 2 :(得分:0)

由于您没有全局声明变量,因此必须定义它们。 在计数器后面添加=0或全局声明它们,但是全局声明是不良编码做法的一部分,因此请避免使用它。

答案 3 :(得分:0)

您的代码存在一些问题:

  1. 您的范围变量未初始化。您期望? + 1的结果如何?

您可以通过在声明变量时初始化变量来解决此问题:

int range0to24 = 0;
int range25to49 = 0;
int range50to74 = 0;
...
  1. 您的while循环正在检查scores.fail()是否继续执行,只有在打开文件失败的情况下才进入循环!

改为使用while (!scores.fail())

  1. 您的if else if结构具有一些冗余条件。
if (tastyData <= 24)
{
    range0to24 = range0to24 + 1;
}
else if (tastyData <= 49 && tastyData > 24)
{
    range25to49 = range25to49 + 1;
}
else if ...

如果输入第一个if (tastyData <= 24),则将不输入任何else if块。如果第一个条件不成立,则tastyData必须大于24,因此下一个块的tastyData > 24条件是不必要的。此逻辑一直向下层叠,如果您使用的是tastyData,则只需检查<=是否是else if的下一个分数层。


我还借此机会简化了代码,并展示了如何使用数组和一些整数数学而不是几个硬编码的得分变量和庞大的if else if结构。

#include <fstream>
#include <iostream>
#include <string>

int main()
{
    // Set up the 'bins' for counting scores
    int max = 200;
    int binSize = 25;
    int binCount = max / binSize;

    int* bins = new int[binCount];
    for (int i = 0; i < binCount; i++)
    {
        bins[i] = 0;
    }

    // Open the scores file
    std::fstream scores("data.txt");
    std::string line;
    // Read each text line in the file
    while (getline(scores, line))
    {
        std::stringstream linestream(line);
        std::string       value;

        // Read each comma-separated value in a line
        while (getline(linestream, value, ','))
        {
            int tastyData = std::atoi(value.c_str());

            int index = (tastyData / binSize);
            if (index >= binCount) continue;

            bins[index]++;
        }
    }

    scores.close();

    for (int i = 0; i < binCount; i++)
    {
        std::cout << bins[i] << std::endl;
    }

    delete[] bins;

    return 0;
}

*已更新为使用Adrien Givry的文件解析修复程序。