Logical error in display/math not displaying initial result - c#

I have a population estimator program for school, the results do not display the first set of results. Here is the code.
private void Button1_Click(object sender, EventArgs e)
{
double startingPop;
double increasePer;
double numDays;
const int INTERVAL = 1;
if (double.TryParse(textBox1.Text, out startingPop))
{
if (double.TryParse(textBox2.Text, out increasePer))
{
if (double.TryParse(textBox3.Text, out numDays))
{
for (int i = 1; i <= numDays; i += INTERVAL)
{
startingPop = (startingPop * (increasePer / 100) + startingPop);
Results.Items.Add("After " + i + " days, the amount of organisms is " + startingPop);
}
}
}
}
}
private void Button2_Click(object sender, EventArgs e)
{
this.Close();
}
private void Button3_Click(object sender, EventArgs e)
{
textBox1.Text = "";
textBox2.Text = "";
textBox3.Text = "";
Results.Items.Clear();
}
I want it to show day 1 2 organisms, instead it shows the first calculation with the increase percentage i.e (day 1 2.6). I know this is probably super obvious so I apologize. Thanks for your insight.

If I understand your problem correctly, your code should look something like this:
private void button1_Click(object sender, EventArgs e)
{
double startingPop;
double increasePer;
double numDays;
const int INTERVAL = 1;
if (double.TryParse(textBox1.Text, out startingPop) &&
double.TryParse(textBox2.Text, out increasePer) &&
double.TryParse(textBox3.Text, out numDays))
{
Results.Items.Add("On the first day, the amount of organisms is " + startingPop);
for (int i = 1; i <= numDays; i += INTERVAL)
{
startingPop = (startingPop * (increasePer / 100) + startingPop);
Results.Items.Add("After " + i + " day(s), the amount of organisms is " + startingPop);
}
}
}
The changes I made to the code:
Combine the three if statements into one using the && operator.
Print the population value before increasing it so that the next displayed value (which reads "after 1 day") will be the next incremented value.
To make your result items grammatically correct, you may the second line inside the loop with something like:
string s = (i > 1 ? "s" : string.Empty);
Results.Items.Add($"After {i} day{s}, the amount of organisms is {startingPop}.");
Now, assuming the values in textBox1, textBox2, textBox3 are 2, 30, and 5, the displayed result would be something like this:

Related

Return input to adjacent output label after loop to calculate values

I am getting the correct results but I would like to be specific with the calculated values displayed for each label that is adjacent to each input.
Currently using two line breaks & it seems to line up with inputs by luck.
Program calculates book cost based on the number of pages printed:
1 - 500 pages 2 cents per page
500 - 100 pages 1.5 cents per page
1000+ pages 1 cent per page
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnPriceResults_Click(object sender, EventArgs e)
{
//VARIABLES
double[] arrPrintPageNums = new double[3];
double total = 0;
//INPUTS
arrPrintPageNums[0] = double.Parse(txtInputBook1.Text);
arrPrintPageNums[1] = double.Parse(txtInputBook2.Text);
arrPrintPageNums[2] = double.Parse(txtInputBook3.Text);
//PROCESS (i = INDEX NUMBER(0 1 2 3 4))
for (int i = 0; i < arrPrintPageNums.Length; i++)
{
if (arrPrintPageNums[i] > 0 && arrPrintPageNums[i] <= 500)
{
lblBook1Price.Text += "Print Cost: " + (arrPrintPageNums[i] * 2) + "\n\n";
total += arrPrintPageNums[i] * 0.02;
}
else if (arrPrintPageNums[i] > 500 && arrPrintPageNums[i] <= 1000)
{
lblBook1Price.Text += "Print Cost: " + (arrPrintPageNums[i] * 1.5) + "\n\n";
total += arrPrintPageNums[i] * 0.015;
}
else if (arrPrintPageNums[i] > 1000)
{
lblBook1Price.Text += "Print Cost: " + (arrPrintPageNums[i] * 1) + "\n\n";
total += arrPrintPageNums[i] * 0.01;
}
else
{
lblBook1Price.Text += "ERROR! OUTSIDE PRINT RANGE" + "\n\n";
}
}
//OUTPUT
lblBookPriceTotal.Text = "Total price: " + total.ToString("C2");
}
}
Desired result:
Book 1 Pages Input - Book 1 Total Print Cost Label
Book 2 Pages Input - Book 2 Total Print Cost Label
Book 3 Pages Input - Book 3 Total Print Cost Label
Button 'Book Print Cost' - Grand Total Print Cost Label
Use an array of labels that match your labels to the right of the inputs:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
bookPriceLabels = new Label[] { lblBook1Price, lblBook2Price, lblBook3Price };
}
private Label[] bookPriceLabels;
private void btnPriceResults_Click(object sender, EventArgs e)
{
//VARIABLES
double[] arrPrintPageNums = new double[3];
double total = 0;
//INPUTS
arrPrintPageNums[0] = double.Parse(txtInputBook1.Text);
arrPrintPageNums[1] = double.Parse(txtInputBook2.Text);
arrPrintPageNums[2] = double.Parse(txtInputBook3.Text);
Label[] labels = new Label
//PROCESS (i = INDEX NUMBER(0 1 2 3 4))
for (int i = 0; i < arrPrintPageNums.Length; i++)
{
if (arrPrintPageNums[i] > 0 && arrPrintPageNums[i] <= 500)
{
bookPriceLabels[i].Text = "Print Cost: " + (arrPrintPageNums[i] * 2);
total += arrPrintPageNums[i] * 0.02;
}
else if (arrPrintPageNums[i] > 500 && arrPrintPageNums[i] <= 1000)
{
bookPriceLabels[i].Text = "Print Cost: " + (arrPrintPageNums[i] * 1.5);
total += arrPrintPageNums[i] * 0.015;
}
else if (arrPrintPageNums[i] > 1000)
{
bookPriceLabels[i].Text = "Print Cost: " + (arrPrintPageNums[i] * 1);
total += arrPrintPageNums[i] * 0.01;
}
else
{
bookPriceLabels[i].Text = "ERROR! OUTSIDE PRINT RANGE" + "\n\n";
}
}
//OUTPUT
lblBookPriceTotal.Text = "Total price: " + total.ToString("C2");
}
}
I was quite confused by the picture you supplied and the code that is posted. From the first picture it “Appears” you are using three (3) labels to the right of each text box. However the supplied code only uses one label i.e... lblBook1Price. This is confusing to use this label for book 1 for all the books. You are correct is certainly blind luck that they line up properly. Remove one of “\n”’s in the line: lblBook1Price.Text += "Print Cost: " + (arrPrintPageNums[i] * 1) + "\n\n"; and it won’t line up properly.
Again this seems odd and not very intuitive to others who are reading your code. One solution would be to simply use 3 different labels as the first picture shows, one for each text box. At least you are not using the book 1 label to output the book 3 costs. I hope this makes sense.
The other problem I see is user sanitation, your code wil crash if the user types in letters and not numbers. I hooked up two events to handle this. KeyPressed event to allow only numeric input and the TextChanged event if the user copy and pastes invalid text. Hope this helps.
private void button1_Click(object sender, EventArgs e) {
updateForm();
}
private void updateForm() {
double total = 0;
//INPUTS
double curCost = 0;
curCost = GetBookCost(txtInputBook1, 0.02);
lblBook1Price.Text = curCost.ToString("C2");
total += curCost;
curCost = GetBookCost(txtInputBook2, 0.015);
lblBook2Price.Text = curCost.ToString("C2");
total += curCost;
curCost = GetBookCost(txtInputBook3, 0.01);
lblBook3Price.Text = curCost.ToString("C2");
total += curCost;
//OUTPUT
lblBookPriceTotal.Text = "Total price: " + total.ToString("C2");
}
private double GetBookCost(TextBox pagesText, double pricePerPage) {
double totPages = 0;
double.TryParse(pagesText.Text, out totPages);
double cost = totPages * pricePerPage;
return cost;
}
private void txtInputBook1_KeyPress(object sender, KeyPressEventArgs e) {
KeyPressManager(sender, e);
}
private void txtInputBook2_KeyPress(object sender, KeyPressEventArgs e) {
KeyPressManager(sender, e);
}
private void txtInputBook3_KeyPress(object sender, KeyPressEventArgs e) {
KeyPressManager(sender, e);
}
private void KeyPressManager(object sender, KeyPressEventArgs e) {
char keyPressed = e.KeyChar;
if ((!char.IsDigit(keyPressed)) && (!char.IsControl(e.KeyChar))) {
e.Handled = true;
}
}
private void txtInputBook1_TextChanged(object sender, EventArgs e) {
TextChangedManager(sender, e);
}
private void txtInputBook2_TextChanged(object sender, EventArgs e) {
TextChangedManager(sender, e);
}
private void txtInputBook3_TextChanged(object sender, EventArgs e) {
TextChangedManager(sender, e);
}
private void TextChangedManager(object sender, EventArgs e) {
TextBox tb = (TextBox)sender;
int userInput = 0;
if (int.TryParse(tb.Text, out userInput)) {
updateForm();
} else {
if (tb.Text != "") {
MessageBox.Show("Invalid input for number of pages!");
txtInputBook1.Text = "";
}
}
}

Fill a textbox based on another textbox text

I have TextBoxA and TextBoxB. What i want to do is , whenever i put a number (yes, both of the textboxes values are always integers) in TextBoxA , TextBoxB should "autocomplete" with value (100-TextBoxA). Same thing goes for TextBoxB. The sum of TextBoxA and TextBoxB should always be 100.
Here's what i've already tried:
static void TextBoxA_TextChanged()...
{
int a = Convert.ToInt32(TextBoxA.Text);
int b = Convert.ToInt32(TextBoxB.Text);
string text = (100-a).ToString();
TextBoxB.Text = text;
}
Static void TextBoxB_TextChanged()...
{
int a = Convert.ToInt32(TextBoxA.Text);
int b = Convert.ToInt32(TextBoxB.Text);
string text = (100-b).ToString();
TextBoxA.Text = text;
}
But it doesn't work.
Here's what you can try:
private void TextBoxA_TextChanged(object sender, EventArgs e)
{
int num = 0;
if (int.TryParse(TextBoxA.Text, out num))
{
string text = (100 - num).ToString();
TextBoxB.Text = text;
}
}
private void TextBoxB_TextChanged(object sender, EventArgs e)
{
int num = 0;
if (int.TryParse(TextBoxB.Text, out num))
{
string text = (100 - num).ToString();
TextBoxA.Text = text;
}
}
This will autocomplete on either TextBox on TextChanged Event.
First, i dont know why your event handlers are declared static.. its usually got to be :
private void TextBoxA_TextChanged(object sender, EventArgs e) { }
Secondly, you know if you have 2 textboxs, and each one triggers the other, you'll never go out of the TextChanged event.
To understand me more, here's an example :
1- You set TextBoxB.text = "1";2- TextBoxB.TextChanged triggers, it
sets TextBoxA.Text = "2"; 3- TextBoxA.TextChanged triggers, it sets
TextBoxB.Text = "1";
And it continues like this until i believe you'll get an Exception of memory.
EDIT : The opertator '-' works on numbers. You can't substract a number from a string. they have to be both numbers, so convert them first.
EDIT 2 :
Here's a code i wrote that works fine
private void textBox1_TextChanged(object sender, EventArgs e)
{
int n;
if (int.TryParse(textBox1.Text, out n)) // Check if the text value is a number
{
if (n > 100) // Since you want a sum of 100
return;
int m = 100 - n; // remaining
if (textBox2.Text != m.ToString()) // to not re-trigger the TextChanged event
textBox2.Text = m.ToString();
}
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
int n;
if (int.TryParse(textBox2.Text, out n)) // Check if the text value is a number
{
if (n > 100) // Since you want a sum of 100
return;
int m = 100 - n; // remaining
if (textBox1.Text != m.ToString()) // to not re-trigger the TextChanged event
textBox1.Text = m.ToString();
}
}
Try this. This is a more efficient and elegant way I'd choose using lambda expressions, without repeating the method:
private void onChangeDoSum(object sender, EventArgs e,
TextBox substractNumber, TextBox sumNumber)
{
sumNumber.Text = (100 - Int32.Parse(substractNumber.Text)).ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.TextChanged += (a, b) => onChangeDoSum(sender, e, textBox1, textBox2);
textBox2.TextChanged += (a, b) => onChangeDoSum(sender, e, textBox2, textBox1);
}
Alternatively use Int32.TryParse to prevent unexpected results.
I think you can do something like this
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox2.Text = (100 - Int32.Parse(textBox1.Text)).ToString();
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
textBox1.Text = (100 - Int32.Parse(textBox2.Text)).ToString();
}
when I see that static word I think you have tried to create these method by yourself and you forgot to add
textBox1.TextChanged += textBox1_Changed;
// I saw other post where you wrote that it could raise exception and fall. Of course it can. You can use if condition like
textBox1.Text != null && textBox1.Text != ""
before value would be changed or TryParse() method

Need help appending a variable in listbox

When the Add button is pressed the price is taken from the second half of a 'split' line in the first list box. This is then multiplied by a value entered in a textbox or just entered as is into the second listbox.
I have then added a line below it in the second list box with the total price. When a new item is added the code removes the previous total price and replaces it with the new updated total price.
I'm looking to then append (add all the prices being listed in the second listbox) the prices together in the 'total price' section of the last line of the second list box.
Below is the code I have written so far.
private void button1_Click(object sender, EventArgs e)
{
string TheItem = Convert.ToString(listBox1.SelectedItem);
string[] theSplits = TheItem.Split(' ');
string FirstSplit = theSplits[0];
string SecondSplit = theSplits[1];
Decimal theNewTotal;
Decimal theValue;
if (textBox1.Text == "")
{
listBox2.Items.Add(TheItem);
listBox2.Items.Add("Total Price:" + SecondSplit);
}
else
{
theValue = Convert.ToDecimal(SecondSplit) * Convert.ToDecimal(textBox1.Text);
listBox2.Items.Add(textBox1.Text + "x " + TheItem);
theNewTotal = theValue;
listBox2.Items.Add("Total Price:" + theNewTotal);
}
if (listBox2.Items.Count > 2)
{
int theNumber = listBox2.Items.Count;
listBox2.Items.RemoveAt(theNumber-3);
}
}
You'd be better off starting by removing the total price first, as you expend some effort trying to work around that. So something like:
private void button1_Click(object sender, EventArgs e) {
RemoveLastTotal();
AppendPrices();
AppendTotal();
}
private void RemoveLastTotal() {
var lastItemIndex = listBox2.Items.Count-1;
if (listBox2.Items[lastItemIndex].StartsWith("Total Price:"))
{
listBox2.Items.RemoveAt(lastItemIndex);
}
}
private void AppendPrices() {
string TheItem = Convert.ToString(listBox1.SelectedItem);
string[] theSplits = TheItem.Split(' ');
string itemDesc = theSplits[0];
string itemPrice = theSplits[1];
float quantity = (string.IsNullOrEmpty(textBox1.Text))? 0: float.Parse(textBox1.Text)
if (quantity==0) {
listBox2.Items.Add(TheItem);
} else {
var lineTotal = Convert.ToDecimal(itemPrice) * quantity;
listBox2.Items.Add(textBox1.Text + " x " + TheItem + " = " + lineTotal);
}
}
private void AppendTotal()
{
var total = 0;
foreach(var item in listBox2.Items)
{
var splits = item.Split(' ');
total += decimal.parse(splits[splits.length-1]);
}
listBox2.Items.Add("Total Price:" + total);
}
That said, if you really want to do it "properly", you should separate the view i.e. the listbox from the model (DataTable for instance).

How to get array data from one Click Method to another one

Don't think i could be any newer to coding, so please forgive me for whats about to be asked.
Im currently writing a program that lets the user enter a desired amount of random numbers to be generated by Random via textBox (lets say 15 --> you get 15 random numbers), ranging from 1 to 1000.
When hitting the Button A, those randomized Numbers will be saved in Zahlenarray[](-->with the length of the number entered in the textbox) and displayed in label1.Text.
Then there's a Button B, that, when clicked, should sort the Numbers from Zahlenarray[] via bubblesort and display them in label2.
My problem is now that the second Method (Button B_Click) doesnt have the contents of Zahlenarray from the Button A_Click Method.
Id like to pass this data by ref via the arguments, but fiddling with public void (Object sender, EventArgs e) seems to get me in major trouble.
Can i add arguments after EventArgs e, ... or am i missing another way of getting data out f this "scope" (hope thats the right word)?
Both Methods are in the same class.
part of the code of Button A:
public void Button_Anzeigen_Click(Object sender, EventArgs e)
{
label1.Text = "";
int[] Zahlenarray = new int[Int32.Parse(textBox1.Text)];
Everything from Button B:
private void Button_Sortieren_Click(object sender, EventArgs e)
{
label2.Text = "";
label3.Text = "";
int Speicher;
for (int n = Zahlenarray.Length; n > 0; n--)
{
for (int i = 0; i < n-1; i++)
{
if (Zahlenarray[i] > Zahlenarray[i + 1])
{
Speicher = Zahlenarray[i];
Zahlenarray[i] = Zahlenarray[i + 1];
Zahlenarray[i + 1] = Speicher;
Speicher = 0;
}
}
}
foreach (int i in Zahlenarray)
{
label2.Text += i + " ";
if ((i % 9 == 0) && !(i == 0))
label2.Text += "\n";
}
}
Put your array declaration outside of your buttona click handler so you can reference it inside your button b handler.
int[] Zahlenarray;
public void Button_Anzeigen_Click(Object sender, EventArgs e)
{
label1.Text = "";
Zahlenarray = new int[Int32.Parse(textBox1.Text)];
...
}

random numbers and multiple buttons c#

I'm confused on how to get this program to do a few certain things and a question for future reference for myself:
Question:
Can you do if statements with buttons
example: if (button1 is clicked)
do this
else if (button2 is clicked)
do this
The goal of my program is to help learn basic integer mathematics and the four sections are ADDING, SUBTRACTING, MULTIPLYING, and MOD.
I have four buttons for each one of those topics, and a fifth button to submit the answer for the question, I have 3 text boxes, the first being the question that is presented, second being the users answer, third being whether the answer was correct or not
What I currently have set up:
private void button1_Click(object sender, EventArgs e)
{
Random random1 = new Random();
int randomNumber1 = random1.Next(6, 11);
Random random2 = new Random();
int randomNumber2 = random2.Next(1, 6);
textBox1.Text = "What is " + randomNumber1 + " + " + randomNumber2 + " ?";
}
private void button2_Click(object sender, EventArgs e)
{
Random random1 = new Random();
int randomNumber1 = random1.Next(6, 11);
Random random2 = new Random();
int randomNumber2 = random2.Next(1, 6);
textBox1.Text = "What is " + randomNumber1 + " - " + randomNumber2 + " ?";
}
private void button3_Click(object sender, EventArgs e)
{
Random random1 = new Random();
int randomNumber1 = random1.Next(6, 11);
Random random2 = new Random();
int randomNumber2 = random2.Next(1, 6);
textBox1.Text = "What is " + randomNumber1 + " * " + randomNumber2 + " ?";
}
private void button4_Click(object sender, EventArgs e)
{
Random random1 = new Random();
int randomNumber1 = random1.Next(6, 11);
Random random2 = new Random();
int randomNumber2 = random2.Next(1, 6);
textBox1.Text = "What is " + randomNumber1 + " % " + randomNumber2 + " ?";
}
private void button5_Click(object sender, EventArgs e)
{
Random random1 = new Random();
int randomNumber1 = random1.Next(6, 11);
Random random2 = new Random();
int randomNumber2 = random2.Next(1, 6);
if (Convert.ToInt16(textBox2.Text) == (randomNumber1) + (randomNumber2))
textBox3.Text = "Correct!";
else if (Convert.ToInt16(textBox2.Text) == (randomNumber1) - (randomNumber2))
textBox3.Text = "Correct!";
else if (Convert.ToInt16(textBox2.Text) == (randomNumber1) * (randomNumber2))
textBox3.Text = "Correct!";
else if (Convert.ToInt16(textBox2.Text) == (randomNumber1) % (randomNumber2))
textBox3.Text = "Correct!";
else
textBox3.Text = "Incorrect!";
}
}
}
and what I'm looking to do is if button 1 is clicked you add, button 2 you subtract, button 3 you multiply, button 4 you mod and then depending on which one was clicked you click submit and it'll tell you whether you got the right answer or not. What I currently have somewhat does that but if the answer is any of the four types of questions answers it'll show it as correct.
ie: the question is 8 + 3 and you put 5, it'll say correct because 8 - 3 is 5
You can try the following code instead, you code has fairly many things redundant and the checking mechanism to determine if user answers correctly is totally wrong:
public enum Operation {
Add,
Subtract,
Divide,
Multiply,
Modulo
}
Random rand = new Random();
private decimal GenerateQuestion(Operation o){
int a = rand.Next(6, 11);
int b = rand.Next(1, 6);
decimal result = 0;
string os = "";
switch(o){
case Operation.Add:
result = a + b;
os = "+";
break;
case Operation.Subtract:
result = a - b;
os = "-";
break;
case Operation.Multiply:
result = a * b;
os = "*";
break;
case Operation.Divide:
result = (decimal)a/b;
os = "/";
break;
case Operation.Modulo:
result = a % b;
os = "%";
break;
}
textBox1.Text = string.Format("What is {0} {1} {2}?", a,os,b);
return result;
}
decimal result;
private void button1_Click(object sender, EventArgs e)
{
result = GenerateQuestion(Operation.Add);
}
private void button2_Click(object sender, EventArgs e){
result = GenerateQuestion(Operation.Subtract);
}
private void button3_Click(object sender, EventArgs e){
result = GenerateQuestion(Operation.Multiply);
}
private void button4_Click(object sender, EventArgs e){
result = GenerateQuestion(Operation.Modulo);
}
private void button5_Click(object sender, EventArgs e){
decimal v;
if(decimal.TryParse(textBox2.Text, out v)){
textBox3.Text = (v == result) ? "Correct!" : "Incorrect!";
}else {
textBox3.Clear();
MessageBox.Show("Enter a number please!");
}
}
You can assign one event handler to multiple buttons, and then check the EventArgs to tell which button fired the event, and put appropriate conditional logic in there.
Not sure if this is ASP.NET or WinForms, but it works something along the lines of:
btn1.Click += button_Click;
btn2.Click += button_Click;
btn3.Click += button_Click;
private void button_Click(object sender, EventArgs e)
{
var btn = sender as Button;
if (sender != null) {
if (btn is btn1) {
//do something
}
else if (btn is btn2) {
//do something
}
//etc
}
}
I have added the event handlers declaratively but you could do this through the properties dialog or in the markup.
I am assuming you are doing a Windows Application here (not Web). In that case, why don't you simply have a class level variable to store the last operation (subtract, add etc), and include check of that variable in the if condition.
eg:
public enum Operations
{
Add,
Subtract
}
private void button1_Click(object sender, EventArgs e)
{
Random random1 = new Random();
int randomNumber1 = random1.Next(6, 11);
Random random2 = new Random();
int randomNumber2 = random2.Next(1, 6);
var currentOperation = Operations.Add
textBox1.Text = "What is " + randomNumber1 + " + " + randomNumber2 + " ?";
}
if (Convert.ToInt16(textBox2.Text) == (randomNumber1) + (randomNumber2) && currentOperation == Operations.Add)
textBox3.Text = "Correct!";
You are generating random (*) numbers to create question and again to validate it. It makes absolutely no sense since you have something like "What is 3 + 4" and you comparing result to 7 + 2 or some other random value.
You should save generated values and operation for verification in some member variable, or even easier simply save expected result.
Random random = new Random();
int expectedResult;
private void button3_Click(object sender, EventArgs e)
{
int randomNumber1 = random.Next(6, 11);
int randomNumber2 = random.Next(1, 6);
textBox1.Text = "What is " + randomNumber1 + " * " + randomNumber2 + " ?";
expectedResult = randomNumber1 * randomNumber2;
}
private void button5_Click(object sender, EventArgs e)
{
textBox3.Text =
int.Parse(textBox2.Text) == expectedResult ? "Correct!" : "Incorrect!";
}
(*) Note that your current "random" numbers are not exactly random due to your code restarting sequence on each call - so pairs of numbers would be very closely related. Note that numbers generated for expression will likely be different from numbers generated for the check. Proper usage is to have one single Random object (potentially one-per-thread, but you don't need to worry about it for your case).

Categories

Resources