Showing the name of the most expensive product in vb - vb.net

i'm pretty new to programming and i got stuck trying to write a program where you type in the name and prices of products and you get back the total, the name+ prices and the most expensive product. Everything works fine except showing the name of the most expensive product.
Here's what i've done
""
Public Class Mrj
Shared Sub main()
Dim i, n As Integer
Console.WriteLine("Enter the number of products")
n = Console.ReadLine()
Dim Products_name(n) As String
Dim Products_price(n), HT, TTC, TVA, max As Decimal
For i = 1 To n
Console.WriteLine("Enter the name of the product " & i)
Products_name(i - 1) = Console.ReadLine()
Console.WriteLine("Enter the price of the product " & i)
Products_price(i - 1) = Console.ReadLine()
HT = HT + Products_price(i - 1)
Next
For i = 1 To n
Console.WriteLine(Products_name(i - 1) & " " & Products_price(i - 1))
Next
TVA = 0.2 * HT
TTC = HT + TVA
Console.WriteLine("Total to pay " & TTC)
max = Products_price(0)
For i = 1 To n - 1
If max > Products_price(i) Then
Else
max = Products_price(i)
End If
Next
Console.WriteLine("The product the most expensive is" & max & Products_name(i))
End Sub
End Class
""

I think the problem is that you are using i to get the name of the most expensive product, but that index i is always i = n since you don't save the index of the maximum value.
You should add a new variable where you store the index everytime you get a new maximum value, and use it in the last line.
Your for loop should be something like this:
Dim max_index As Integer
For i = 1 To n - 1
If max > Products_price(i) Then
Else
max = Products_price(i)
max_index = i
End If
Next
Console.WriteLine("The product the most expensive is" & max & Products_name(max_index))
Try this out and check if it works.

Turn on Option Strict now and forever. Project Properties -> Compile tab. Also for future projects Tools -> Options -> Projects and Solutions -> VB Defaults
You cannot assume that a user will actually enter a number. Test with TryParse.
Arrays in vb.net are declared Products_name(upper bound). In this case that would be Products_name(n-1)
Instead of doing i - 1 for the indexes in the For loop, start our with For i = 0 to n-1
I decided to not use the parallel arrays. Instead I made a tiny class and declared a List(Of Product). I filled the list with the user input setting the Properties of the Product.
I used Linq instead of loops for sums and max. Not necessarily faster but can be accomplished in a single line of code.
I use interpolated strings to display results. When your string is preceded by a $, you can insert variables directly in the text surrounded by braces. The colon following Price indicates a formatting character. Here, I used a C for currency.
Public Class Product
Public Property Name As String
Public Property Price As Decimal
End Class
Sub main()
Dim ProductList As New List(Of Product)
Dim n As Integer
Console.WriteLine("Enter the number of products")
Integer.TryParse(Console.ReadLine, n)
For i = 1 To n
Dim p As New Product
Dim pr As Decimal
Console.WriteLine("Enter the name of the product " & i)
p.Name = Console.ReadLine()
Console.WriteLine("Enter the price of the product " & i)
Decimal.TryParse(Console.ReadLine, pr)
p.Price = pr
ProductList.Add(p)
Next
For Each p In ProductList
Console.WriteLine($"{p.Name} {p.Price:C}")
Next
Dim SubTotal As Decimal = ProductList.Sum(Function(item) item.Price)
Dim Tax As Decimal = 0.2D * SubTotal
Dim Total = SubTotal + Tax
Console.WriteLine($"Total to pay {Total:C}")
Dim Prod = ProductList.OrderByDescending(Function(p) p.Price).FirstOrDefault()
Console.WriteLine($"The product the most expensive is {Prod.Name} at {Prod.Price:C}")
Console.ReadKey()
End Sub

Related

How do I debug this crash

My code:
Imports System
Module Program
Sub Main(args As String())
Dim Price As Integer
Dim Qty As Integer
Dim Total As Integer
Console.Write("Enter the product unit price. ")
Price = Console.ReadLine()
Console.Write("Enter the product quantity. ")
Qty = Console.ReadLine()
Total = Price * Qty
If (Qty > 99) And (Qty < 150) Then
Console.WriteLine("You did not qualify for a discount. Your total is: " + Total.ToString)
End If
If (100 < Qty > 149) Then
Console.WriteLine("You qualified for a 10% discount! Your total is: " + (Total * 1.1).ToString)
End If
If (Qty > 149) And (Qty < 200) Then
Console.WriteLine("You qualified for a 15% discount! Your total is: " + (Total * 1.15).ToString)
End If
If (Qty > 199) Then
Console.WriteLine("You qualified for a 20% discount! Your total is: " + (Total * 1.2).ToString)
End If
End Sub
End Module
I can run it to input the values but crash when the math component is executed. Any ideas on how to fix this silly little program?
This isn't a thing:
If (100 < Qty > 149) Then
If needs to look more like this:
If 100 <= Qty AndAlso Qty < 150 Then
The first condition should also just be If Qty < 100 Then
Worse, Qty is a STRING. For cultural/internationalization reasons, converting between strings and numbers is one of the slowest and most error-prone operations you can do within a single computer. It's something to minimize. Therefore you should parse the Qty and Price variables into actual Integer and Decimal variables once right after you read them from the user. Failure to do so makes the code seem amateurish.
Finally, rather than a bunch of If/Else conditions I'd put the data in an ordered map and take the first match:
Imports System
Imports System.Linq
Imports System.ValueTuple ' No longer needed on recent versions of VS
Module Program
Sub Main(args As String())
Console.Write("Enter the product unit price. ")
Dim Price As Decimal = Decimal.Parse(Console.ReadLine())
Console.Write("Enter the product quantity. ")
Dim Qty As Integer = Integer.Parse(Console.ReadLine())
Dim Total As Decimal = Price * Qty
Dim discount As Decimal = GetDiscount(Qty)
Dim discountMessage As String = "You did not qualify for a discount."
If discount > 0.0D Then
discountMessage = $"You qualified for a {discount:P0} discount!"
Total *= (1.0D - discount)
End If
Console.WriteLine($"{discountMessage} Your total is: {Total:C2}")
End Sub
Public Function GetDiscount(Qty As Integer) As Decimal
Dim discountMap() As (Integer, Decimal) = {
(200, 0.20D),
(150, 0.15D),
(100, 0.10D),
(Integer.MinValue, 0.00D)
}
Return discountMap.First(Function(m) m.Item1 <= Qty).Item2
End Function
End Module
If some of this code looks strange to you, it relies on Tuples, a lambda expression, and string interpolation; all three techniques are good tricks to add to your programming repertoire.

Math expression parsing: incorrect output when a + followed by a -

I am trying to create a program that parses an expression such as 3x^3 + 7x^2 + 6x - 9. I am using a recursive system to do this. At the moment, I'm just testing to see if I get the correct output for the expression I input by only using constants in the expression. The code works fine with most expressions, but when I have a minus followed by a positive, both terms are subtracted (first term should be subtracted, second term should be added). An example of this is entering 4*3^2-7*3+5*3. The answer to this is 30 but the program does 4*3^2-7*3-5*3 instead and outputs 0. I am unsure how to solve this.
Code:
Private Function ParseExpr(ByRef expression As String)
Dim op, op1 As Integer
op = ParseFactor(expression)
If expression.Length <> 0 Then
If (expression(0) = "+") Then
expression = expression.Substring(1, expression.Length - 1)
op1 = ParseExpr(expression)
op += op1
ElseIf (expression(0) = "-") Then
expression = expression.Substring(1, expression.Length - 1)
op1 = ParseExpr(expression)
op -= op1
End If
End If
Return op
End Function
All is well with raising to a power and multiplication. At that point we are simplified to 36-21+15. Here we must remember that we are adding -21. So we need to go back to -7 . When I build my list of numbers (it handles numbers of more than one digit) I add the minus sign to the number it precedes.
This code does not handle decimal numbers or parenthesis. I think you will be able to add the division operator, if you wish.
Private NumList As New List(Of Double)
Private OperatorList As New List(Of String)
Private Sub OpCode()
Dim Input = "14*3^2-7*3+15*3"
PopulateLists(Input)
Dim OpIndex As Integer
Dim NewNum As Double
Dim operators = {"^", "*", "+"} 'Note: no minus sign, the minus goes with the number
For Each op In operators
Do
OpIndex = OperatorList.IndexOf(op)
If OpIndex = -1 Then
Exit Do
End If
Select Case op
Case "^"
NewNum = NumList(OpIndex) ^ NumList(OpIndex + 1)
Case "*"
NewNum = NumList(OpIndex) * NumList(OpIndex + 1)
Case "+"
NewNum = NumList(OpIndex) + NumList(OpIndex + 1)
End Select
NumList.RemoveAt(OpIndex + 1)
NumList(OpIndex) = NewNum
OperatorList.RemoveAt(OpIndex)
Loop
Next
MessageBox.Show(NumList(0).ToString) 'Displays 150
End Sub
Private Sub PopulateLists(Input As String)
Dim strNum As String = ""
For Each c As Char In Input 'Be careful here, the IDE wants to add () at the end of this line - it doesn't belong
If Char.IsDigit(c) Then
strNum &= c
ElseIf c = "-" Then
OperatorList.Add("+") 'We are adding a negative number
NumList.Add(CDbl(strNum)) 'Add the last number we accumulated so we can start a new one with the minus sign
strNum = "-" 'Start a new number with the minus sign
Else 'The other operators are added to the list
OperatorList.Add(c)
NumList.Add(CDbl(strNum))
strNum = ""
End If
Next
NumList.Add(CInt(strNum)) 'The last number which will not be followed by an operator
End Sub

Is there a way to add up items(numbers) in the listbox and display them in the same box in visual basic

So I'm a beginner in vb class and am wondering how I can add up all products of Modnumber(variable name) Mod 2 so that i can attach them into one single line at the bottom of my listbox. What line should i add so the program runs like the pic below?
Dim number As Integer
Dim Modnumber As String
number = InputBox("I'm kindly asking you to tell me a number", "Number")
LstNumber.Items.Clear()
Do Until number = 1
Modnumber = number
LstNumber.Items.Add(number & vbTab & Modnumber Mod 2)
'each time it devides the number by two until number = 1
number \= 2
Loop
This is what I get
This is what I'm supposed to get in my lstbox
'capture your original input to use in the final result
Dim input = InputBox("I'm kindly asking you to tell me a number", "Number")
Dim number As Integer = input
Dim modNumber As Integer 'Changed this to a number
Dim result As New StringBuilder 'Used to store the product of doing Mod 2
LstNumber.Items.Clear()
Do Until number = 0 'loop until 0 instead of 1
modNumber = number Mod 2 'Do mod outside of LstNumber add so u can retain the value
LstNumber.Items.Add(number & vbTab & modNumber)
result.Insert(0, modNumber) 'Build your result string
number \= 2
Loop
'Add your additional stuff
LstNumber.Items.Add("Therefore")
LstNumber.Items.Add($"{input} = {result.ToString}") 'Original input plus built string

Trying to shorten code in VB.NET

One of my assignments in vb.net is to make a program that takes in 15 inputted "test scores", returns the average, and then returns the corresponding letter grade. I am trying to make this as short as possible, and I remembered a code format that I can use when I am coding in Python (simple example with only three scores):
counter = 0
number = 0
test1,test2,test3 = 0,0,0
for i in [test1,test2,test3]:
print("Enter a test score")
i = int(input())
counter += i
number += 1
average = counter/number
Is there such a code format in VB.NET?
Yes.
Here is a simple sample code which asks user to input number of items and then items one by one. At the end it calculates average of numbers.
Console.WriteLine("Enter number of Items")
Dim numberOfItems As Integer
If Integer.TryParse(Console.ReadLine(), numberOfItems) Then
Dim items As New List(Of Decimal)()
For i As Integer = 1 To numberOfItems
Console.WriteLine("Enter number {0}", i)
Dim num As Decimal
If Decimal.TryParse(Console.ReadLine(), num) Then
items.Add(num)
End If
Next
Console.WriteLine("Average is " + items.Average())
Console.ReadLine()
End If
Please note that I've not included any type of error handling.

How do you find greatest number among 5 with vb.net?

This is code for finding maximum in 3 but i want the code for finding maximum amoung 5:
Dim a, b, c As Integer
a = InputBox("enter 1st no.")
b = InputBox("enter 2nd no.")
c = InputBox("enter 3rd no.")
If a > b Then
If a > c Then
MsgBox("A is Greater")
Else
MsgBox("C is greater")
End If
Else
If b > c Then
MsgBox("B is Greater")
Else
MsgBox("C is Greater")
End If
End If
Put the values into an array and use the Max function on IEnumerable:
'Requires Linq for Max() function extension
Imports System.Linq
'This is needed for List
Imports System.Collections.Generic
' Create a list of Long values.
Dim longs As New List(Of Long)(New Long() _
{4294967296L, 466855135L, 81125L})
' Get the maximum value in the list.
Dim max As Long = longs.Max()
' Display the result.
MsgBox("The largest number is " & max)
' This code produces the following output:
'
' The largest number is 4294967296
As David suggested, keep your values in a list. That's easier than using individual variables and can be extended to as many values as requested (up to millions of values).
If you need to keep individual variables for some reason, do this:
Dim max As Integer = a
Dim name As String = "A"
If b > max Then
max = b
name = "B"
End If
If c > max Then
max = c
name = "C"
End If
If d > max Then
max = d
name = "D"
End If
' ... extend to as many variables as you need.
MsgBox(name & " is greater")
A simple solution for you,
Dim xMaxNo As Integer
Dim xTemp As Integer
For i as integer = 1 To 5
xTemp = InputBox("enter No: " & i)
xMaxNo = if(xTemp > xMaxNo, xTemp, xMaxNo)
Next
MsgBox("The Highest Number is " & xMaxNo)