Catch exception and reset windows form C# - c#

I'm currently working on my first assignment using windows forms in visual studio and have been a little stuck.
I'm trying to test if a user input is numeric, and if the input is not numeric, a little message box pops up and alerts the user. (I've done this part). The issue I'm having is the and error continues to pop in visual studio
Is this a formatting issue? Should I reformat my code? As you can probably see I am new the C# (and programming).
My code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace wtgCalculator {
public partial class Form1 : Form {
const double maleratio = 0.536;
const double femaleratio = 0.492;
public Form1() {
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e) {
}
private void Form1_Load(object sender, EventArgs e) {
}
private void label1_Click(object sender, EventArgs e) {
}
private void textBox1_TextChanged_1(object sender, EventArgs e) {
}
private void WaistNumericCheck() {
double waist;
string inpwaist = heighttextbox.Text;
if (double.TryParse(inpwaist, out waist)) {
MessageBox.Show("Value must be numeric"); //this is where the problem is
}
}
private void HeightNumericCheck() {
//todo
}
private void button1_Click(object sender, EventArgs e) {
//record inputs to variables
WaistNumericCheck();
HeightNumericCheck();
double height = double.Parse(heighttextbox.Text);
double waist = double.Parse(waisttextbox.Text);
//check is inputs are within boundry
CheckDimensions(height, waist);
//test
// ShowResult(height, waist);
}
private void CheckLimits(double height, double waist) {
double result = CalculateRatio(height, waist);
if (Female.Checked) {
if (result < femaleratio) {
MessageBox.Show("Your risk of obesity related cardiovasular is low");
}
if (result > femaleratio) {
MessageBox.Show("Your risk of obesity related to cardiovascular is high");
}
}
if (Male.Checked) {
if (result < maleratio) {
MessageBox.Show("Your risk of obesity related cardiovasular is low");
}
if (result > maleratio) {
MessageBox.Show("Your risk of obesity related cardiovasular is High");
}
}
//testing
MessageBox.Show(result.ToString());
}
private void ShowResult(double height, double waist) {
//double result = CalculateRatio(height, waist);
//if (Female.Checked) {
// if (result < femaleratio) {
// MessageBox.Show("Your risk of obesity related cardiovasular is low");
// }
// if (result > femaleratio) {
// MessageBox.Show("Your risk of obesity related to cardiovascular is high");
// }
//}
//if (Male.Checked) {
//}
}
private static void CheckDimensions(double height, double waist) {
if (height <= 120) {
MessageBox.Show("Height must be greater than 120cm");
}
if (waist <= 60) {
MessageBox.Show("Waist must be greater than 60cm");
}
}
private void Gender_CheckedChanged(object sender, EventArgs e) {
button1.Enabled = true;
}
private static double CalculateRatio(double height, double waist) {
double finalratio = waist / height;
return finalratio;
}
}
}
Thanks again, and let me know if more information is required.

You're not really handling this correctly. .Parse() is supposed to throw an exception if the value cannot be converted. The whole point of .TryParse() is to avoid that. So, your methods need to be cleaned up and edited to actually accomplish something:
private bool WaistNumericCheck(out double waist)
{
bool canParse = double.TryParse(heighttextbox.Text, out waist);
if ( !canParse ) {
MessageBox.Show("Value must be numeric");
}
return canParse;
}
private bool HeightNumericCheck(out double height)
{
// todo -> same pattern as above
}
private void button1_Click(object sender, EventArgs e)
{
double height = 0, waist = 0;
if( WaistNumericCheck(waist) && HeightNumericCheck(height) )
{
CheckDimensions(height, waist);
/* ... the rest of your code */
}
}
This modifies your test methods to return a true/false based on whether the parse was successful, and outs your parsed variables so that you don't have to parse them again.
I suggest at some point that you review the MSDN documentation: http://msdn.microsoft.com/en-us/library/994c0zb1%28v=vs.110%29.aspx

Related

System.IndexOutOfRangeException: 'Index was outside the bounds of the array.' C#

I am currently working on a project where I connect an arduino uno to a windows form and display the temperature in it using serial communication.
However I got this weird error every time I compiled my app
System.IndexOutOfRangeException: 'Index was outside the bounds of the array.
I have declared my string array correctly. Can anyone help me to overcome this issue?
using System;
using System.Windows.Forms;
using System.Threading.Tasks;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
serialPort1.Open();
}
public String[] towTemp = new string[1];
public Task Tempdisplay()
{
//timer1.Start();
return Task.Factory.StartNew(() =>
{
try
{
String tempFromArduino = serialPort1.ReadLine().ToString();
towTemp = tempFromArduino.Split(',');
CheckForIllegalCrossThreadCalls = false;
if (float.TryParse(towTemp[0], out float result1))
{
result1 = (float)(Math.Round(Convert.ToDecimal(result1), 1));
label2.Text = result1.ToString();
aGauge1.Value = result1;
}
else
{
return;
}
if (float.TryParse(towTemp[1], out float result2))
{
result2 = (float)(Math.Round(Convert.ToDecimal(result2), 1));
label3.Text = result2.ToString();
aGauge2.Value = result2;
}
else
{
return;
}
}
catch (Exception err)
{
MessageBox.Show(err.ToString());
}
});
}
private async void timer1_Tick(object sender, EventArgs e)
{
timer1.Interval = 1000;
await Tempdisplay();
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
timer1.Stop();
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
}
}
With that line towTemp = tempFromArduino.Split(','); you overwrite the array that means it can have the length 0 now.
Check its length before you access it.

Trouble with random number guessing game in c#

So I am working on a project for school that in a guessing game for a randomly generated number between 1-100. The only trouble I am having at the moment is that every time the user enters a new number the generated number also changes. I tried putting the code to generate the number in the form loader but then I can't access it later in the program. Here's what I have so far.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void guessButton_Click(object sender, EventArgs e)
{
int userGuess;
userGuess = int.Parse(guessText.Text);
Random rand = new Random();
int number = rand.Next(1, 100);
label2.Text = "" + number;
if (userGuess > number)
{
resultLabel.Text = "Your guess is too high";
}
else if (userGuess < number)
{
resultLabel.Text = "Your guess is too low.";
}
else if (userGuess == number)
{
resultLabel.Text = "That is correct!";
}
guessText.Clear();
}
private void exitButton_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
As it currently stands, the Random number is overwritten every time the guessButton_Click function is run.
You are declaring Random inside the guessButton_Click function, that is called every time the guess button is clicked (that's also a memory leak!).
To fix, declare it as a global variable, in the namespace:
Edit: The below code compiles properly, and works perfectly.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
int number = new Random().Next(1, 100);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void guessButton_Click(object sender, EventArgs e)
{
int userGuess;
userGuess = int.Parse(guessText.Text);
label2.Text = "" + number;
if (userGuess > number)
{
resultLabel.Text = "Your guess is too high";
}
else if (userGuess < number)
{
resultLabel.Text = "Your guess is too low.";
}
else if (userGuess == number)
{
resultLabel.Text = "That is correct!";
}
guessText.Clear();
}
private void exitButton_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
You are getting a new random number every button click try the following:
public partial class Form1 : Form
{
Random rand;
int number;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
rand = new Random();
number = rand.Next(1, 100);
}
private void guessButton_Click(object sender, EventArgs e)
{
int userGuess;
userGuess = int.Parse(guessText.Text);
label2.Text = "" + number;
if (userGuess > number)
{
resultLabel.Text = "Your guess is too high";
}
else if (userGuess < number)
{
resultLabel.Text = "Your guess is too low.";
}
else if (userGuess == number)
{
resultLabel.Text = "That is correct!";
}
guessText.Clear();
}
}

Changing value in numericupdown in c# form

The problem is that the numericupdown doesn't change types of speed for fast and slow. Basically it would speed up whether the value is positive or negative and if I take it to back to zero it will crash. I am now trying to make an if loop inside of the numericupdown for TickCounter.
Here it is:
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Text = "AAAAAAA AAAAAAA #########";
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
TickCounterLabel.Text = "The timer has started";
tPeriodic.Enabled = true;
}
else
{
TickCounterLabel.Text = "The timer has ended";
tPeriodic.Enabled = false;
}
}
private void TickCounter_ValueChanged(object sender, EventArgs e)
{
**TickCounter.Value = TickCount;
if (TickCount >= 0)
tPeriodic.Interval = 1000 / Convert.ToInt32(TickCounter.Value * TickCounter.Value);
else if (TickCount <= 0)
tPeriodic.Interval = 1000 * Convert.ToInt32(TickCounter.Value * TickCounter.Value);
else if (TickCount == 0)
tPeriodic.Interval = Convert.ToInt32(TickCounter.Value * TickCounter.Value);**
}
private void tPeriodic_Tick(object sender, EventArgs e)
{
tickCount += 1;
lTickCount.Text = tickCount.ToString();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
public int tickCount { get; set; }
public int X { get; set; }
private void TickCounterLabel_Click(object sender, EventArgs e)
{
}
public int TickCount { get; set; }
}
}
Should I use another type of loop or am I just writing this wrong? When I try to change the value now it just crashes and the doesn't change at all.
Does anyone know how this can be accomplished? Also, should else if (TickCount == 0) be different if I don't want to have any change at all?
I guess it is because of divide by zero.
In the code of "TickCounter_ValueChanged", for TickCount=0, it just gets into the first "if" block and will cause the exception.
You need to use "if-else" conditions in a correct way.
private void TickCounter_ValueChanged(object sender, EventArgs e)
{
if (TickCounter.Value > 0)
tPeriodic.Interval = 1000 / Convert.ToInt32(TickCounter.Value * TickCounter.Value);
else if (TickCounter.Value < 0)
tPeriodic.Interval = 1000 * Convert.ToInt32(TickCounter.Value * TickCounter.Value);
else
tPeriodic.Interval = 1000;
}
Please let me know whether it solves your problem.

Why is a variable not recognized in an event handler?

I have two issues with this piece of code. I 'm having trouble because the submit button event doesn't recognize the variable calculated in the text box event, and because the text box event isn't recognizing my if statements as statements. You can see where I'm having trouble in the comments below.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication11
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
int points;
int userInput = int.Parse(textBox1.Text);
if (userInput == 0)
{
points == 5; //I CANNOT COMPILE BECAUSE APPARENTLY I AM NOT ALLOWED TO USE
THIS AS A STATEMENT?
}
if (userInput == 1)
{
points == 10;
}
if (userInput == 2)
{
points == 20;
}
if (userInput ==3)
{
points == 30;
}
else
{
points == 40;
}
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show = ("You have been awarded" + textBox1.points + "points");
} //I WANT TO BE ABLE TO RETRIEVE THE POINTS CALCULATED USING THE CALCULATION IN
TEXT BOX, BUT I CANNOT COMPILE THE BUTTON EVENT DOES NOT RECOGNIZE THE POINTS
VARIABLE
private void label1_Click(object sender, EventArgs e)
{
}
}
}
The == symbol is a comparison symbol not an assignment symbol
You need to use
if (userInput == 2) // this is a comparison
{
points = 20; // this is an assignment
}
First you have declared points local to the TextChanged event, so it won't be accessible in your button click event.
textBox1.points is not right since int points declaration has nothing to do with the TextBox, you may declare points as a class variable, something like
public partial class Form1 : Form
{
int points =0;
public Form1()
{
InitializeComponent();
}
//......//
this would then work out as
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show( string.Format("You have been awarded {0} points",this.points));
}
Also you do assignment using = sign, so points = 5; would be the right thing to do
To add value to variable you should write:
points = 5;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication11
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public int points=0;
private void Form1_Load(object sender, EventArgs e)
{
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
int userInput = int.Parse(textBox1.Text);
if (userInput == 0)
{
points = 5;
}
if (userInput == 1)
{
points = 10;
}
if (userInput == 2)
{
points = 20;
}
if (userInput ==3)
{
points = 30;
}
else
{
points = 40;
}
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show = ("You have been awarded" + points.ToString() + "points");
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}
As already stated - you confussed with assignment operator and with global/local variables.
But there is several other "errors" in your code. User input might be simple text - so there will be exception, you should use int.TryParse instead of int.Parse. Also there are plenty of ifs in your code - but they cannot fire all together, I recomend use switch. And of course you should try to name your constants somehow, it will make your code much more readable!
Overral your code might look like this:
int pointsAvarded = 0;
private void textBox1_TextChanged(object sender, EventArgs e)
{
pointsAvarded = 0; //so you can be sure to use the latest input
int userInput = 0;
if (int.TryParse(textBox1.Text, out userInput))
switch (userInput)
{
case 0:
points = 5;
break;
case 1:
points = 10;
break;
...
default:
points = 40;
break;
}
}
private void button1_Click(object sender, EventArgs e)
{
if (pointsAvarded != 0)
MessageBox.Show("You have been awarded" + pointsAvarded + "points");
}

c# scoping issue, simple fix i'm sure

So I have the following code, and It works nearly flawlessly, except for the fact that no matter what I do I cannot get the parts that are like: for (int.parse(txtGuess.Text) == numbGen) it will not recognize 'numbGen' no matter where I place it in the code. I cannot place it inside the button click function because I don't want the number to change, unless they've gotten it correct or re-opened the form.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class rndNum : Form
{
public rndNum()
{
}
private void rndNum_Load(object sender, EventArgs e)
{
int numbGen = RandMake(0, 100);
}
private void txtGuess_TextChanged(object sender, EventArgs e)
{
}
private void btnEval_Click(object sender, EventArgs e)
{
int guesses = 0;
while (txtGuess.Text != "")
{
if (int.Parse(txtGuess.Text) == numbGen)
{
MessageBox.Show("You got it!", "Congratulations!");
break;
}
else if (int.Parse(txtGuess.Text) > numbGen)
{
MessageBox.Show("Sorry, but you're too high. The number was " + numbGen + "!", "Please try again.");
txtGuess.Clear();
txtGuess.Focus();
guesses++;
break;
}
else if (int.Parse(txtGuess.Text) < numbGen)
{
MessageBox.Show("Sorry, but you're too low. The number was " + numbGen + "!", "Please try again.");
txtGuess.Clear();
txtGuess.Focus();
guesses++;
break;
}
}
}
private static int RandMake(int min, int max)
{
Random mkRnd = new Random();
return mkRnd.Next(min, max);
}
}
}
numbGen must be a class member.
Change
private void rndNum_Load(object sender, EventArgs e)
{
int numbGen = RandMake(0, 100);
}
to
private int numbGen;
private void rndNum_Load(object sender, EventArgs e)
{
numbGen = RandMake(0, 100);
}
actually you don't need to put the initialization in Form.Load, you can initialize a class member directly.
public partial class rndNum : Form
{
private int numbGen = RandMake(0, 100);
public rndNum()
{
}
and to further refine: if you want to make sure the values is not changed you can make it readonly
public partial class rndNum : Form
{
private readonly int numbGen = RandMake(0, 100);
public rndNum()
{
}
int numbGen;
private void rndNum_Load(object sender, EventArgs e)
{
numbGen = RandMake(0, 100);
}
try this!!!
The others already commented on the scoping issue you noticed. But your RandMake method is flawed too. You should not create an instance of Random for each number, but reuse the instance.
The problem here is that new Random() uses the time as seed, and the time only changes every few milliseconds. This means that if you call RandMake several times within that time interval you will get the same "random" number.
This doesn't seem to be a immediate problem because you only call it once, but you should be aware of this in the future.
When you put numbGen's declaration on the inside of a method, the number only exist in that functions scope. You have to place it outside like this:
int numbGen;
private void rndNum_Load(object sender, EventArgs e)
{
numbGen = RandMake(0, 100);
}

Categories