Domanda

I'm writing a program that takes in input and formats it into a score as "Name Score". Here is what needs to be done "Here's Moonglow's format.

  • The text file is composed of words. If a word is a number, then that is a student's score on a question, so you add it to the student's exam score.

  • If the word is not a number, but is the word "NAME", then the next word is the student's name (Moonglow only uses first names -- last names are corporate and impersonal).

  • If the word is "AVERAGE", then you start reading numbers until you read a word that is not a number (or is the end of the file). You average all of those numbers and add that to the score. Since Moonglow is a little scatterbrained, sometimes a number does not follow "AVERAGE." In that case, you ignore the "AVERAGE". "

My problem is I've somehow entered into a infinite loop, and have spent hours trying to fix this. This is a VERY simple program, and I can't seem to get it to work!

#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
È stato utile?

Soluzione

I'm not going to write code for you (since this is clearly a homework problem), but I will offer some suggestions as to how I would do this completely differently. Hope this pseudo code helps.

EDIT: I missed the logic for AVERAGE and how the score should work, I'm making some corrections. (Note, with these changes, it may be better to add new states. I would consider Normal, Name, BeginAverage, Average, EndAverage. But it's up to you.)

1) Define these states (use an enum perhaps):

  • Normal (there's probably a better name for this one)
  • Name
  • Average

2) You want to read one "token" and transition with the following rules. Note that a token in this case will be a string, separated by spaces (e.g. "NAME", "AVERAGE", "Bob", "11", "23").

  • If state is Normal (this is also the initial state)
    • If token is "NAME", go to state Name
    • If token is "AVERAGE", go to state Average
    • If token starts with one of these characters '0', '1', '2', ... '9', convert it to a double and add it to your score
  • If state is Name
    • Copy the token into your "name" variable, transition back to Normal state
  • If state is Average
    • If you get a number, add it to a temporary count and increment a counter
    • If you get a string that is not "NAME", "AVERAGE", or a number, go back to Normal state
    • If you get "NAME", go to Name state
    • Before you enter this state, you need to reset your temporary count/counter to calculate the average
    • Before you leave this state, calculate the average and add it to the total score

3) For processing the input, read everything into a string variable first. Then you can use stringstreams to convert to double when needed. Just read all of the strings (tokens) as I've described and process them as above until you reach EOL.

"Code":

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 takes a string and can just check that the first character is a number ('0', '1',...). It could be fancier and look at each character for numbers/decimals.

convertToNumber takes a string and converts to a double. Could use stringstreams to do the conversion or just the old atoi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top