簡體   English   中英

C ++文件讀取程序在循環中遞增變量錯誤

[英]C++ File reading program incrementing variable wrong in loop

我正在處理從文件中讀取數據的作業,假設學生分數(我將在下面包括),然后我的程序應該輸出多少分數在 0-25、25-50 等范圍內直到 200。當我運行我的代碼時,我得到了瘋狂的數字,例如,在 0-25 范圍內有 120412409 個分數,但在 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";
    }

這是數據.txt

76, 89, 150, 135, 200, 76, 12, 100, 150, 28, 178, 189, 167, 200, 175, 150, 87, 99, 129, 149, 27, 107, 106 189

我希望程序輸出每個范圍中有多少條目,例如 range0to24 = 1 range25to49 = 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 ? + 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條件是不必要的。 這個邏輯一直向下級聯,如果你使用else if ,你只需要檢查tastyData是否<=下一個分數層。


我還借此機會簡化了您的代碼,並展示了如何使用數組和一些整數數學代替幾個硬編碼的分數變量和一個巨大的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 的文件解析修復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM