private void btnCalculate_Click(object sender, RoutedEventArgs e)
{
double pay;
pay = 0.00;
double add;
add = 0.00;
int age;
age = int.Parse(txtAge.Text);
string month;
month = txtMonth.Text;
if (age >= 18 && age <= 55)
{
pay = 350;
}
else if (age <= 18)
{
pay = 150; //if-else-if statements depending on age
}
else if (age > 55)
{
pay = 35;
}
switch (month)
{
case "January":
case "january":
case "July":
case "july": //switch statement, how much you pay depending on month
add = 100;
break;
case "February":
case "february":
case "August":
case "august":
add = 120;
break;
case "March":
case "march":
case "September":
case "september":
add = 140;
break;
case "April":
case "april":
case "October":
case "october":
add = 160;
break;
case "May":
case "may":
case "November":
case "november":
add = 180;
break;
case "June":
case "june":
case "December":
case "december":
add = 120;
break;
}
lblTotal.Content = (pay + add) * 1.13; //calculation that prints to the label
}
So when I run the code it just outputs 0 in the label
If I put the Calculation at the bottom (seen here) it will say something about the label not being reachable. Any help would be great. Code has been solved
You can directly assign variables. Declaration and assignment need not be different statements.
18 has two different checks: >= 18 in the if, and <= 18 in the first else if. Not a code error but a semantics error.
The final assignment is inside the switch block and unreachable. Put it outside the switch.
It looks like you're using WPF? If so, you should have a look at the MVVM pattern, as well as data binding. It's a good bit to learn and not easy but very important in WPF. It will eliminate the need for querying and writing properties of elements in most cases, though – because that will be handled by the runtime.
Also consider using a ComboBox for the month. Way easier to validate the data.
As suggested your label assignment was inside the switch statement causing it not to execute unless the month was June or December.
In any case, I'd suggest though that you simplify.
Try this:
private void btnCalculate_Click(object sender, RoutedEventArgs e)
{
int age = int.Parse(txtAge.Text);
double pay = age <= 18 ? 150.0 : (age > 55 ? 35.0 : 350.0);
int index = (DateTime.Parse("1 " + txtMonth.Text).Month - 1) % 6;
double[] choices = new [] { 100.0, 120.0, 140.0, 160.0, 180.0, 120.0 };
double add = choices[index];
lblTotal.Content = (pay + add) * 1.13;
}
The label assignment was inside the switch statement. There's a lot of other improvements you can make to code as well.
For starters, you can also join assignment and declaration of variables and use .ToLower() in switch to save yourself the extra cases:
private void btnCalculate_Click(object sender, RoutedEventArgs e)
{
var pay = 0.00;
var add = 0.00;
var age = int.Parse(txtAge.Text);
var month = txtMonth.Text;
if (age >= 18 && age <= 55)
{
pay = 350;
}
else if (age <= 18)
{
pay = 150;
}
else if (age > 55)
{
pay = 35;
}
switch (month.ToLower())
{
case "january":
case "july":
add = 100;
break;
case "february":
case "august":
case "june":
case "december":
add = 120;
break;
case "march":
case "september":
add = 140;
break;
case "april":
case "october":
add = 160;
break;
case "may":
case "november":
add = 180;
break;
}
lblTotal.Text = Convert.ToString((pay + add) * 1.13); //calculation that prints to the label
}
Related
So I am currently trying to finish this program that when you input a number correlating to the days of the week, it reflects the text connected to the numeric variable. (IE : Sunday - 1, Monday - 2, etc etc.)
I have found a functioning code that makes the program work, but it outputs incorrect information. No matter what number I put in, it always displays Sunday. And it doesn't stop me from inputting bad variables. Which I want it to. I'm frustrated at this point and I am very new to all of this. Can someone check over my code and tell me what I'm doing incorrectly? Thank you.
private void OkButton_Click(object sender, EventArgs e)
{
string day ="1";
int number;
if (int.TryParse(day, out number))
{
if (number >= 7 && number <= 1)
{
switch (day)
{
case "1":
dayOutputLabel.Text = "Sunday";
break;
case "2":
dayOutputLabel.Text = "Monday";
break;
case "3":
dayOutputLabel.Text = "Tuesday";
break;
case "4":
dayOutputLabel.Text = "Wednesday";
break;
case "5":
dayOutputLabel.Text = "Thursday";
break;
case "6":
dayOutputLabel.Text = "Friday";
break;
case "7":
dayOutputLabel.Text = "Saturday";
break;
}
}
else
{
MessageBox.Show("Invalid number input. Please use a number between 1 and 7.");
}
}
else
{
MessageBox.Show("Please put in a valid number.");
}
}
private void ExitButton_Click(object sender, EventArgs e)
{
this.Close();
}
Looks like you've hard coded day = "1" (i.e. Sunday).
Also this is a mistake:
if (number >= 7 && number <= 1)
Surely you meant...
if (number >= 1 && number <= 7)
I can't tell precisely what sort of project you're working on, but the following slight modification works in wpf and should be all you need to solve this:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
string day = myTextBox.Text.Trim();
int number = 0;
if (int.TryParse(day, out number))
{
if (number >= 1 && number <= 7)
{
switch (day)
{
case "1":
dayOutputLabel.Content = "Sunday";
break;
case "2":
dayOutputLabel.Content = "Monday";
break;
case "3":
dayOutputLabel.Content = "Tuesday";
break;
case "4":
dayOutputLabel.Content = "Wednesday";
break;
case "5":
dayOutputLabel.Content = "Thursday";
break;
case "6":
dayOutputLabel.Content = "Friday";
break;
case "7":
dayOutputLabel.Content = "Saturday";
break;
}
}
else
{
MessageBox.Show("Invalid number input. Please use a number between 1 and 7.");
}
As mentioned in the comment above... here is a possible solution using the System.DayOfWeek enumeration:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
// this TryParse makes use of pattern matching
if(int.TryParse(myTextBox.Text.Trim(), out var input) && input >= 0 && input <= 6)
{
// this should automatically convert to the name of the day of week
// if not, add .ToString() at the end
dayOutputLabel.Content = (DayOfWeek)input;
}
else
{
MessageBox.Show(
text: "Please use a number between 0 and 6",
caption: "Invalid Input",
buttons: MessageBoxButtons.OK,
icon: MessageBoxIcon.Error);
}
}
And here is an another option using Enum.TryParse() instead:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
// this TryParse makes use of pattern matching
if(Enum.TryParse(myTextBox.Text.Trim(), out DayOfWeek input) &&
input >= DayOfWeek.Sunday && input <= DayOfWeek.Saturday)
{
// this should automatically convert to the name of the day of week
// if not, add .ToString() at the end
dayOutputLabel.Content = input;
}
else
{
MessageBox.Show(
text: "Please use a number between 0 and 6",
caption: "Invalid Input",
buttons: MessageBoxButtons.OK,
icon: MessageBoxIcon.Error);
}
}
switch(number){
case 2:
a+=b;
break;
case 3:
a+=b;
break;
case 4:
a+=b;
d=f;
break;
case 5:
d=e;
break;
}
how to minimize first three switch cases which which does similar work?
If you using C# 7, you can make use of Pattern Matching, even though this is an overkill as rightly pointed by Jon Skeet. But in case, you want to stick to switch case, and want to reduce 'case', you could do the following
switch(number)
{
case var _ when number == 2 || number==3 || number==4:
a+=b;
if(number ==4)
d=f
break;
case 5:
d=e;
break;
}
You can also replace the first case with variants like
case var _ when new[]{2,3,4}.Contains(number):
Or
case var _ when number >= 2 || number <= 3: // As pointed by earlier answer
Without pattern matching, you could do the following as well
switch(number)
{
case 2:
case 3:
case 4:
a+=b;
if(number ==4)
d=f;
break;
case 5:
d = e;
break;
}
Btw, if your problem is "a+b" is about 60 lines of code, you always have the option to make it a function (and move it out of switch case) to increase its readability.
switch(number)
{
case 2:
case 3:
case 4:
MethodAbAction();
if(number ==4)
MethodDFAction();
break;
case 5:
MethodDEAction();
break;
}
btw, a 60 line method is never fun to read. It would be better if you can split up.
if (2 <= number && number <= 4) {
a += b;
}
if (number == 4) {
d = f;
} else if (number == 5) {
d = e;
}
if (number != 5)
{
a += b;
}
if (number == 4)
{
d = f;
}
else
if (number == 5)
{
d = e;
}
when i tried to use the Switch case function, it goes always to the default message besides case 5:
private void btnCandlesLight_Click(object sender, EventArgs e)
{
int result;
result = Convert.ToInt32(textBox1.Text);
switch(result)
{
case 1:
day1.Start();
candlesOne();
break;
case 2:
day2.Start();
candlesTwo();
break;
case 3:
day3.Start();
candlesThree();
break;
case 4:
day4.Start();
candlesFour();
break;
case 5:
day5.Start();
candlesFive();
break;
case 6:
day6.Start();
candlesSix();
break;
case 7:
day7.Start();
candlesSeven();
break;
case 8:
day8.Start();
candlesEight();
break;
default:
MessageBox.Show("Enter new day");
break;
}
}
When I Enter the value 1 for example to the text box, the default case works, but only when I enter the value 5 it works perfectly.
If you want to see the difference between the function "candlesOne" to "candlesFive":
The "c" variable is a variable of the seconds. i tried to use a timer in a way of lighting up the candles every 2-3 seconds.
public void candlesOne()
{
firedmatch.Left = firedmatch.Left + 100;
if (c == 1)
{
candle1.Visible = true;
}
if (c == 3)
{
candle2.Visible = true;
}
}
and:
public void candlesFive()
{
firedmatch.Left = firedmatch.Left + 100;
if(c == 1)
{
candle1.Visible = true;
}
if(c == 3)
{
candle2.Visible = true;
}
if(c == 5)
{
candle3.Visible = true;
}
if(c == 7)
{
candle4.Visible = true;
}
if(c == 11)
{
candle5.Visible = true;
}
}
I haven't found a mistake,
can you guys help me?
Thanks
Have you checked if you really get for example (int)1 as a result of the "1" input from your conversion?
On a broader scale, there is a lot of repetition in your code, you should consider refactoring it a little.
In your CandlesOne and CandlesFive methods, you use a c variable, no idea what that is or where it comes from. Those two methods (and probably the other CandlesXXX() do the same kind of things. Can't you remove complexity by generalizing the logic? Can the result used in your switch-case be passed as a parameter and used to trigger the numbers of c == X calls in the CandleXXX() methods?
This way you could remove the switch and lose a lot of complexity!
Edit
If you have further problems, consider creating a .NET Fiddle, I miss a lot of context in your code so I cannot efficiently help you here.
Some refactoring ideas for you:
// Somewhere else in your code, create a dictionary with your day1-day8 objects
var days = new Dictionary<int, Day>()
days[1] = day1;
...
days[8] = day8;
//Simplfiy your method
private void btnCandlesLight_Click(object sender, EventArgs e)
{
try
{
var dayIndex = Convert.ToInt32(textBox1.Text);
if(dayIndex > 0 && dayIndex <= 8)
{
days[dayIndex].Start(); //Get the corresponding day via its Key
LightUpCandles(dayIndex); //pass the key as a parameter
}
else
{
MessageBox.Show("Enter new day");
}
}
catch(InvalidCastException exception)
{
//Whatever you do when the textbox cannot be parsed
}
}
I still don't get what your candlesOne to five methods are really doing or why the method "candlesOne" lights up two candles (pay attention to the variable naming). I also don't get how this makes up some kind of timer... but here's a first potential refactoring for it anyway:
public void LightUpCandles(int dayIndex)
{
firedmatch.Left = firedmatch.Left + 100;
if(c == 1)
{
candle1.Visible = true;
}
if(c == 3 && dayIndex > 1)
{
candle2.Visible = true;
}
if(c == 5 && dayIndex > 2)
{
candle3.Visible = true;
}
if(c == 7 && dayIndex > 3)
{
candle4.Visible = true;
}
if(c == 11 && dayIndex > 4)
{
candle5.Visible = true;
}
}
Your switch logic is correct which I tested with the following;
int result;
result = Convert.ToInt32(textBox1.Text);
switch (result)
{
case 1:
MessageBox.Show("1");
break;
case 2:
MessageBox.Show("2");
break;
case 3:
MessageBox.Show("3");
break;
case 4:
MessageBox.Show("4");
break;
case 5:
MessageBox.Show("5");
break;
case 6:
MessageBox.Show("6");
break;
case 7:
MessageBox.Show("7");
break;
case 8:
MessageBox.Show("8");
break;
default:
MessageBox.Show("Enter new day");
break;
}
If you don't get the same results I would perhaps look at making the message boxes above display the data type of the variable.
MessageBox.Show(result.GetType().ToString());
I recently switched from VB to C#. One thing that I noticed was that in C#, I have problems using comparisons as part of the case. I am not sure how to explain it in words, so here is an example of what I am trying to do.
In VB, my code looks like this and works perfectly fine.
Select Case ExamScore
Case Is >= 90
Grade = "A"
Case Is >= 80
Grade = "B"
Case Is >= 70
Grade = "C"
Case Is >= 60
Grade = "D"
Case Else
Grade = "F"
End Select
In C# on the other hand, Visual Studio tells me that ">=" is an invalid expression.
switch (examScore)
{
case >= 90: grade = "A"; break;
case >= 80: grade = "B"; break;
case >= 70: grade = "C"; break;
case >= 60; grade = "D"; break;
default: grade = "F"; break;
}
Am I doing something wrong here, or is it simply not possible to do this in C#?
Thank you very much in advance!
Top part of this answer is true for C# versions before 7. See below the line for an update for version 7
It's not possible. C# switches can only switch on exact equality:
Each case label specifies a constant value. Control is transferred to the switch section whose case label contains a constant value that matches the value of the switch expression,
You could replace it with a stack of if/else statements, or if you prefer, you can make something that looks quite compact, but some may frown on - a nest of conditional operators:
grade = examScore >= 90 ? "A" :
examScore >= 80 ? "B" :
examScore >= 70 ? "C" :
examScore >= 60 ? "D" :
"F";
With C# 7, switch has been significantly enhanced, and it's now possible to apply more conditions within cases, although it's still not as "clean" as the VB version. E.g. you could do something like:
switch (examScore)
{
case int es when es >= 90: grade = "A"; break;
case int es when es >= 80: grade = "B"; break;
case int es when es >= 70: grade = "C"; break;
case int es when es >= 60; grade = "D"; break;
default: grade = "F"; break;
}
Assuming that examScore is an int, this somewhat abuses the new "pattern matching on types" facility to be able to have something to say in the case clause, and then using the when clauses to apply arbitrary conditions to the newly introduced variable.
Unlike in VB, the C# switch statement is something like "equals" check. So you might need a if else ladder in order to accomplish this.
You may try something like:
private char Grade(int marks)
{
Dictionary<int, char> grades = new Dictionary<int, char> { { 60, 'A' }, { 50, 'B' } };
foreach (var item in grades)
{
if (marks > item.Key)
return item.Value;
}
return 'C';
}
It's not possible in C#.
Use a bunch of ifs instead.
You can have it all in nice function:
public string Grade(int examScore)
{
if(examScore>=90)
{
return "A";
}
if(examScore>=80)
{
return "B";
}
if(examScore>=70)
{
return "C";
}
if(examScore>=60)
{
return "D";
}
return "F";
}
If you really want a switch statement you could use integer division
int i = 69;
switch (Math.Min(9, i / 10))
{
case 9: Grade = "A"; break;
case 6: Grade = "B"; break;
}
Full disclosure here, I am a student doing homework. I have 2 listboxes with items that can be selected. What is said in them is not needed to be extracted. I wrote the code out and everything works except I get an error saying "use of unassigned variable" on 3 variables at the end of the code. They are locFees, days, and registration. Can anyone tell me what I am doing wrong that is causing the variables to not have a value?
private void btnCalc_Click(object sender, EventArgs e)
{
double registration, lodging, total, days, locFees;
int workshopIndex, locationIndex;
if (lbWorkshop.SelectedIndex != -1)
{
workshopIndex = lbWorkshop.SelectedIndex;
switch (workshopIndex)
{
case 0:
days = 3;
registration = 1000;
break;
case 1:
days = 3;
registration = 800;
break;
case 2:
days = 3;
registration = 1500;
break;
case 3:
days = 5;
registration = 1300;
break;
case 4:
days = 1;
registration = 500;
break;
}
}
else
{
MessageBox.Show("You didn't select a workshop.");
}
if (lbLocation.SelectedIndex != -1)
{
locationIndex = lbLocation.SelectedIndex;
switch (locationIndex)
{
case 0:
locFees = 150;
break;
case 1:
locFees = 225;
break;
case 2:
locFees = 175;
break;
case 3:
locFees = 300;
break;
case 4:
locFees = 175;
break;
case 5:
locFees = 150;
break;
}
}
else
{
MessageBox.Show("You didn't select a city.");
}
lodging = locFees * days;
total = registration + lodging;
}
Can anyone tell me what I am doing wrong that is causing the variables to not have a value?
Sure - you're ignoring the possibility that workshopIndex isn't 0, 1, 2, 3 or 4.
If you believe that should never happen, just add:
default:
throw new InvalidOperationException("Invalid selected index " + workshopIndex);
Or if you just want to use some defaults, do something like:
default:
days = 1;
registration = 100;
break;
That's the first way you can end up with days and registration unassigned.
Next, there's the fact that you only go into the switch block at all if lbWorkshop.SelectedIndex != -1. Your else block is just:
else
{
MessageBox.Show("You didn't select a workshop.");
}
... so after that else block, you're going to continue. You probably want:
else
{
MessageBox.Show("You didn't select a workshop.");
return;
}
You've then got the same problem for locFees, in terms of both the switch statement and the else block.
One thing to learn from this: be grateful that the compiler spotted these for you. It's stopped you from running code which definitely had bugs in. That's always a good thing.