This question already has answers here:
Input string was not in a correct format in double.Parse
(5 answers)
Closed 4 years ago.
I'm trying to figure out why when I run my program and press the submit button I get an error saying that my list is in the wrong format. A little background on the program: It's for my visual programming class. The program is for a bank account. I tried to comment on what each section is to make it kinda easier to read
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Tab 1 Create and close account
private void Submitbtn_Click(object sender, EventArgs e)
{
double x;
if (OpenRdo.Checked == true && Nametxtbx.TextLength > 0)
{
double.TryParse(Nametxtbx.Text, out x);
// after clicking the button there is
// no number; it says system.random
Random acct = new Random();
int AccountNumber = acct.Next(5, 1000);
outputlbl.Text = acct.ToString();
}
// list for accounts
// This is where it says I have the error
// that my list is in the wrong format
var accounts = new List<Account>
{
new Account(Nametxtbx.Text, double.Parse(outputlbl.Text), 0)
};
// Write these records to a file
WriteFile(accounts);
// message box when you create account
if (ValidateChildren(ValidationConstraints.Enabled))
{
MessageBox.Show("Account Created", "Message",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
//writing to the file
static void WriteFile(List<Account> accts)
{
StreamWriter outputFile = File.CreateText("accounts.txt");
string record;
foreach (var acct in accts)
{
record = $"{acct.Name},{acct.Balance}";
Console.WriteLine($"Writing record: {record}");
outputFile.WriteLine(record);
}
outputFile.Close();
}
}
As far as I can tell (this is rather a lot of code), the issues are those lines:
Random acct = new Random();
int AccountNumber = acct.Next(5, 1000);
outputlbl.Text = acct.ToString();
You set the label to "System.Random" (because you call ToString() on the wrong thing). And that can not be sensibly casted into a integer later.
Ideally you should not even retrieve the data from the UI. If you got a integer in code behind, keep it there. Use it. But with the seperation between Events that might not be always possible.
I would recommend, do not just parse a text if you not know whats in the textbox.
Rather do something like this
if(double.TryParse (outputlbl.Text, out double outputNumber))
{
new Account(Nametxtbx.Text, outputNumber, 0);
}
Also, have a look at the formatprovider
Related
I am trying to fill an array from several textboxes, then calculate with the values in the array.
I have the following code, but don't know why it doesn't work. Explained in the code:
private void button1_Click(object sender, EventArgs e)
{
double[] temperaturen = new double[6];
temperaturen[0] = double.Parse(textBox1.Text);
MessageBox.Show(temperaturen[0].ToString()); //the messagebox is just to test if
//it works
}
The above code works, but it stops working after I add more values from more textboxes:
private void button1_Click(object sender, EventArgs e)
{
double[] temperaturen = new double[6];
temperaturen[0] = double.Parse(textBox1.Text); //now it stops working and gives
temperaturen[1] = double.Parse(textBox2.Text); //the following error:
temperaturen[2] = double.Parse(textBox3.Text); //format exceptions was unhandled.
temperaturen[3] = double.Parse(textBox4.Text);
temperaturen[4] = double.Parse(textBox5.Text);
temperaturen[5] = double.Parse(textBox6.Text);
temperaturen[6] = double.Parse(textBox7.Text);
MessageBox.Show(temperaturen[0].ToString());
}
Does anybody know if parsing from textbox is the right way of doing this whatsoever? and why this does not work?
Please note, that you have 7 textboxes, not 6, so you should declare new double[7].
To avoid such errors, let's query with a help of Linq:
using System.Linq;
...
double[] temperaturen = new TextBox[] {
textBox1, textBox2, textBox3,
textBox4, textBox5, textBox6,
textBox7 }
.Select(box => double.TryParse(box.Text, out var value) ? value : double.NaN)
.ToArray();
Note, that text box can have text which is not a valid floating point value (say, "bla-bla-bla"),
I put double.NaN (Not a Number) in this case.
What actually solved the problem is:
Adding a try catch, and changing the array to have 7 values.
The final code, fully functioning.
private void button1_Click(object sender, EventArgs e)
{
decimal[] temperaturen = new decimal[7];//the array
try // try block
{
temperaturen[0] = decimal.Parse(txtZondag.Text);//parsing input
temperaturen[1] = decimal.Parse(txtMaandag.Text);//from
temperaturen[2] = decimal.Parse(txtDinsdag.Text);//textboxes
temperaturen[3] = decimal.Parse(txtWoensdag.Text);
temperaturen[4] = decimal.Parse(txtDonderdag.Text);
temperaturen[5] = decimal.Parse(txtVrijdag.Text);
temperaturen[6] = decimal.Parse(txtZaterdag.Text);
decimal temp = 10.2m;//decimal temp for calculations
decimal uitkomst1 = 0.0m;//decimal for sum.
uitkomst1 = temperaturen[0] - temp;//calculation
textBox8.Text = uitkomst1.ToString();
decimal uitkomst2 = 0;
uitkomst2 = temperaturen[1] - temp;
textBox9.Text = uitkomst2.ToString();
decimal uitkomst3 = 0;
uitkomst3 = temperaturen[2] - temp;
textBox10.Text = uitkomst3.ToString();
decimal uitkomst4 = 0.0m;
uitkomst4 = temperaturen[3] = temp;
textBox11.Text = uitkomst4.ToString();
decimal uitkomst5 = 0;
uitkomst5 = temperaturen[4] - temp;
textBox12.Text = uitkomst5.ToString();
decimal uitkomst6 = 0;
uitkomst6 = temperaturen[5] - temp;
textBox13.Text = uitkomst6.ToString();
decimal uitkomst7 = 0;
uitkomst7 = temperaturen[6] - temp;
textBox14.Text = uitkomst7.ToString();
}
catch (Exception exception)//catch block
{
MessageBox.Show("Incorrecte invoer! " + exception.Message);
}
}
Your code is not SOLID, meaning that it doesn't follow the guidelines of the Solid principle. If you are not familiar with SOLID, consider to read some background information about SOLID
For instance, your code has more than one Responsibility. This principle states that each class should have a single purpose or responsibility. This helps reduce bugs by:
Simplifying the code,
Making testing easier, and
Allowing for more modularity (i.e., the ability to reuse and combine code).
In your case: you need a class that can read the temperature from somewhere. This can be from a text box, or from the internet, a digital thermometer, anything:
interface IThermometer
{
double ReadTemperature();
}
class TextBoxThermometer : IThermometer
{
public TextBox TextBox {get; set;}
public double ReadTemperature()
{
// TODO: add some error checking: null textbox, no proper value in the textbox, etc.
return Double.Parse(this.TextBox.Text);
}
}
This class is easy to create, easy to test, and easy to maintain: if you want a decimal as temperature, the changes will be minimal.
Once you've got this class, and created unit tests for them, you can be certain that the class is working correctly, for any TextBox that you attach to this class.
Apparently you don't have one Thermometer, you've got a collection of Thermometers. From each Thermometer you can read the temperature:
class ThermometerCollection : IReadOnlyCollection<IThermometer>
{
public List<IThermometer> Thermometers {get; set;}
// TODO: implement IReadOnlyCollection<IThermometer>
public double ReadTemperatur(int thermometerIndex)
{
// TODO: check validity of thermometerIndex
return this.Thermometers[thermometerIndex].ReadTemperature();
}
}
The thermometer collection is also a fairly simple class with functions with only one or two lines. Easy to understand, Easy to test, easy to maintain. If desired you can even have different types of thermometers in the collection: one that reads from a text box, another that reads from the internet.
Because you've unit tested the class, you can be certain that it works with all kinds of IThermometers.
Inside your form:
private IReadOnlyCollection<IThermometer> Thermometers {get;}
public MyForm() // constructor
{
InitializeComponent();
this.Thermometers = new ThermometerCollection
{
Thermometers = new List<IThermometer>()
{
new TextBoxThermometer() {TextBox = this.TextBox1},
new TextBoxThermometer() {TextBox = this.TextBox2},
new TextBoxThermometer() {TextBox = this.TextBox3},
new TextBoxThermometer() {TextBox = this.TextBox4},
new TextBoxThermometer() {TextBox = this.TextBox5},
new TextBoxThermometer() {TextBox = this.TextBox6},
},
}
}
Now your form has one ThermometerCollection with six thermometers. For users of these thermometers, it is not important how they get their temperature. They might read them from a text box, but if in future you decide to read the temperature from the internet, changes in your form will be minimal. Remember: because you've got unit tests for your TextBoxThermometer you can be sure that this type of Thermometer works flawless.
Now that you've decoupled the Thermometer from where it gets the temperature, in your form you can write methods to read the temperature
public double ReadTemperature(int thermometerIndex)
{
return this.ThermometerCollection.ReadTemperature(thermometerIndex);
}
Again a one liner method. Note that this is a method in your Form, so it is fairly difficult to unit test. But since you have tested the ThermometerCollection thoroughly, you hardly miss the test.
private void button1_Click(object sender, EventArgs e)
{
this.ProcessTemperatures();
// TODO: do other things that must be done when button1 is clicked
}
public void ProcessTemperatures()
{
// Read the temperatures, and process them:
ICollection<double> measuredTemperatures = Enumerable.Range(1,6)
.Select(thermometerIndex => this.ReadTemperature(thermometerIndex)
.ToList();
this.ProcessTemperatures(measuredTemperatures);
}
public void ProcessTemperatures(ICollection<double> measuredTemperatures)
{
// TODO: do what you wanted to do with your measured temperatures
}
I've decoupled the button click from the processing. If later you decide that you want to do something different if the button is clicked, changes will be minimal. Also, if you want to add a menu item that will also process the temperatures: the procedure will be a one liner.
Summary
Because I made methods that only have one specific task, you have methods that are easy to understand, easy to unit test, simple to change and maintain, simple to reuse.
Because I separated your from from the notion of Thermometers, you can reuse the thermometers in a different form. You have unit tested the Thermometer classes, so you can be certain that it will also work if you want 10 Thermometers.
Because I separated the Thermometer from where it gets its data from, it is easy to use a different type of Thermometer, for instance one that reads from a cell in a table, or from the internet. Users of your Thermometer class won't notice the difference.
Am trying to solve this issue I have for work I saw that selenium is quite useful and I wanted to save time and energy doing the same task everyday so I tried making a really basic way to solve the current issue I have with C# and Selenium I need to do the following.
I'm trying to figure out how I could connect a textbox (multiple text input) to then randomly pick one and send it to a webpage. This is my code so far:
namespace emails
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
//textbox input
string quest = question1.Text;
var random = new Random();
var names = new List<string> { question1.Text};
int index = random.Next(names.Count);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
ChromeDriver driver = new ChromeDriver(#"C:\webdrivers");
ChromeDriver drv; Thread th;
string url = "https://accounts.google.com/signin/v2/identifier?continue=https%3A%2F%2Fmail.google.com%2Fmail%2F&service=mail&sacu=1&rip=1&flowName=GlifWebSignIn&flowEntry=ServiceLogin";
driver.Navigate().GoToUrl(url);
driver.FindElement(By.ClassName("whsOnd")).SendKeys(question1.Text); Thread.Sleep(2000);
}
}
}
I tried this but as expected this would just send the whole textbox input.
Assumimg question1 contains several lines and you want to pick 1 line, ie question1 is:
SomeLineWhichIsaName
AnotherLineAnotherName
SomeMoreName
You want to split question1 on linebreaks, which gives you a list of lines (3 in this case, they seem to be names). Than your random function works.
var names = question1.Text.Split("\r\n");
int index = random.Next(names.Count);
string randomName = names[index];
driver.FindElement(By.ClassName("whsOnd")).SendKeys(randomName)
\r\n or \r or \n => just figure out what works
I'm trying to create a Calculator with a Class. However using references from the internet particularly from this website (https://www.sourcecodester.com/tutorials/c/7548/simple-calculator-using-class-c.html)
It did not mention to declare "Information" or whatsoever.
When I typed in the code, the error list return with Information does not exist in current context.
Is there a way to modify the code below? Thank you so much.
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
}
private void Form4_Load(object sender, EventArgs e)
{
}
public void RadioButton_Click(object sender, System.EventArgs e)
{
//call a constructor method and return to cal as an instance of a class
calculate cal = new calculate();
//declaring the string variable represent as a textbox
string txtnum1 = TextBox1.Text;
string txtnum2 = TextBox2.Text;
//declaring the double variable
double dbl_val1 = default(double);
double dbl_val2 = default(double);
if (**Information**.IsNumeric(txtnum1) && **Information**.IsNumeric(txtnum2)) //check if the textbox has a numeric value
{
//convert the string to double
dbl_val1 = double.Parse(txtnum1);
dbl_val2 = double.Parse(txtnum2);
//get the value of the converted variable
//to pass it into the variable in the class
cal.num1 = dbl_val1;
cal.num2 = dbl_val2;
//the condition is, if the radiobutton is clicked,
//the operation of MDAS executes.
if (Radio_Multiplication.Checked)
{
//result:
cal.multiply(); //call a subname in a class for multiplying
}
else if (Radio_Addition.Checked)
{
//result:
cal.add(); //call a subname in a class for adding
}
else if (Radio_Subtraction.Checked)
{
//result:
cal.subtract(); //call a subname in a class for subtracting
}
}
else
{
//the result is:
//if the textbox is empty or has a string value
TextBox3.Text = "Enter a number";
return;
}
//put the result of the MDAS to a textbox.
TextBox3.Text = cal.total.ToString();
}
}
I had a quick look at the link and they don't appear to have declared Information anywhere nor have they indicated that they've overridden anything so...I don't know.
That line, however, is just validating that the information entered into the two text boxes are actually numbers and not anything else that can't be calculated.
There are lots of methods you could use to check those numbers. Options would include, but are not limited to:
if(Int32.TryParse(txtNum1, out int temp1) && Int32.TryParse(txtNum2, out int temp2))
{
do stuff;
}
or
if(txtNum1.All(char.IsDigit) && txtNum2.All(char.IsDigit))
{
do stuff;
}
There are other options, but those two might be worth looking into.
Downloading the sample project, I had a look at what Information refers to. Turns out, it's a class from the Microsoft.VisualBasic namespace, presumably for exposing certain aspects of the VB core library to all .NET languages. You can use it in your program by adding a reference to Microsoft.VisualBasic to your project and adding:
using Microsoft.VisualBasic;
to the top of your code file.
(Personally, I can't imagine that this approach is terribly efficient. It's supposed to take an object and determine if it can be evaluated as a number, and I have no idea what approaches it uses to make that deduction based on any random object. You would probably be better off using one of the alternatives that Benny O'Neill suggests.)
having a bit of a problem changing the label text when a button is pressed. my code looks like this. i searched a bit in this forum and tried this solution in form1 i have this code.
public string info
{
get
{
return label11.Text;
}
set
{
label11.Text = value;
}
}
in class search i have this
public void fighting()
{
character tom = new character();
Form1 f = new Form1();
Random explore = new Random();
int exploration = explore.Next(0, 3);
if (character.location == "Forest" || character.location == "Dungeon")
{
switch (exploration)
{
case 0:
f.info = "You didnt find anything";
f.Refresh();
f.herodamage = exploration.ToString();
break;
...
the button has this
public void button8_Click(object sender, EventArgs e)
{
Search find = new Search();
find.fighting();
}
what am i doing wrong? everytime i press the button the text wont change but it works because it does change a buttons text.
Fighting method is creating a new instance of Form1, different from your UI.
While it is updating label1.Text, it refers to different Form1.
My suggestion is for refactoring of your code to make responsibilities more clear.
Something like
var info = find.fighting(); // Where fighting returns string, instead of creating new Form1 and setting value, just return the value.
this.info = info;
If you still insist to update UI from search method, which is not correct way to approach this problem, you can pass around Form1 from the parameter.
Search find = new Search(this); // Store it as instance of Search class.
find.fighting(); // fighting should never create new instance of Form1 (reason of problem you are facing)
Instead of creating a new instance of Form1 you need to get a reference to the already existing instance of this form.
One simple way to do this is to use the Application.OpenForms property:
character tom = new character();
Form1 f = Application.OpenForms.OfType<Form1>().FirstOrDefault();
Random explore = new Random();
...
I need a little help with a Random Number Guessing Game in visual studio. I got the brunt of the code down but I am having troubles with the Random number generator and getting the random number to port into the click events. As always, I don't really need code but some guidance and/or explanations as to what I am doing wrong and if there is a more effecient way to do things in the beginner phases of learning. Below is my code, the comments are the parts where I am having troubles. Thanks for any help as the help I've recieved to date as been phenominal.
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 LAB6B
{
public partial class game : Form
{
public game()
{
InitializeComponent();
//Generate Random number between 1 and 100
//Not sure if there is a better way?
Random rand1 = new Random();
int num1 = rand1.Next(1,50);
int num2 = rand1.Next(1,50);
int answer = num1 + num2;
}
private void evaluate_Click(object sender, EventArgs e)
{
int count = 0;
int choice = Convert.ToInt32(guess);
if (guess.Text != string.Empty)
{
// set counter to keep track of how many tries
// should this be done by a loop or will it count without a loop?
count++;
//compare user input against random number
//Can’t import the random number for comparision
if (choice < answer)
{
Evaluate.Visible = false;
lblMessage.Visible = true;
lblMessage.Text = "Too Low!";
Clear.Visible = true;
BackColor = Color.LightSeaGreen;
}
else if (choice > answer)
{
Evaluate.Visible = false;
lblMessage.Visible = true;
lblMessage.Text = "Too High!";
Clear.Visible = true;
BackColor = Color.SlateBlue;
}
else
{
//Display correct message along with how many times it took to get it
MessageBox.Show(" Eso es CORRECTO! It took you {0} tries. ", count);
}
}
}
private void Clear_Click(object sender, EventArgs e)
{
guess.Text = "";
Evaluate.Visible = true;
lblMessage.Visible = false;
Clear.Visible = false;
BackColor = Color.PowderBlue;
}
}
}
As the rand1 and answer variables are defined within the constructor, you can only access them in the constructor. Defining answer on the class level will solve most of the problems, as you will be able to access it both from the constructor and the click handlers, like this:
private int answer;
private int count;
public game()
{
InitializeComponent();
//Generate Random number between 1 and 100
Random random= new Random();
// no need for num1 and num2, it's just as random
answer = random.Next(1,101);
}
I think you have an issue of scope. The "answer" variable is declared inside your constructor, so it will not be visible to the code inside evaluate_Click(…).
Looks like you need to declare answer as a class variable. When you declare a variable in a constructor, it's still local to that method and not available to other methods.
I do not really know what you want answered, but an obvious error is that you must define your count variable as a member variable in order to keep track of the number of tries. As it is now, the count will always be initialized as zero each time the user presses the button.
First of, you need to declare your variable answer in the page level so it can be used by other page level functions.
Do it like this
public partial class game : Form
{
int answer;
public game()
{
}
}
in your counter you can use a static counter or a page level variable also such as the variable answer
just reset the counter when the user have guessed correctly