Чтение двойных слов и слов и выполнение действий на основе прочитанного

0

Я пишу программу, которая принимает входные данные и форматирует их в балл как "Оценка имени". Вот что нужно сделать "Здесь формат Moonglow.

  • Текстовый файл состоит из слов. Если слово - это число, то это вопрос студента по вопросу, поэтому вы добавляете его на счет экзамена студента.

  • Если слово не является числом, но является словом "NAME", то следующим словом является имя студента (Moonglow использует только имена - фамилии являются корпоративными и безличными).

  • Если слово "AVERAGE", вы начинаете считывать цифры, пока не прочитаете слово, которое не является числом (или является концом файла). Вы усредняете все эти цифры и добавляете их в партитуру. Поскольку Moonglow немного рассеян, иногда число не следует "СРЕДНЕЕ". В этом случае вы игнорируете "СРЕДНЕЕ". "

Моя проблема заключается в том, что я каким-то образом вступил в бесконечный цикл и потратил часы, пытаясь это исправить. Это ОЧЕНЬ простая программа, и я не могу заставить ее работать!

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <stdlib.h>
using namespace std;

int main()
{
    string s, name = "test";
    string buffer;
    double qScore, eScore, totalExam = 0, grade = 0, numExam = 0, finalGrade, avg = 0;
    while (!cin.eof())
    {
        if (cin >> qScore)
        {
            if (cin.fail())
            {
                cin.clear();
            }

            else
            {
                grade += qScore;
            }
        }
        else if (cin >> s)
        {
            if (s == "NAME")
            {
                cin >> s;
                s = name;
            }
            else if (s == "AVERAGE")
            {
                while (cin >> eScore)
                {
                    numExam++;
                    totalExam += eScore;

                }
                cin.clear();
            }
        }
    }

    if (numExam == 0)
    {
        avg = 0;
    }
    else
    {
        avg = (totalExam / numExam);
    }
    finalGrade = avg + grade;
    cout << name << " " << finalGrade << endl;
    return 0;

}
// end of main
  • 1
    Для начала while (!eof()) неверно.
  • 0
    Должен ли я заменить его на while (cin >> qScore || cin >> s)?
Показать ещё 11 комментариев
Теги:
string
cout
cin
stringstream

1 ответ

1
Лучший ответ

Я не буду писать для вас код (так как это явно проблема домашних заданий), но я буду предлагать некоторые предложения относительно того, как я буду делать это совершенно по-другому. Надеюсь, этот псевдокод поможет.

EDIT: Я пропустил логику для AVERAGE и как должен работать счет, я делаю некоторые исправления. (Обратите внимание, что с этими изменениями может быть лучше добавить новые состояния. Я бы рассмотрел Normal, Name, BeginAverage, Average, EndAverage. Но это зависит от вас.)

1) Определите эти состояния (возможно, используйте перечисление):

  • Обычный (вероятно, лучшее название для этого)
  • имя
  • В среднем

2) Вы хотите прочитать один "токен" и переход со следующими правилами. Обратите внимание, что токеном в этом случае будет строка, разделенная пробелами (например, "NAME", "AVERAGE", "Bob", "11", "23").

  • Если состояние Normal (это также начальное состояние)
    • Если токеном является "NAME", перейдите к названию состояния
    • Если токен "СРЕДНЕЕ", перейдите в состояние "Средняя"
    • Если токен начинается с одного из этих символов "0", "1", "2", "9", преобразуйте его в двойное и добавьте его в свой счет
  • Если состояние Имя
    • Скопируйте токен в свою переменную "имя", переход в нормальное состояние
  • Если состояние среднее
    • Если вы получаете номер, добавьте его к временному счету и добавьте счетчик
    • Если вы получите строку, которая не является "NAME", "AVERAGE" или числом, вернитесь в "Нормальное состояние"
    • Если вы получите "НАЗВАНИЕ", перейдите в состояние "Имя"
    • Прежде чем вводить это состояние, вам необходимо сбросить временный счетчик/счетчик, чтобы вычислить средний
    • Прежде чем покинуть это состояние, вычислите среднее значение и добавьте его в общий балл

3) Для обработки ввода сначала прочитайте все в строковой переменной. Затем вы можете использовать stringstream для преобразования в double при необходимости. Просто прочитайте все строки (жетоны), как я описал, и обработайте их, как указано выше, до тех пор, пока вы не достигнете EOL.

"Код":

while (cin >> s)
{
    if (state == state_normal)
    {
        if (s == "NAME") { state = state_name; }
        else if (s == "AVERAGE")
        {
            state = state_average;
            // You are starting a new average, initialize these variables to 0
            scoresToAverage = 0;
            numberOfScores = 0;
        }
        else if (isNumber(s))
        {
            number = convertToNumber(s);
            score += number;
        }
    }
    if (state == state_name)
    {
        name = s;
        state = state_normal;
    }
    if (state == state_average)
    {
        bool calculateAverage = false;
        if (s == "NAME")
        {
             state = state_name;
             calculateAverage = true;
        }
        else if (s == "AVERAGE")
        {
             state = state_average;
             calculateAverage = true;
        }
        else if (isNumber(s))
        {
            number = convertToNumber(s);
            scoresToAverage += number;
            numberOfScores++;
        }
        else
        {
            state = state_normal;
            calculateAverage = true;
        }

        // If you are DONE averaging, calculate the average and add it to the total
        if (calculateAverage)
        {
            if (numberOfScores > 0)
            {
                score += (scoresToAverage / numberOfScores);
            }
            scoresToAverage = 0;
            numberOfScores = 0;
        }
    }
}

// done reading input, just print!

isNumber берет строку и может просто проверить, что первый символ - это число ('0', '1',...). Это может быть более привлекательным и смотреть на каждый символ для чисел/десятичных знаков.

convertToNumber берет строку и преобразует в double. Могут использовать stringstreams для преобразования или просто старые atoi.

  • 0
    Это довольно полезно до сих пор. Всего один вопрос. Что вы имеете в виду, используя enum для состояний?
  • 0
    Предполагая, что вы не знаете, что такое enum , cprogramming.com/tutorial/enum.html Таким образом, вы можете создать новый тип enum котором каждое возможное значение является различным состоянием. В качестве альтернативы вы можете использовать int и определять const , например, 0 - первое состояние, 1 - второе, 2 - третье. Это (в некоторой степени) то, что enum делает для вас.
Показать ещё 14 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню