c# empty textboxs after click - c#

I have this problem where I run my code and it gives me empty text boxs and I'm not sure why. I have debug it and found that number = double.Parse(txtTableAvgTemp.Text); and poolCost = double.Parse(txtTableDollars.Text); are both returning NULL. The code is to work out the heating cost of the pool in question as per size.
const double poolLengthMin = 5; // min pool length
const double poolLengthMax =50; // max pool length
const double poolWidthMin = 2; // min pool width
const double poolWidthMax = 20; // max pool width
const double poolDepthMin = 2; // min pool depth
const double poolDepthMax = 4; // max pool depth
// variable used in btnCalculate_Click
float poolLength;
float poolWidth;
float poolDepth;
float SurfaceArea = 0;
float Volume = 0;
const int poolSize = 0;
const int smallPool = 500000 ;
const int mediumPool = 1500000;
const double poolTemp = 1.5;
double poolDegreesMin = 5;
double poolDegreesMax = 25;
double number;
double costToHeatPool;
double heatingVolume;
double poolDegrees = 5;
/* validation statements for pool
* length, width and depth
*/
bool ValidPoolLength(double poolLength)
{
if (poolLength >= poolLengthMin && poolLength <= poolLengthMax)
{
return true;
}
else
{
return false;
}
}
bool ValidPoolWidth(double poolWidth)
{
if (poolWidth >= poolWidthMin && poolWidth <= poolWidthMax)
{
return true;
}
else
{
return false;
}
}
bool ValidPoolDepth(double poolDepth)
{
if(poolDepth >= poolDepthMin && poolDepth <= poolDepthMax)
{
return true;
}
else
{
return false;
}
}
// end of validation statements
private void lblCategory_Click(object sender, EventArgs e)
{
}
private void btnCalculate_Click(object sender, EventArgs e)
{ // convert variable to float from double from string
poolLength = float.Parse(txtLength.Text);
poolWidth = float.Parse(txtWidth.Text);
poolDepth = float.Parse(txtAvgDepth.Text);
//clear string
txtVolume.Clear();
txtSurfaceArea.Clear();
txtTableDollars.Clear();
// error massages for pool length
//pool width and pool depth
if (!(ValidPoolLength(poolLength)))
{
MessageBox.Show("Length measurement is invalid \r\n Please enter a value between : " + poolLengthMin + " and " + poolLengthMax, "Pool Lenght Invalid" , MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
if (!(ValidPoolWidth(poolWidth)))
{
MessageBox.Show("Width measurment is invalid \r\n Please enter a value between : " + poolWidthMin + " and " + poolWidthMax, "Pool Width Invalid", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
if (!(ValidPoolDepth(poolDepth)))
{
MessageBox.Show("Pool Depth is invalid \r\n Please enter a value between : " + poolDepthMin + " and " + poolDepthMax, "Pool Depth Invalid", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
// caclulate surface area and show in txtSurfaceArea
SurfaceArea = poolLength * poolWidth;
txtSurfaceArea.Text += SurfaceArea;
//calculate pool volume and show in txtVolume
Volume = poolLength * poolWidth * poolDepth * 1000;
txtVolume.Text += Volume;
//calculate size of pool Small, Medium or large
//and show in lblcategory
Volume = float.Parse(txtVolume.Text);
if (poolSize <= smallPool && smallPool >= Volume)
{
lblCategory.Text = "Pool Category: Small";
}
else if (poolSize <= mediumPool && mediumPool >= Volume)
{
lblCategory.Text = "Pool Category: Medium";
}
else
{
lblCategory.Text = "Pool Category: Large";
}
//cost to heat the pool to 25 degrees
while (poolTemp >= poolDegrees && poolTemp < poolDegrees)
{
number = poolDegrees + poolTemp;
txtTableAvgTemp.Text += number.ToString() + "\r\n";
poolDegrees += poolTemp;
//variable for costing out heating of pool
double poolCost = costToHeatPool;
heatingVolume = float.Parse(txtVolume.Text);
costToHeatPool = float.Parse(txtVolume.Text);
poolCost = double.Parse(txtTableDollars.Text);//empty ?
number = double.Parse(txtTableAvgTemp.Text);//empty ?
poolCost = (Math.Truncate(poolCost));
//formula for costing of heating to pool
costToHeatPool = (25 - number) * heatingVolume / 32500;
txtTableDollars.Text += poolCost + "\r\n";
}
}
I have given you my whole code as I'm not sure where I have gone wrong. I did try poolDegreesMin and poolDegreesMax.

I just see some problems with the parsing itselve. You parse the text of txtTableAvgTemp.Text.
This text is extended for each while loop with a new line of temperature:
txtTableAvgTemp.Text += number.ToString() + "\r\n";
This will never parse.
Further on, on the first cycle the text is empty ("", which is not null). This will also throw a FormatException.
Initialize the text box first with a 0. And don't add new lines to a text box if you want to parse from them later. You should use temporary double fields to store the last values. Then there is no need for parsing the whole time.
// init with 0
txtTableDollars.Text = 0;
txtTableAvgTemp.Text = 0;
double currentCost = 0;
// do them outside, no need to do it on every loop
float heatingVolume = float.Parse(txtVolume.Text);
// working while
while (poolDegrees >= 3.5 && poolDegrees < 23)
{
poolDegrees += poolTemp;
double costToHeatPool = (25 - poolDegrees) * heatingVolume / 32500;
currentCost += costToHeatPool;
txtTableAvgTemp.Text += poolDegrees + System.Environment.NewLine;
txtTableDollars.Text += currentCost + System.Environment.NewLine;
}
Additional point: I do not know exactly, but this while loop here looks realy suspicious
while (poolTemp >= poolDegrees && poolTemp < poolDegrees) {/*...*/}
For me this looks like a while(false). Is this intended? this loop should never be executed...

Well, in the beginning of your code there is line of code:
txtTableDollars.Clear();
is clears textbox, so later when you're using that text, obviously it is empty:
poolCost = double.Parse(txtTableDollars.Text);
And later in the same loop - you're assigning it like
txtTableDollars.Text += poolCost + "\r\n";
so if your loop will be executed more than once - you will get some strange result (or exception) when parsing it again.
It looks like you should divide your computation from visualisation. Parse your input once and use numbers for computation, don't reparse text values again.

Related

Why does the average only output the sum and then add the same value for 8th input and when there is only 7 entries

I am just trying to output the average of a case entry form. The case entry form is suppose to take only 7 inputs and convert it to a double and output the average of all the inputs but my average is not working. I am not too sure. Every time I try to use sum += userInput; and then move onto the if statement which calculates the average, it only outputs either all the numbers added together or some arbitrary number. I have tried just using the number 7 instead of the MaxDays constant which is 7. I am suppose to output the average to the user in a label. I have asked colleagues and look at reddit, youtube videos, other questions related to this issue but it does not really pertain to my issue.
Here is the code.
private void Enter_Click(object sender, EventArgs e)
{
bool isValid;
isValid = ValidateInfections();
double userInput;
if (double.TryParse(textBoxCaseEntry.Text, out userInput))
{
using TryParse.
if (userInput >= 0 && userInput <= int.MaxValue)
{
listBoxCases.Items.Add(textBoxCaseEntry.Text);
labelDay.Text = "Day " + (listBoxCases.Items.Count + 1);
for (int p = 0; p <= MaxDays; p++)
{
sum += userInput;
if (listBoxCases.Items.Count == MaxDays)
{
double dailyAverage = sum / MaxDays ;
labelAverageDailyCases.Text = "The daily case average is " + dailyAverage.ToString();
textBoxCaseEntry.Enabled = false;
Enter.Enabled = false;
}
}
}
}
else
{
MessageBox.Show("Calculations can not be performed as one or more validations have failed");
SetDefaults();
}
}

Arduino Serial Communication from C# visual studio

Arduino code
void setup() {
Serial.begin(9600);
pinMode(GREEN_LED, OUTPUT);
pinMode(RED_LED, OUTPUT);
pinMode(BLUE_LED, OUTPUT);
Serial.write("x\n");
}
void loop() {
if(Serial.available() > 0){
if(first == true){ Serial.read(); first = false; }
if(Serial.peek() == 'r'){
analogWrite(RED_LED, (Serial.readString() + Serial.readString() + Serial.readString()).toInt());
}
else if(Serial.peek() == 'g'){
analogWrite(GREEN_LED, (Serial.readString() + Serial.readString() + Serial.readString()).toInt());
}
else if(Serial.peek() == 'b'){
analogWrite(BLUE_LED, (Serial.readString() + Serial.readString() + Serial.readString()).toInt());
Serial.write("x\n");
}
else{
error();
}
Serial.println(String(brightnessR) + "," + String(brightnessG) + "," + String(brightnessB) + "\n");
}
}
While simple there is an issue, probably due to my inability to understand the Serial methods. It begins with sending a test byte down the serial to tell the C# program on the computer that it can begin sending information. Next it checks if there are any bytes in the serial and if so it checks if the first byte matches any of the either r, g, or b and grabs the next three bytes from the serial and turns it into an integer.
On the visual studio side
string getRGB(Color rgb)
{
String rValue = "r";
if (type == 0)
{
if(rgb.R < 100)
{
rValue += "0";
}
if (rgb.R < 10)
{
rValue += "0";
}
type++;
return rValue + (rgb.R).ToString() + "\n";
}
String gValue = "g";
if (type == 1)
{
if (rgb.G < 100)
{
gValue += "0";
}
if (rgb.G < 10)
{
gValue += "0";
}
type++;
return gValue + (rgb.G).ToString() + "\n";
}
String bValue = "b";
if (type == 2)
{
if (rgb.B < 100)
{
bValue += "0";
}
if (rgb.B < 10)
{
bValue += "0";
}
type = 0;
return bValue + (rgb.B).ToString() + "\n";
}
return "";
}
public void SerializeRGB()
{
Color RGB = GetColorFromScreen(new Point(1160, 450));
if (LineOpen())
{
Updater(getRGB(RGB));
}
else
{
Values.Text = "Error\nError\nError";
}
}
public void Updater(String n)
{
Values.Text = n;
WriteSerial(n);
}
On visual studio if it detects that the arduino has requested data with the 'x' then it sends a string through the serial comprised of either r000 g000 b000 with the appropriate rgb values of the middle pixel on my screen.
The idea of this program is to translate screen colors onto a LED RGB strip hooked up to the Arduino. Currently the problem comes in that the program cannot identify whether there is an r,g or b at the beginning of the string and never gives a true for an if(){} statement and always end up on the else{}.
If anyone could help me solve this serial communication problem it would be very appreciated :)
Notes: Serial.readString() returns a string, Serial.read() returns the next byte in the serial.
I believe 10 is the char for a newline. Try filtering out for a new line/return. I would recommend set a string with a value of (String input = Serial.readString();), and using the first char from the string as you would be able to first filter the string of new lines/returns, which should give you the rgb chars.
String input = Serial.readString(); //gets string for serial port
input.trim(); //removes all whitespaces(\n\r, etc)
Char type = input.charAt(0); //gets first char

Unable to plot multiple lines in Fastline chart

I am trying to have a Fastline Chart (type chosen as I get lots of point to plot). I want to plot in the data I just got plus an average on the same chart. Should be easy but I keep getting an error "An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll".
The function is below, if I comment out the second series called [AverageTime"] I compile and work with one line.
Please note the function is async (.net 4.5) which I use for "await Task.Delay(Int32.Parse(txtbx_timing_delay.Text));". Not sure if this has anything to do with it as I presume I have a thread I am waiting for.
Any ideas on how to get round the issue?
private async void btn_timing_send_Click(object sender, EventArgs e)
{
int recursive_counter = 0, num = 0, num2 = 0;
double total_time = 0, average_time = 0, min_time = 0, max_time = 0, ave_plot = 0;
num2 = Int32.Parse(txtbx_iterations.Text); // number of required iterations
/*
* Just a word on timings - Windows is bad at doing timings in lower Microseconds and below so we need to do a few things to try and get
* accurate timings.
*
* As the general rule, when testing comms with completion time in the range of several microseconds it's recommended to implement
* the loop running 10,000...100,000 iterations in order to increase the accuracy of the measurement
*/
string str1 = "";
Stream stm = tcpclnt.GetStream();
byte[] payload;
string ID = txtbx_timing_send_data.Text;
str1 = "No Connection";
ID = ID.ToCharArray().Aggregate("", (result, c) => result += ((!string.IsNullOrEmpty(result) && (result.Length + 1) % 3 == 0) ? " " : "") + c.ToString());//add space every two chars to make hex
payload = ID.Split().Select(s => Convert.ToByte(s, 16)).ToArray(); //split the bytes into the array
if (ckbx_plot.Checked)
{
chrt_timings.Series["ResponseTimes"].ChartType = SeriesChartType.FastLine; //set type
chrt_timings.Series["ResponseTimes"].Color = Color.Blue; //set colour
chrt_timings.Series["AverageTime"].ChartType = SeriesChartType.FastLine; //set type
// chrt_timings.Series["AverageTime"].Color = Color.Red; //set colour
// chrt_timings.Series["AverageTime"].BorderDashStyle = ChartDashStyle.Dash;
chrt_timings.Legends.Clear(); // We do not need a legend
chrt_timings.ChartAreas[0].AxisX.IsMarginVisible = false;
}
do
{
try
{
Stopwatch timer = Stopwatch.StartNew();
long frequency = Stopwatch.Frequency;
long nanosecPerTick = (1000L * 1000L * 1000L) / frequency;
long startTick = timer.ElapsedTicks; //start of timed section
stm.Write(payload, 0, payload.Length);
byte[] input = new byte[tcpclnt.ReceiveBufferSize];
int k = stm.Read(input, 0, tcpclnt.ReceiveBufferSize);
Array.Resize(ref input, k); //crop the array to the amount of items it read in
str1 = string.Join(" ", input.Select(b => string.Format("{0:X2} ", b))); //format as hex bytes
long stopTick = timer.ElapsedTicks; //end of timed section
var timestamp = Convert.ToDouble((stopTick - startTick) * nanosecPerTick) / 1000000;
timer.Reset();
rchtxbox_timings.SelectionColor = Color.LimeGreen;
rchtxbox_timings.AppendText(str1 + "\r");
rchtxbox_timings.SelectionColor = Color.Yellow;
rchtxbox_timings.AppendText(timestamp + "ms\r\r");
rchtxbox_timings.ScrollToCaret();
if (num == 0) min_time = timestamp;
if (num2 > 1)
{
total_time = total_time + timestamp;
if (max_time < timestamp) max_time = timestamp;
if (min_time > timestamp) min_time = timestamp;
}
if (chkBx_LogData.Checked)
{
using (StreamWriter sw = new StreamWriter(timing_filename, true))
{
str1 = str1.Replace(" ", ""); //take out the spaces
sw.WriteLine(str1 + "," + timestamp.ToString() + "\r");
}
}
//Plot graph if required
if (ckbx_plot.Checked)
{
ave_plot = timestamp / num;
if (ckbx_restrict_graph.Checked)
{
if (chrt_timings.Series["ResponseTimes"].Points.Count() >= Convert.ToInt16(txtbx_axispoints.Text)) chrt_timings.Series["ResponseTimes"].Points.RemoveAt(0);
chrt_timings.Series["ResponseTimes"].Points.Add(timestamp);
chrt_timings.Series["ResponseTimes"].ToolTip = timestamp.ToString();
// if (chrt_timings.Series["AverageTime"].Points.Count() >= Convert.ToInt16(txtbx_axispoints.Text)) chrt_timings.Series["Average Time"].Points.RemoveAt(0);
// chrt_timings.Series["AverageTime"].Points.Add(ave_plot);
chrt_timings.ResetAutoValues();
}
else
{
recursive_counter++;
chrt_timings.Series["ResponseTimes"].Points.AddXY(recursive_counter, timestamp);
chrt_timings.Series["ResponseTimes"].ToolTip = timestamp.ToString();
// chrt_timings.Series["AverageTime"].Points.AddXY(ave_plot, timestamp);
}
}
num = num + 1;
timestamp = 0;
await Task.Delay(Int32.Parse(txtbx_timing_delay.Text));
}
catch (Exception d)
{
rchTxtBx_output.AppendText("red..... " + d.StackTrace);
}
} while (num2 > num);
if (num2 > 1)
{
//write out min, max and ave times
average_time = total_time / num;
rchtxbox_timings.SelectionColor = Color.LightBlue;
rchtxbox_timings.AppendText("\rMinimum Time = " + min_time + "\r");
rchtxbox_timings.SelectionColor = Color.LightBlue;
rchtxbox_timings.AppendText("Maximum Time = " + max_time + "\r");
rchtxbox_timings.SelectionColor = Color.LightBlue;
rchtxbox_timings.AppendText("Average Time = " + average_time + "\r\r");
rchtxbox_timings.ScrollToCaret();
}
}
Thanks for help, after much head scratching I solved the issue. I missed one small point and that was I did not have the second series, Series["AverageTime"], declared as a member of the charting canvas.
To fix this I went to the Properties then click on collection and Add the member, AverageTime. Once that was done I could draw its points to the Chart Canvas.
So now I initialise the lines below
if (ckbx_plot.Checked)
{
chrt_timings.Series["ResponseTimes"].ChartType = SeriesChartType.FastLine; //set type
chrt_timings.Series["ResponseTimes"].Color = Color.Blue; //set colour
chrt_timings.Series["AverageTime"].ChartType = SeriesChartType.FastLine; //set type
chrt_timings.Series["AverageTime"].Color = Color.Red; //set colour
chrt_timings.Series["AverageTime"].BorderDashStyle = ChartDashStyle.Dash;
chrt_timings.Legends.Clear(); // We do not need a legend
chrt_timings.ChartAreas[0].AxisX.IsMarginVisible = false;
}
and now I add the data
if (ckbx_restrict_graph.Checked)
{ //shows just set number of points, add a new point remove an old point
if (chrt_timings.Series["ResponseTimes"].Points.Count() >= Convert.ToInt16(txtbx_axispoints.Text)) chrt_timings.Series["ResponseTimes"].Points.RemoveAt(0);
chrt_timings.Series["ResponseTimes"].Points.Add(timestamp);
chrt_timings.Series["ResponseTimes"].ToolTip = timestamp.ToString();
if (chrt_timings.Series["AverageTime"].Points.Count() >= Convert.ToInt16(txtbx_axispoints.Text)) chrt_timings.Series["Average Time"].Points.RemoveAt(0);
chrt_timings.Series["AverageTime"].Points.Add(ave_plot);
chrt_timings.ResetAutoValues();
}
else
{ //squash all points onto the same canvas
recursive_counter++;
chrt_timings.Series["ResponseTimes"].Points.AddXY(recursive_counter, timestamp);
chrt_timings.Series["ResponseTimes"].ToolTip = timestamp.ToString();
chrt_timings.Series["AverageTime"].Points.AddXY(ave_plot, timestamp);
}

Why my "while loop" does not stop

I have some lines of code like this.
can anyone explain for me why "while loop" does not stop. it is keeping shows the result more than the balance.
static void Main(string[] args)
{
const double balance = 303.91;
const double phonePrice = 99.99;
double a = 0;
while (a < balance )
{
a = a + phonePrice;
}
Console.WriteLine(a);
Console.ReadLine();
}
It does exactly what you have written.
The loop ends when a is bigger than balance and then you print that a variable
If you expect to stop the loop BEFORE running out of money then you need to change the loop exit condition
static void Main(string[] args)
{
const double balance = 303.91;
const double phonePrice = 99.99;
double a = 0;
// You don't want to run out of money, so check if buying
// another phone will bankrupt your finances....
while ((a + phonePrice) < balance )
{
a = a + phonePrice;
}
Console.WriteLine(a); // a = 299,97
Console.ReadLine();
}
you are checking the value after add so it add first then check if a greater than balanceor not so one time extra phoneprice is added with a. Make your while loop
while ((a + phonePrice) < balance)
{
a = a + phonePrice;
}

Hourly Pay Calc

The Task:
Create a hourly pay calculator which is simple to use but effective.
private double amount4Hours = 4;
private double amount8Hours = 8;
private double amount10Hours = 10;
private void btnSubtotal_Click(object sender, EventArgs e)
{
double answer;
// 45 min break removal
double break45 = 0.75;
double outputValue = 0;
bool isNumber = true;
//true false statement for error checking
isNumber = double.TryParse(text4Hours.Text, out outputValue);
isNumber = double.TryParse(text8Hours.Text, out outputValue);
isNumber = double.TryParse(text10Hours.Text, out outputValue);
if (!isNumber)
{
//error checking for blank text boxes
MessageBox.Show("Enter a number from 0-9");
}
else
{
//calculates total amount of hours after breaks have been removed
amount4Hours = amount4Hours * double.Parse(text4Hours.Text);
amount8Hours = amount8Hours * double.Parse(text8Hours.Text) -
break45 * double.Parse(text8Hours.Text);
amount10Hours = amount10Hours * double.Parse(text10Hours.Text) -
break45 * double.Parse(text10Hours.Text);
// Adds all together to output final amount of hours
answer = amount4Hours + amount8Hours + amount10Hours;
labSubtotal.Text = answer.ToString();
}
}
private void btnPay_Click(object sender, EventArgs e)
{
// Hourly pay stored here
double hourpay = 6.19;
hourpay = hourpay * double.Parse(labSubtotal.Text);
labPay.Text = hourpay.ToString();
}
private void btnClear_Click(object sender, EventArgs e)
{
// Resets all text boxes back to blank
text4Hours.Text = string.Empty;
text8Hours.Text = string.Empty;
text10Hours.Text = string.Empty;
labSubtotal.Text = string.Empty;
labPay.Text = string.Empty;
}
}
}
The Problem...
When I type in three different numbers in each text box, I get the outcome just perfect.
If I hit the clear button, it does what I ask and removes everything from the output
If I enter three numbers again (same ones or different ones) after it has been cleared, I will get different output.
I think it has something to do with the clear code because it's not resetting the values to zero like it does at the start of the program. I have tried setting the clear code to input zeros, but that doesn't help; just gives the same problem.
This is a good case to show how to use the debugger. Put a breakpoint on the line:
amount4Hours = amount4Hours * double.Parse(text4Hours.Text);
Then when you calculate the answer, watch how the amount4Hours variable changes.
This type of bug shows why people avoid the use of global variables.
private double amount4Hours = 4;
private double amount8Hours = 8;
private double amount10Hours = 10;
This code should go into your btnSubtotal_Click.
amount4Hours = 4;
amount8Hours = 8;
amount10Hours = 10;
Put this code in clear button. You also need to reset your global variables.
As others have said, on a general point you need to use the debugger for figuring out why something hasn't worked as you expected. In this case you are creating 3 global variables at the beginning (amount4hours etc.) and then manipulating them later on when clicking btnSubmit. At no point when btnClear do you reset your global values. Try adding in your btnClear_Click method:
amount4hours = 4;
amount8hours = 8;
amount10hours = 10;
This will reset your global variables.
If the global variables value should not be updated,why not directly get the value of answer by having their sum value directly
/*amount4Hours = amount4Hours * double.Parse(text4Hours.Text);
*
* amount8Hours = amount8Hours * double.Parse(text8Hours.Text) -
* break45 * double.Parse(text8Hours.Text);
*
* amount10Hours = amount10Hours * double.Parse(text10Hours.Text) -
* break45 * double.Parse(text10Hours.Text);
*
* answer = amount4Hours + amount8Hours + amount10Hours;*/
answer = amount4Hours * double.Parse(text4Hours.Text) +
amount8Hours * double.Parse(text8Hours.Text) -
break45 * double.Parse(text8Hours.Text) +
amount10Hours * double.Parse(text10Hours.Text) -
break45 * double.Parse(text10Hours.Text);
By the way, your error checking is fail because you stored all checking result in same variable therefore only the third textbox content is checked based on your logic. I assume you display the MessageBox whenever one of three textbox have invalid input. Then,
//bool isNumber = true;
//true false statement for error checking
//isNumber = double.TryParse(text4Hours.Text, out outputValue);
//isNumber = double.TryParse(text4Hours.Text, out outputValue);;
//isNumber = double.TryParse(text10Hours.Text, out outputValue);
//if (!isNumber)
if (!double.TryParse(text4Hours.Text, out outputValue)||
!double.TryParse(text8Hours.Text, out outputValue)||
!double.TryParse(text10Hours.Text, out outputValue))
{
//error checking for blank text boxes
//the checking only check if they are double type
//but not checking the range from 0 to 9
MessageBox.Show("Enter a number from 0-9");
}

Categories

Resources