Loop not looping and 2nd If not Iffing - vb.net

Here's all my code
Module Module1
Sub Main()
Dim yob As Integer
System.Console.WriteLine("If you would as be kind as to input your year of birth then I will tell you how old you are")
loops:
Try
yob = Int32.Parse(Console.ReadLine())
Catch ex As SystemException
Console.WriteLine("that is not a number, try again.")
GoTo loops
Finally
End Try
Do Until yob > 0 And yob < DateTime.Today.Year
Loop
If yob < 0 Or yob > DateTime.Today.Year Then
Console.WriteLine("You entered a number that is either zero or a date in the future.")
Console.WriteLine("You can't be born in the future. C'mon son")
Console.WriteLine("Try again")
End If
Dim Age = DateTime.Today.Year - yob
Console.WriteLine("You are " & Age & " years old")
If Age > 100 Then
Console.WriteLine("You are were born over a 100 years ago and little is known about that time since there was no Facebook, Twitter or Instagram for people to log their every")
Console.WriteLine(" thought, action, emotion, or take pictures of their food before this time")
Console.ReadKey()
End If
If Age > 90 Then
Console.WriteLine("You were born in the 20s")
Console.WriteLine("In this decade Halloween was born. The first Halloween celebration in America took place in Anoka, Minnesota in 1921. ")
Console.ReadKey()
End If
End Sub
End Module
Until I added a goto in my try catch block my loop would run fine. Now it doesn't and if you input a year bigger than 2014 It just sits their.
The other problem I have is that my 2nd If doesn't work. If you put in a year that makes your age bigger than 90 It doesn't do anything and the program closes without performing the If statements.
Any Ideas on what's wrong?

The code you want to loop has to be in the Do loop.
Do
Try
yob = Int32.Parse(Console.ReadLine())
Catch ex As SystemException
Console.WriteLine("that is not a number, try again.")
GoTo loops
Finally
End Try
Loop Until yob > 0 And yob < DateTime.Today.Year

Wow, a Goto. Not everyday that you see one of those, and for good reason. You shouldn't use it. There are some situations where it's useful, but you are not likely to actually encounter one of them, ever.
The reason that the code stops for a year out of range is that you have an empty loop where you check the year. As the variable can't change inside the loop, the loop will never end.
You should use the loop around the input instead of after it, and do all the checking inside the loop. You can use the TryParse method instead of letting the code throw an exception, it's usually better to check for the condition that would cause an error instead of waiting for it to happen:
Dim yob As Integer
System.Console.WriteLine("If you would as be kind as to input your year of birth then I will tell you how old you are")
Dim inputting As Boolean = True
Do While inputting
Dim input As String = Console.ReadLine()
If Int32.TryParse(input, yob) Then
If yob <= 0 Or yob > DateTime.Today.Year Then
Console.WriteLine("You entered a number that is either zero or a date in the future.")
Console.WriteLine("You can't be born in the future. C'mon son")
Console.WriteLine("Try again")
Else
inputting = False
End If
Else
Console.WriteLine("that is not a number, try again.")
End If
Loop
When I test with a year that makes me 94, the second If statement works fine. However, it only checks the lower bound, so if I enter a year that makes me 150 years old, it still says that I was born in the twenties.
Also, being between 90 and 100 doesn't mean that you were born in the twenties, but being between 85 and 95 does. You might want to use the actual birth year in that condition instead of the age:
If yob >= 1920 And yob <= 1929 Then
Side note: Only the birth year is not enough to accurately determine the age. If I was born 1994 it's not certain that I am 20 years old, if I haven't had my birthday yet this year, I'm still 19.

There are two problems in your code. (Well, three if I count also the goto)
The first one is the empty do while that, if you type a value bigger than the current year, will loop forever as pointed in the comments above. The second problem is the lacking of an else if between your two outputs. If I have more than 100 years then I have also more than 90 years and you write both statements.
The first problem is fixed removing all the try/catch block and the Do while loop with
While True
if Int32.TryParse(Console.ReadLine(), yob) then
if yob > 0 And yob < DateTime.Today.Year then
Exit While
else
Console.Writeline("Enter a number between 0 and " & DateTime.ToDay.Year)
End if
else
Console.Writeline("This is not a number")
End if
End While
Notice that TryParse is preferable to the simple Parse because if the input is not a number it will return false and it doesn't throw an exception.
The second problem is simply fixed adding the appropriate else if (and use Console.Readline to be sure to exit when the user presses enter)
If Age > 100 Then
.....
Console.ReadLine()
else If Age > 90 Then
....
Console.ReadLine()
End If
However keep in mind that calculating the age of a person is not a simple task as it seems.
Look at this question

Related

IsNumeric statement and a range

Hey everyone I am working on an assignment where i have to validate the user input data. When asking my instructors if i can use a IsNumeric to validate a range between two numbers he just said yes and did not show me how.
Now I know you can validate using if statements , and i have several doing so with a basic:
if hours < 0 then
Messagebox("Please enter a value greater than 0" "Input Value to
low" messagebox.buttons retry/cancel) ''something like that
Elseif hours > 23 then
Messagebox( "please enter a value less than 23" "Input Value to
high" messagebox.buttons retry/cancel)
End if
I even asked him if i can use a AND in the if statement to range the data. Again yes with no example
Example that i had in mind
If hours < 0 AND hours > 23 then
'' continue processing
Else
Messagebox("Please enter a Value between 0 and 23" "Input
value
out of range" messagebox.buttons retry/cancel)
End if
In response to your example you can try this:
If isnumeric(hours) then
If hours < 0 AND hours > 23 then
'' continue processing
Else
MessageBox.Show("Input value out of range",
"Please enter a Value between 0 and 23",
MessageBoxButtons.RetryCancel)
End if
End if
IsNumeric() is old... modern practice would tend to use Integer.TryParse() or Double.TryParse(), depending on what kind of value you need. You can also use CInt() or Convert.ToInt32(), but when you know you start with a string, parsing is the best choice.
But what concerns me is you should also have Option Strict turned on, or at least Option Infer. Anything else is really poor practice. With that in mind, look at this code:
Dim hours As String = GetSomeValueFromUser()
If IsNumeric(hours) Then
If hours < 0 Or hours > 23 Then 'a value can never be both negative *and* greater than 24
'...
End
End If
In any sensible project, that should be a compiler error, because it uses a string value (hours) as if it's a number. It doesn't matter that you checked with IsNumeric() first. If you're using Option Strict, as you should be, that's still an error.
This is much better practice:
Dim hours As String = GetSomeValueFromUser()
Dim hrs As Integer
If Integer.TryParse(hours, hrs) AndAlso hrs>= 0 AndAlso hrs <= 23 Then
'code here
Else
MessageBox.Show("Please enter a Value between 0 and 23" "Input value out of range", MessageBoxButtons.RetryCancel)
End If
One additional thing here: NEVER declare a variable for Function without an explicit type known to the compiler. Option Infer can muddy the waters there somewhat, but generally the type of a variable should always be known and fixed.

Do Until Loop InputBox infinitely loops

I am creating a probability macro where user enters number of players in a card game. If I enter string (ex, Joe), non-integer(ex, 15.67), or integer less than 0 (ex, -25), the InputBox should loop. However, integers greater than 0 should terminate the loop. (I have to force kill Excel to stop the InputBox regardless of user input.)
I want the InputBox to close / Exit Sub once an integer greater than 0 is entered. What am I doing wrong here?
Sub GenerateCards()
Players = InputBox("How many players? Please enter an integer.")
Do Until TypeName(Players) = "Integer" And Players > 0 ' why does this loop even if both conditions are met (ex, Players=5?)
Players = InputBox("How many players? Please enter an integer.")
Loop
End Sub
InputBox() always returns a string, so TypeName() will always return "String".
But you can test if the string that's returned is an integer. First, you can use IsNumeric() to test if the string is a numeric value. Then, you can safely cast it to a Double or an Integer. In fact, you can cast it to both and then compare them against each other. If they're the same, you've got an integer value. For example:
Sub GenerateCards()
Do
Players = InputBox("How many players? Please enter an integer.")
If IsNumeric(Players) Then
If CDbl(Players) = CLng(Players) And Players > 0 Then
' Integer > 0 entered. Exit loop...
Exit Do
End If
End If
Loop
End Sub

Excel VBA: Case query

I have this code, which sorts an input number into a convenient range:
Public Sub TestCase2()
Dim Number As Long
Dim Message As String
Number = InputBox("Enter a number:", "Number entry")
Message = "Number is "
Select Case Number
Case Is < -10
MsgBox (Message & "less than -10")
Case Is < 0
MsgBox (Message & "equal to or greater than -10 but less than zero")
Case Is = 0
MsgBox (Message & "equal to zero")
Case Is < 10
MsgBox (Message & "greater than zero but less than 10")
Case Else
MsgBox (Message & "greater than or equal to 10")
End Select
End Sub
It falls over when I enter -10.5 - I would have thought it would output:
Number is less than -10
But it says:
Number is equal to or greater than -10 but less than zero.
If I enter -10.6, the output is as expected: Number is less than -10.
Also, it falls over with an entry of 0.001: it says Number is equal to zero. Which it isn't.
I cannot work with integers here - the input has to have decimals (up to 3).
Is there a neater way of doing this? Many thanks for your constructive input.
Regards,
Shane (VBA newbie of 4 weeks).
PS I know I can do this with If-Then statements, but I'm just getting to grips with Select Case-Case Else).
InpuBox function returns string. So, to be able to compare value returned by this function, you need to convert it into proper numeric format:
Dim sNumber As String
sNumber = InputBox(...)
'prevent Cancel click
If sNmber = "" Then Exit Sub
'prevent non-numeric value
If Not IsNumeric(sNmber) Then Exit Sub
Select Case CDbl(sNumber)
....
If you want to use If .. else statement instead of Select case , please see: If .. Then ... Else ...
Number may have to be dimmed as Single or Double
Dim Number As Single

What's Wrong With my logic in this Vb program?

I'm new to visual basic and I just started taking classes on it at school. I was given an assignment to write an app that tells if an input in a textbox is a Prime Number Or Not.
I have written this code snippet in Visual Studio:
Public Class PrimeNumberApp
Public Sub CheckButton_Click(sender As Object, e As EventArgs) Handles CheckButton.Click
Dim x, y As Integer
x = Val(PrimeTextBox.Text)
For y = 2 To (x - 1)
Select Case x
Case Is = (33), (77), (99)
MsgBox("Its not a prime number, try a different number!")
Exit Sub
End Select
If x Mod y = 0 Then
MsgBox("Its not a prime number, try a different number!")
Exit Sub
Else
MsgBox("Its a prime number, you're golden!")
Exit Sub
End If
Next
Select Case x
Case Is <= 0
MsgBox("I'm only accepting values above 0. :p")
Exit Sub
End Select
End Sub
I have this code snippet displaying a Message Box telling whether the input by the user is a prime number or not with the help of the Mod operator in visual basic.
If you go through the code carefully, you'll notice I had to separately create more or less escape statements for the number 33, 77 and 99.
I had to do this cause every time I typed either of those three numbers, I'd get the result that the number is a prime number which is incorrect since they're all divisible by numbers apart from themselves. Without getting things mixed up, the program displays other prime and non-prime numbers with the right Message Box, just those three.
I had spent hours trying to figure out what I had done wrong before I added the lines below to put myself out of vb misery, lol.
Select Case x
Case Is = (33), (77), (99)
MsgBox("Its not a prime number, try a different number!")
Exit Sub
End Select
But doing this isn't healthy if I really want to be awesome at coding. So here's my question, how do I get this program fixed to display the right message box when any integer is typed in the text box. Thanks.
Your code doesn't seem to work at all. It seems to always say that every number is a prime number. You loop through every possible divisor and in that loop you test to see if the input is evenly divisible by the current divisor. That part makes sense. The problem, though is that you always immediately exit the loop after the first iteration regardless of the result of the test. Pay close attention to this code from inside your loop:
If x Mod y = 0 Then
MsgBox("Its not a prime number, try a different number!")
Exit Sub
Else
MsgBox("Its a prime number, you're golden!")
Exit Sub
End If
If we remove all of the spurious details, you can tell that the logic is flawed:
If MyTest = True Then
Exit Sub
Else
Exit Sub
End If
As you can see, no matter what the result of the test is, it's always going to exit the loop. Therefore, the loop will never progress beyond the first iteration. In order to make it continue testing every possible divisor, you need to remove the Exit Sub statements and just keep track of the result in a variable. For instance, something like this:
Dim isPrime As Boolean = True
For y = 2 To x - 1
If XIsEvenlyDivisibleByY Then
isPrime = False
Exit For
End If
Next
If isPrime Then
' ...
Else
' ...
End If
Notice that once the first evenly divisible divisor is found, I have it Exit For. There's no point in searching any further since one is enough to make it not prime.
For what it's worth, you should use Integer.TryParse rather than Val and you should use MessageBox.Show rather than MsgBox. Val and MsgBox are old VB6 style functions. It's preferable to use the newer .NET-only versions.
here is an example of how to find prime numbers, for example up to 100, using 2 loops to check every single number in a given range. In this case I started by 2 because as you know 2 is the smallest of the prime numbers.
Dim i As Integer = 2, j As Integer = 2
For i = 2 To 100
For j = 2 To (i / j)
If i Mod j = 0 Then
Exit For
End If
Next
If (j > (i / j)) Then
Console.WriteLine("{0} is prime", i)
End If
Next

How can I check string in textbox as integer in Visual Basic?

I have 3 textboxes (day, month, year) and I want to check if input is e.g. day has to be from 1 to 31 and so on.
My code is:
If InputDan.Text < "1" Or InputDan > "31" Then Warning.Text = "Not a valid day input." Else Warning.Text = ""
Also I have day and month input limited to 2 characters and year to 4.
It works fine with numbers from 10 to 31 and it properly puts an warning message when input is 0 or 32 and on.
Here's the problem...
When I put in numbers from 4 to 9 it puts on a warning message, as I figured out later that program considers empty space after one character input as 0.
So if I enter 4 the program will read it as 40, and so on.
Can I solve this problem with converting String input as Int somehow?
You need to parse the numbers to integer before you can compare them, otherwise >"11" will compare them alphabetically and not by their numerical order.
Dim day As Integer
Dim valid As Boolean = Int32.TryParse(InputDan.Text, day)
Now you know if that input was a correct number and you could show a warning if it was not.
I would suggest a different approach to check whether or not the input was a correct day since you must take the number of days in that month into account(also leap years, different calendars etc). So use the current culture's calendar and look if the number of days is correct for the given month in this way:
Dim daysInMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(year, month)
If day > daysInMonth OrElse day < 1 Then
' show warning '
End If
(assuming you have already checked the year and month part with Int32.TryParse)
Better than doing this from the code behind, asp.net has already validations here is an example of a textbox that represents the day, and it has to be between 1 and 31:
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RangeValidator ID="RangeValidator1" runat="server"
ErrorMessage="You have to insert a valid day" ControlToValidate="TextBox2" MaximumValue="31" MinimumValue="1"></asp:RangeValidator>
check it out
Your problem is, that "9" (the string) IS "larger" than "31". Because sorting is done on the first char, then the second and so on.
Dim Value As Integer
' is there an (integer) NUMBER in the textbox?
If Integer.TryParse(InputDan.Text, Value) Then
If Value > 0 AndAlso Value < 31 Then
' do something
Else
MessageBox.Show("please enter a number!")
End If
Else
MessageBox.Show("please enter a number!")
End If
With "TryParse" you can test if a String can be converted to an Integer (or Double, Single, whatever implements a TryParse method) and if it can be converted, the value is stored in the second parameter.
You should use Strict on" to avoid the coding problems - basically you are comparing strings against each other. They do NOT behave like Integers for comparisons.
Try like this: (Assuming framework above/or 3.5)
If Not IsNumeric(InputDan.Text) OrElse _
Not Enumerable.Range(1, 31).Contains(CInt(InputDan.Text)) Then
Warning.Text = "Not a valid day input."
Else
Warning.Text = ""
End If
It will first validate the input must be a number and then will validate if it lies within range of 1 and 31. I assume Days can not be 1.5 so I called CInt.
OrElse is what we call ShortCircuit. The second condition will not evaluate if the first one failed.