How to eliminate an incorrect input?

anabeatriz

New member
Joined
Sep 4, 2019
Messages
4
Programming Experience
Beginner
The teacher gave us this exercise:
"Write a program that calculates and displays the average of 10 typed grades. Consider valid notes, only values between 0 (zero) and 10 (ten). If the user enters any invalid value, a message should be displayed stating what happened."

I wrote a code that is almost right:
C#:
double nota = 0;
double soma = 0;
for (double x = 1.0; x <= 10.0; x++) {
   Console.WriteLine("Enter a grade: ");
   nota = double.Parse(Console.ReadLine());
   while (nota < 0 || nota > 10) {
      Console.WriteLine("Invalid grade, enter again: ");
      break;
   }
   soma = soma + nota;
}
   Console.WriteLine("The average is {0}", soma / 10);

Example:
Capturar2.PNG


I want these two 50s that were typed not to be stored and allow the user to enter two more grades. How do I do that?
 
Your code doesn't really represent the logic you want to implement. That while loop will never execute more than once because you have a break statement that gets hit the first time through. What do you actually want to do? While the entered value is invalid, you want to keep prompting the user to enter another value and keep getting that value.. What you have is code to prompt once but not actually accept the invalid value. What you need to do is get rid of the break statement and copy, in it's place, the line that reads the user input and stores it. This is an example of why you should write out the logic that you're trying to implement before writing the code to implement it. That way, you always have something to compare your code to to make sure it makes sense.
 
As a small aside,
C#:
soma = soma + nota;
can be more succinctly written
C#:
soma += nota;
Also, why would you use a double as your loop counter? If you were actually using it as a value inside the loop for calculations then maybe but, if what you're doing is counting, you should use counting numbers, i.e. integers.
 
Finally, I'm not sure whether it is safe for you to assume that the user will enter a number or not. Maybe it is, as is often the case in beginner assignments, but you might have to allow for non-numeric input too.
 
Your code doesn't really represent the logic you want to implement. That while loop will never execute more than once because you have a break statement that gets hit the first time through. What do you actually want to do? While the entered value is invalid, you want to keep prompting the user to enter another value and keep getting that value.. What you have is code to prompt once but not actually accept the invalid value. What you need to do is get rid of the break statement and copy, in it's place, the line that reads the user input and stores it. This is an example of why you should write out the logic that you're trying to implement before writing the code to implement it. That way, you always have something to compare your code to to make sure it makes sense.
I want invalid inputs to be deleted and allow the user to enter 10 valid grades
 
As a small aside,
C#:
soma = soma + nota;
can be more succinctly written
C#:
soma += nota;
Also, why would you use a double as your loop counter? If you were actually using it as a value inside the loop for calculations then maybe but, if what you're doing is counting, you should use counting numbers, i.e. integers.
Thank you I will change those two things
 
Finally, I'm not sure whether it is safe for you to assume that the user will enter a number or not. Maybe it is, as is often the case in beginner assignments, but you might have to allow for non-numeric input too.
How I allow for non-numeric input too?
 
There are a few things you can do. I'd first start off by re-reading the notes left above. And I am not suggesting you use either approach, I am just demonstrating some ways you can check the user input. You should use some get setters, but if you are looking to grade something, you are less likely to grade it by double values, and integers is what you would and should use. I can surely understand a use for doubles when averaging. Anyway, the get setters :
C#:
        public static double doubNota { get; set; }
        public static double doubSoma { get; set; }
        public static int iNota { get; set; }
        public static int iSoma { get; set; }
Using some regex, with a specific pattern, you could also use patterns for both integers, and doubles. A pattern for doubles would look like this :
C#:
Regex doubRegex = new Regex(@"^-?(?:0|[1-9][0-9]*)\.?[0-9]+$"); /* this pattern checks only numbers and . dot */
Where as a pattern for numbers would look like this (This could be expressed a little better but I'm tight on time, and It will give you something to play with) :
C#:
Regex intRegex = new Regex(@"^[0-9]+$"); /* this pattern checks only numbers */
Set the value variable to be the line you want to evaluate.
C#:
var value = Console.ReadLine();
You would then check the pattern for a match and do as you please with the double value :
C#:
if (doubRegex.IsMatch(value)) /* Our double is not a string, so we convert to string to compare the pattern - IsMatch takes a string */
I suppose if a double value is not matched by the pattern, you could run an else if statement for the intRegex like so :
C#:
else if (intRegex.IsMatch(value))
And perhaps an else statement for non matching conditions above :
C#:
                else
                {
                    Console.WriteLine("That is not an accepted number");
                }
You could also use some static functions to evaluate whether or not the input value is actually a double or not by executing something like the below functions which will also update your get setters with the converted result if succeeded :
C#:
        public static bool IsInputDoubles(string value)
        {
            var newValue = 0.0;
            if (double.TryParse(value, out newValue)) /* Is it a double */
            {
                doubNota = newValue;
                return true;
            }
            return false;
        }
        public static bool IsInputIntegeral(string value)
        {
            var newValue = 0;
            if (int.TryParse(value, out newValue)) /* Is it a integer */
            {
                iNota = newValue;
                return true;
            }
            return false;
        }
You would then call these functions with the below code and if they return true. the conversions succeeded, and if they are false, add an else condition for failures and evaluation? As follows :
C#:
                    if (IsInputDoubles(value)) /* Is it a double? */
                    {
                        Console.WriteLine($"Double is {doubNota}");
                    }
AND :
C#:
                    if (IsInputIntegeral(value)) /* Is it a integer */
                    {
                        Console.WriteLine($"Integer is {iNota}");
                    }
Now it's up to you to put it together. I've tested the regular expression patterns and they appear to work after running one or two quick tests. And my preferences are to use TryParse over Parse, because if the input value is not in the expected format, and if it can't be parsed using Parse, you will be likely introduced to a FormatException or alike. Whereas TryParse returns a bool value indicating if the conversion succeeded or not, and this thus not throw an exception, and it is my preferred choice since it fails silently. Remember to check the condition of the result. I would only use Parse if I was 100% sure that the validation events that took place prior executing Parse ensured the value was correct and evaluated before executing it with Parse method.

Just to elaborate on one other point. Note I am using property values of iSoma, and iNota. These are only for type integral values; hence the i before the name. The same for doubNota and doubSoma, the doub before your variable name implying it should be used with doubles. And so, if you wish to work with additional values, you should assign additional individual properties specific to their variable type. Further note; when user input has been validated and parsed, you will refer to these properties directly when you want to update or use the values results.

How I allow for non-numeric input too?

That depends on what user-input is received. Typically using simple conditional if-else statements can suffice.

This post was longer than i wanted it to be, but hopefully helps. :)
 
Last edited:
I want invalid inputs to be deleted and allow the user to enter 10 valid grades
That's way too vague. This is the main reason that beginners have trouble writing code to achieve their aim: they don't know what their aim is. You should pretty much always start solving a programming problem by forgetting that it is a programming problem. Assume that you need to perform the task manually, with pen and paper. What steps would you perform? Assume that you have to provide detailed instructions to someone else to perform those steps. Write down those instructions. If you can then follow those instructions and those instructions alone and achieve your end goal then you have yourself an algorithm. Only then should you start treating it as a programming problem and the code you write should be an explicit implementation of your algorithm. At every step, you can compare your code to your algorithm to make sure that it does what it is supposed to do. If the code doesn't work properly then either it is not a faithful implementation of the algorithm or else the algorithm is faulty. Working out exactly where the code doesn't work is easy because you know exactly what should happen at every step and you can debug to make sure that it does happen that way. The first step that produces unexpected results is the specific site of an issue.
 
Back
Top Bottom