It appears my teacher wants the class to use double to solve this problem. I am having difficulty getting it to take. I'm sure it's someting simple that I'm missing but I want to see what others think.
public char Test4(double grade)
{
// TODO: Write code here to compute an answer.
// Return the answer from this function.
// Read the lab document for detailed instructions.
}
I've tried using if else statements and to no luck. I'm not sure how to use a double for this. Please help.
Thanks.
Here's an example of what I've tried.
if (grade >= 90 && grade <= 100)
{
public char = 'A'
}
else if (grade >=80 && grade <90)
{
public char = 'B'
}
return public char;
{
The output:
I've cleaned this up. Hope this helps to clarify the question.
public char Test4(double grade)
{
// TODO: Write code here to compute an answer.
// Return the answer from this function.
// Read the lab document for detailed instructions.
if (grade >= 90.0)
{ return 'A'; }
else
if (grade >= 80.0)
{ return 'B'; }
else
if (grade >= 73.0)
{ return 'C'; }
else
if (grade >=70.0)
{ return 'D'; }
else
if (grade >= 0)
{ return 'F'; }
else
if (grade <0 )
{ return '?'; }
else
if (grade > 100)
{ return '?'; }
}
You are returning "public char", you need to either return it in place, or store the value in a variable.
example 1
if (grade >= 90)
{
return 'A';
}
else if ....
{
//copy for each letter grade above F
}
else
{
return 'F';
}
example 2
char gradeLetter = 'F';
if (grade >= 90)
{
gradeLetter = 'A';
}
else if ....
{
//copy for each letter grade above F
}
return gradeLetter;
I don't think that you compile with Test4 as written and are running and old, unimplemented version of Test4 (hence no results). You have an error, which I'm guessing is: "not all code paths return a value." To solve this, have a "catch all" at the end - you don't need to check if grade is <0 AND >100, just return ?.
...
else if(grade >= 0)
{
return 'F';
}
// if none of the if statements were hit, you have an incorrect grade value
return '?';
This is should properly compile Test4 (note, you have an error with Test5 that needs to be fixed as well) and give you the correct results.
Related
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!");
}
}
}
}
}
"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.
Is there any more "elegant" way to filter a number input for specific parameters?
Like here, I need to say different things if you're to high, to low or of the limits.
Would appreciate if you explain what you suggest. I'm like 2 weeks into programming.
//VARIABLES
int userNumber;//uN
int searchedNumber;//sN
//NUMBER WE'RE LOOKING FOR
searchedNumber = 87;
//TASK FOR "CUSTOMER"
Console.WriteLine("Type in a number between 1-100!");
//DO-WHILE, because it hast to run one either way
do
{
//READING OUT CONSOLE
string userNumberString = Console.ReadLine();
//CONVERTING STRING TO INT
userNumber = int.Parse(userNumberString);
//uN > THAN sN BUT <= 100
if (userNumber > searchedNumber && userNumber <= 100)
{
Console.WriteLine("To High! /n Try again.");
}
//uN < THAN sN BUT >= 1
else if (userNumber < searchedNumber && userNumber >= 1)
{
Console.WriteLine("To Low! /n Try again.");
}
//uN >= 101 AND uN <= 0
else if (userNumber >= 101 || userNumber <= 0)
{
Console.WriteLine("Between 1 and 100, Dummy!");
}
else
{
//IF NOTHING IS TRUE uN=sN
Console.WriteLine("JACKPOT!");
}
//LOOPING CONDITION
} while (userNumber != searchedNumber);
If this q is already answered somewhere, i'm sorry. English is not my native language and i struggled to even find the right search term.
I suggest extracting methods, please, do not cram everything into huge single routine:
public static int ReadInteger(string title) {
if (!string.ISNullOrWhiteSpace(title))
Console.WriteLine(title);
while (true) {
if (int.TryParse(Console.ReadLine(), out int result))
return result;
Console.WriteLine("This is not a valid integer! Try again.");
}
}
public static string FeedBack(int user, int actual) {
if (user < 0 || user > 100)
return "Between 1 and 100, Dummy!"
else if (user < actual)
return "Too Low! /n Try again.";
else if (user > actual)
return "Too High! /n Try again.";
else
return "JACKPOT!"
}
Then use these methods in a tiny loop:
int userNumber = 0;
int searchedNumber = 87;
do {
userNumber = ReadInteger("Type in a number between 1-100!");
Console.WriteLine(FeedBack(userNumber, actual));
}
while (userNumber != searchedNumber);
One way to get rid of all the else statements is to move the code to a method and return from the method as soon as you know what the response should be.
Something like this
public string EvaluateNumber(int userNumber, int searchedNumber)
{
if (searchedNumber <= 0 || searchedNumber >= 101)
return "Between 1 and 100, Dummy!";
if (searchedNumber < userNumber)
return "Too low! /n Try again.";
if (searchedNumber > userNumber)
return "Too high! /n Try again.";
return "JACKPOT!"; // If we get to here, the numbers are equal
}
This code can get little bit cleaner by rearramging conditions - if will get a lot simplier :) Also, if you have one line under if, you can omit curly braces, see below code. I also included some comments, which I hope, wil be useful:
do
{
//READING OUT CONSOLE
string userNumberString = Console.ReadLine();
//CONVERTING STRING TO INT
// here you need to be careful, what if user types "a"?
// I suggest reading about int.TryParse :)
userNumber = int.Parse(userNumberString);
//uN >= 101 AND uN <= 0
if (userNumber >= 101 || userNumber <= 0)
Console.WriteLine("Between 1 and 100, Dummy!");
// now we are sure we are in the range
if (userNumber > searchedNumber)
Console.WriteLine("To High! /n Try again.");
else if (userNumber < searchedNumber)
Console.WriteLine("To Low! /n Try again.");
else
//IF NOTHING IS TRUE uN=sN
Console.WriteLine("JACKPOT!");
//LOOPING CONDITION
} while (userNumber != searchedNumber);
Thinking of a cleaner code:
public static void Main()
{
//VARIABLES
int userNumber;//uN
int searchedNumber = 87;
int min = 1;
int max = 100;
//TASK FOR "CUSTOMER"
Console.WriteLine($"Type in a number between {min}-{max}!");
//DO-WHILE, because it hast to run one either way
do
{
//READING OUT CONSOLE
string userNumberString = Console.ReadLine();
//CONVERTING STRING TO INT
if (int.TryParse(userNumberString, out userNumber))
{
if (userNumber >= min && userNumber <= max)
{
if (userNumber == searchedNumber)
{
Console.WriteLine("JACKPOT!");
}
else
{
Console.WriteLine("To " + (userNumber < searchedNumber ? "Low" : "High") + "! Try again.");
}
}
else
{
Console.WriteLine($"Between {min} and {max}, Dummy!");
}
}
else
{
Console.WriteLine($"One integer number, Dummy!");
}
} while (userNumber != searchedNumber);
}
The TryParse it's very important
I want to run the gradeStatus in the Console.WriteLine but I fail...
I've almost checked all posts to some extent relevant but none have resolved my problem, please guide?
Console.WriteLine("Type in grade to get stats!");
int gradeScore = Convert.ToInt16(Console.ReadLine());
Console.WriteLine("Grade Score: {0}", gradeScore);
bool isPassed;
if (gradeScore >= 50)
{
isPassed = true;
}
else
{
isPassed = false;
}
Console.WriteLine("Passed: {0}", isPassed);
string gradeStatus;
if(gradeScore == 50)
{
gradeStatus = "Okay";
}
else if (gradeScore == 60)
{
gradeStatus = "Good";
}
else if (gradeScore >= 70)
{
if (gradeScore == 70)
{
gradeStatus = "Great";
}
else if (gradeScore == 80)
{
gradeStatus = "Great";
}
}
else if (gradeScore == 90)
{
gradeStatus = "Excellent";
}
else if (gradeScore == 100)
{
gradeStatus = "Ace!";
}
Console.WriteLine("Grade Status: {0}", gradeStatus);
The problem is with your if statements. What you are probably wanting is the below portion of code for your set of if else statements.
if(gradeScore <= 50)
{
gradeStatus = "Okay";
}
else if (gradeScore <= 60)
{
gradeStatus = "Good";
}
else if (gradeScore <= 70)
{
gradeStatus = "Great";
}
else if (gradeScore <= 80)
{
gradeStatus = "Great";
}
else if (gradeScore <= 90)
{
gradeStatus = "Excellent";
}
else if (gradeScore <= 100)
{
gradeStatus = "Ace!";
}
For a problem like this one, it is often much easier to break the logic into a separate function. When you use a separate function, you can use early return to avoid else. That makes the logic much more plain and easy to read, and less prone to error.
For example, you could write a function like this one:
static string GetGradeStatus(int score)
{
if (score <= 50) return "Okay";
if (score <= 60) return "Good";
if (score <= 70) return "Great";
if (score <= 80) return "Great";
if (score <= 90) return "Excellent";
return "Ace";
}
And modify your code to use it:
Console.WriteLine("Type in grade to get stats!");
int gradeScore = Convert.ToInt16(Console.ReadLine());
Console.WriteLine("Grade Score: {0}", gradeScore);
var isPassed = gradeScore > 50;
Console.WriteLine("Passed: {0}", isPassed);
var gradeStatus = GetGradeStatus(gradeScore);
Console.WriteLine("Grade Status: {0}", gradeStatus);
This is easier to read and makes it very plain if you've got a logic error (e.g. it is obvious that "Great" is used twice, which is what your existing code does).
I also made two other changes:
I changed = to <= since there is nothing preventing the user from entering a number that is not a multiple of 10. That was just a guess. You might need to tweak the logic to meet your requirements correctly.
I changed the if/else assignment of isPassed to a simple Boolean assignment, which is idiomatic for c# and easier to read once you get used to it.
I wrote some code and it works, but now trying to take some of my code and change it to a Class. I already change part of the code to first a method and then turn it into a Class. But this last part of code having trouble figuring out how to change to a method so then I can make a Class.
else if (input == "3")
{
Console.WriteLine("Here are your Students: ");
Array.Sort(names);
Console.WriteLine(String.Join(", ", names));
Console.WriteLine("");
double average = gradesList.Average();
if (average >= 90)
{
Console.WriteLine($"There average is a {average.ToString("n2")} which is an A.");
}
else if (average >= 80)
{
Console.WriteLine($"There average is a {average.ToString("n2")} which is an B.");
}
else if (average >= 70)
{
Console.WriteLine($"There average is a {average.ToString("n2")} which is an C.");
}
else if (average >= 60)
{
Console.WriteLine($"There average is a {average.ToString("n2")} which is an D.");
}
else
{
Console.WriteLine($"There average is a {average.ToString("n2")} which is an E.");
}
}
The first part I was thinking of leaving that and just change the Grade part into a Class. I tried public static string GetLetterGrade(int average)
return ($"There average is a {average.ToString("n2")} which is an A.") but get all kinds or errors that I don't understand.
I would make the grade a non-mutable struct. It represents a value and should be a value type. A class is a reference type.
public readonly struct Grade
{
public Grade(double percentage)
{
Percentage = percentage;
}
public double Percentage { get; }
public char Letter
{
get {
if (Percentage >= 90) return 'A';
if (Percentage >= 80) return 'B';
if (Percentage >= 70) return 'C';
if (Percentage >= 60) return 'D';
return 'E';
}
}
public override string ToString() => $"{Percentage:n2} ({Letter})";
}
Since the if-statements return, it is not necessary to have an else-part.
Then you can easily print the message with
double average = gradesList.Average();
var grade = new Grade(average);
Console.WriteLine(
$"There average is a {grade.Percentage:n2} which is an {grade.Letter}.");
Note that because ToString is overridden, you can print the grade directly.
Console.WriteLine($"The average grade is {grade}");
It will print something like The average grade is 74.25 (C).
this should work
public static char GetLetterGrade(double average)
{
if (average >= 90)
{
return 'A';
}
else if (average >= 80)
{
return 'B';
}
else if (average >= 70)
{
return 'C';
}
else if (average >= 60)
{
return 'D';
}
return 'E';
}
but if you wish to use GetLetterGrade(int average) overload, use it like this
double average = gradesList.Average();
var grade = GetLetterGrade((int)average);
I have a bowling game that takes the list of bowls and then runs them through this code to produce a string that goes through the frames on the UI. If the user bowls a gutter (0) or strike (10) the code works fine. However, if it is between 1 and 9, it fails to produce a string. Why is this? I've searched and tried many other ways to do this, but this seems to be the only way it will work.
public static StringBuilder FormatRolls (List<int> rolls) {
StringBuilder output = new StringBuilder();
for (int i=0; i < rolls.Count; i++) {
if (rolls.Count >= 19 && rolls[i] == 10) { //Bonus End-Frame Strike
output.Append ("X");
} else if (rolls[i] == 0) { //Gutter
output.Append ("-");
} else if (rolls[i-1] + rolls[i] == 10 && rolls.Count > 1) { //Spare
output.Append ("/");
} else if (rolls[i] == 10 && rolls[i+1] == 0) { //Strike
output.Append ("X");
} else { //Normal bowls 1-9
output.Append (rolls[i].ToString());
}
}
output.ToString();
return output;
}
This is the code that then writes to all of the frames:
public void FillRolls (List<int> rolls) {
StringBuilder scoresString = FormatRolls(rolls);
for (int i=0; i<scoresString.Length; i++) {
frameText[i].text = scoresString[i].ToString();
}
}
Any help is greatly appreciated, I've been stuck for DAYS trying to get this to work...
output.ToString(); is a pure function and you are not using its return value (so, you are converting to a string, and then throwing that string away without using/storing/returning it). I guess you really want to return the fully built and formatted string, not the StringBuilder instance. Use:
return output.ToString();
That said, other codepaths should not produce a value either.
After rolling through all the comments and suggestions from others, I took away the try-catch section that blocked me from seeing past my catch error. Then, added debug.log statements to help find the correct position and used Unity's built-in errors to find this wasn't the string's fault at all. It was trying to find an index rolls[i]-1 that didn't exist. After a few attempts I found that if I changed the else if (rolls[i-1] + rolls[i] == 10 && rolls.Count > 1) to a nested if statement and used the output.Length instead of rolls.Count it would no longer return an error. Thank you everyone who tried to help me solve this, you pointed me in the right direction and really got me thinking! Here is the finished code:
public static string FormatRolls (List<int> rolls) {
StringBuilder output = new StringBuilder();
for (int i=0; i < rolls.Count; i++) {
if (rolls.Count >= 19 && rolls[i] == 10) { //Bonus End-Frame Strike
output.Append ("X");
} else if (rolls[i] == 0) { //Gutter
output.Append ("-");
} else if (rolls[i] == 10 && output.Length % 2 == 0) { //Strike
output.Append (" X");
} else if (output.Length >= 1 && output.Length % 2 != 0) { //Spare
if (rolls[i-1] + rolls[i] == 10) {
output.Append ("/");
}
} else { //Normal bowls 1-9
output.Append (rolls[i]);
}
}
return output.ToString();
}