Home > front end >  How can I stop my average output from displaying the same letter grade as my original grade output?
How can I stop my average output from displaying the same letter grade as my original grade output?

Time:11-14

I have a program that is supposed to return your grades and grade average to you using a sentinel value to end the program, while also using input validation. The issue that I am having at the moment is that it runs greatly and it stops when I use "Quit", but my ending prompt of:

Console.WriteLine("The average is {0} is a(n) {1}", average, grade);

is returning me the same letter grade as the prompt for my:

Console.WriteLine("A grade of {0} is a(n) {1}", anInt, grade);

I also need to make the quit be case insensitive so I tried to use the .ToLower() method, my program would not run properly and I would get an error that says "error CS0019: Operator ==' cannot be applied to operands of type method group' and `string'".

My code is listed below and I was wondering if the issue is that I am using the same string function to return both letters and that is why they are mimicking one another? For example, if I enter a grade that is returned as an F as the last letter in the program, the average grade will show as an F at the end of the program regardless of what the numerical grade value that represents the average is. I was also wondering if there was a proper way to implement the .ToLower() method, because I have tried it a few times and it kept giving me errors, so I just removed it as a whole.

using System;
class Program {
  public static void Main (string[] args) {
    int sum=0;
    int count = 0;
    string grade = "A";
    bool KeepGoing = true;
      
    while (KeepGoing){
      string entry = GetEntry();
      if (entry == "Quit") {
        KeepGoing = false;
      } else {
      int anInt = Convert.ToInt32(entry);
      
      grade = DetermineGrade(anInt);
      sum  = anInt;
      count  ;

      Console.WriteLine("A grade of {0} is a(n) {1}", anInt, grade);
     }
    
    }
    double average = sum/ (double)count;
    Console.WriteLine("The average is {0} is a(n) {1}", average, grade);
    
  }
  
  public static string DetermineGrade(int anInt) {
      if (anInt >= 90){
      return "A";            
    }
      if (anInt >= 80 & anInt <= 89){
      return "B";    
    }
      if (anInt >= 70 & anInt <= 79){
      return "C";
    }
      if (anInt >= 60 & anInt <= 69){
      return "D";
    }
      else{
      return "F"; 
    }
  }
 
  public static string GetEntry() {
    while (true){
     Console.WriteLine("Please enter your grade or enter Quit to end program.");
     string entry = Console.ReadLine();
     if (entry == "Quit"){
       return entry;
     }
     int anInt;
      if (Int32.TryParse (entry, out anInt)) {
        if (anInt>= 0 && anInt <= 100) {
          return entry;
        } else {
          Console.WriteLine("Error: Please enter a valid integer!");
      }
     }
    }
  }
}

CodePudding user response:

"How can I stop my average output from displaying the same letter grade as my original grade output?"

You must call DetermineGrade again with the average. The variable grade will not change by itself.

The problem is that average is a double but DetermineGrade wants an int input. You could simply change the type of the input parameter to double. int arguments will automatically be converted to double.

The method can be simplified. Since the first case returns when the input is >= 90, you don't need to test whether it is <= 89 in the second case. The same is true for the following cases.

public static string DetermineGrade(double value) {
    if (value >= 90.0) return "A";
    if (value >= 80.0) return "B";
    if (value >= 70.0) return "C";
    if (value >= 60.0) return "D";
    return "F";
}

And then

string averageGrade = DetermineGrade(average);
Console.WriteLine("The average is {0} is a(n) {1}", average, averageGrade );

You can also use a switch expression (since C# 8.0) and relational patterns (since C# 9.0) and a expression bodied method (since C# 6.0):

public static string DetermineGrade(double value) =>
    value switch {
         >= 90.0 => "A",
         >= 80.0 => "B",
         >= 70.0 => "C",
         >= 60.0 => "D",
         _ => "F"
    };

"Also how to make sentinel values case insensitve?"

Using .ToLower() is an option. Another possibility is to use

while (true) { // Infinite loop.
    string entry = GetEntry();
    if (String.Equals(entry, "Quit", StringComparison.OrdinalIgnoreCase)) {
        break; // Exit the while loop.
    }
    ...
}

You also have the option to use CurrentCultureIgnoreCase or InvariantCultureIgnoreCase instead. This can make a difference for the Turkish culture, because they have two different "i"s ( one without the dot) that may be handled differently.

In simple situations, where no accents or other special or foreign characters are used, OrdinalIgnoreCase will do it.

  •  Tags:  
  • c#
  • Related