/*---
    CS 111 - Week 11 Lecture 1 - 2025-11-04

    compile using:
        g++ 111lect11-1.cpp -o 111lect11-1
    run using:
        ./111lect11-1

    by: Sharon Tuttle
    last modified: 2025-11-04
---*/

#include <cstdlib>
#include <iostream>
#include <string>
#include <cmath>
using namespace std;

/*===
    signature: describe_grade: char -> string
    purpose: expects a grade expressed as a char,
        and returns a string description for that grade,
        as follows:

        grade           description
        =====           ===========
        'A' or 'a'      "Excellent"
        'B' or 'b'      "Very Good"
        'C' or 'c'      "Acceptable"
        'T' or 't'      "Try Again"
        anything
            else  "Unrecognized Grade"
    tests:
        describe_grade('A') == "Excellent"
        describe_grade('B') == "Very Good"
        describe_grade('C') == "Acceptable"
        describe_grade('T') == "Try Again"
        describe_grade('a') == "Excellent"
        describe_grade('b') == "Very Good"
        describe_grade('c') == "Acceptable"
        describe_grade('t') == "Try Again"
        describe_grade('P') == "Unrecognized Grade"
===*/

string describe_grade(char letter_grade)
{
    /*=== 
        our first version, using if-else-if pattern,
            then extended to also accept lowercase grades:

    if ((letter_grade == 'A') || (letter_grade == 'a'))
    {
        return "Excellent";
    }
    else if ((letter_grade == 'B') || (letter_grade == 'b'))
    {
        return "Very Good";
    }
    else if ((letter_grade == 'C') || (letter_grade == 'c'))
    {
        return "Acceptable";
    }
    else if ((letter_grade == 'T') || (letter_grade == 't'))
    {
        return "Try Again";
    }
    else
    {
        return "Unrecognized Grade";
    }

    ===*/

    /*=== 
        Our second version, using a switch statement
            (the break statements here are not really needed,
            because return statement ENDS a function,
            but including them in case you look this up later
            to review switch syntax...)

    switch(letter_grade)
    {
        case 'A':
        case 'a':
            return "Excellent";
            break;

        case 'B':
        case 'b':
            return "Very Good";
            break;

        case 'C':
        case 'c':
            return "Acceptable";
            break;

        case 'T':
        case 't':
            return "Try Again";
            break;

        default:
            return "Unrecognized Grade";
    }

    ===*/

    /*=== 
        our third version, using a switch statement and a
            local variable
        (and for THIS version -- WILL get errors if remove the
            break statements!)
    ===*/

    // initially setting local variable grade_descr
    //     to an empty string,
    //     to avoid compiler warnings -- we know the switch
    //     statement will always set it to some description,
    //     but the compiler cannot be sure of that and
    //     is trying to avoid returning a possibly-uninitialized
    //     local variable as the return value
    // (but then tested after class, and compiler did not complain!!)
  
    string grade_descr = "";

    // comment out one or more of the break statements
    //    in this switch and see which tests fail as a result
    
    switch(letter_grade)
    {
        case 'A':
        case 'a':
            grade_descr = "Excellent";
            break;

        case 'B':
        case 'b':
            grade_descr = "Very Good";
            break;

        case 'C':
        case 'c':
            grade_descr = "Acceptable";
            break;

        case 'T':
        case 't':
            grade_descr = "Try Again";
            break;

        default:
            grade_descr = "Unrecognized Grade";
    }

    return grade_descr;
}

/*---
   test the functions above
---*/

int main()
{
    cout << boolalpha;

    cout << "*** Testing: describe_grade ***" << endl;

    cout << (describe_grade('A') == "Excellent") << endl;
    cout << (describe_grade('B') == "Very Good") << endl;
    cout << (describe_grade('C') == "Acceptable") << endl;
    cout << (describe_grade('T') == "Try Again") << endl;
    cout << (describe_grade('a') == "Excellent") << endl;
    cout << (describe_grade('b') == "Very Good") << endl;
    cout << (describe_grade('c') == "Acceptable") << endl;
    cout << (describe_grade('t') == "Try Again") << endl;
    cout << (describe_grade('P') == "Unrecognized Grade") << endl;

    cout << endl;
    cout << "Just for fun: "
         << describe_grade('a') << endl;

    return EXIT_SUCCESS;
}