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

C++ File reading program incrementing variable wrong in loop

我正在做一个从文件中读取数据的作业,假定学生分数(我将在下面包括),然后我的程序应该输出 0-25、25 范围内的分数-50,依此类推,直到 200。当我 运行 我的代码时,我得到了疯狂的数字,例如,在 0-25 范围内有 120412409 个分数,但在 25-50 范围内有 none,并且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

我希望程序输出每个范围内的条目数,例如 范围 0 到 24 = 1 范围 25 到 49 = 2 等等。

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

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

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

当你为一个变量分配内存而不给它一个值时,该值将是一个垃圾值。意思是你不能确定它。 在 C++ 中,你总是应该初始化你的变量。

此外,我猜你的意思是 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;
}

并将结果存储到 std::vector<int> scores 变量中。

因为你不是在全局声明变量,所以你必须定义它们。 在您的计数器后添加 =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 个块中的 none 个。如果第一个条件不成立,那么 tastyData 必然大于 24,因此下一个块的 tastyData > 24 条件是不必要的。这个逻辑一直向下级联,如果您使用 else if.

,您只需要检查 tastyData 是否是下一个分数等级 <=

我还借此机会简化了您的代码,并展示了如何使用数组和一些整数数学来代替几个 hard-coded 分数变量和巨大的 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 的文件解析修复程序。