В программе чтения файлов C ++ неверно увеличена переменная в цикле - PullRequest
0 голосов
/ 05 июля 2019

Я работаю над заданием, которое считывает данные из файла, предполагаемые баллы учащихся (я включу ниже), а затем моя программа должна вывести, сколько баллов находится в диапазонах 0-25, 25-50и так до 200. Когда я запускаю свой код, я получаю сумасшедшие числа, например, есть 120412409 баллов в диапазонах 0-25, но ни один из 25-50, и около 2000 в 75-100.Я полагаю, что в моей структуре цикла есть ошибка, увеличивающая переменную неправильно, когда она находит соответствие для этого диапазона, но я не могу понять это.

Я пытался, неудачно реализуя проверку длядиапазоны в функции, но это, кажется, только усугубляет ситуацию.

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

1 голос
/ 05 июля 2019

Вы не инициализировали свои переменные, что привело к неопределенному поведению.Поскольку вы используете их в качестве счетчиков, вы должны явно инициализировать их нулями:

int range0to24 = 0;
int range25to49 = 0;
int range50to74 = 0;
int range75to99 = 0;
int range100to124 = 0;
int range125to149 = 0;
int range150to174 = 0;
int range175to200 = 0;
0 голосов
/ 05 июля 2019

Есть несколько проблем с вашим кодом:

  1. Ваши переменные диапазона неинициализированы.Как вы ожидаете, какой будет результат ? + 1?

Это можно исправить, инициализируя переменные при их объявлении:

int range0to24 = 0;
int range25to49 = 0;
int range50to74 = 0;
...
Ваш цикл while проверяет, чтобы scores.fail() был равен true, чтобы продолжить, цикл будет введен только в случае неудачного открытия файла!

Используйте взамен while (!scores.fail()).

Ваша структура 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;
}

* Обновлен для использования исправлений файла Эдриена Гиври.

0 голосов
/ 05 июля 2019

Поскольку вы не объявляете переменные глобально, вы должны определить их. Добавьте =0 после ваших счетчиков или объявите их глобально, но глобальное объявление является частью плохой практики кодирования, поэтому старайтесь избегать его.

0 голосов
/ 05 июля 2019

Когда вы выделяете память для переменной, не присваивая ей значение, оно будет мусорным. Это означает, что вы не можете быть в этом уверены. В 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.

...