I am trying to get this piece of code working in C#, what I want to do is if a textfield is updated to validate its an integer (HP is an integer).
So by attempting to convert the input to an integer, I either get a new integer, and sets the value to it, or if it fails, it takes the previous verified value and pushes back to the text field (pretty much ignoring the input, updating it, and it is now a validated input).
In my head this is all logic and working, in effect its not. Please help.
private void Input_HP_TextChanged(object sender, EventArgs e)
{
Try
{
HP = Convert.ToInt32(Input_HP.Text);
}
catch(Exception e)
{
Input_HP.Text = HP;
}
}
You can use try.parse, but you will want to set it to a temporary variable. In your case, using HP will overwrite your variable you want to save.
int tempInt;
if(Int32.TryParse(Input_HP.Text, out tempint))
{
HP = tempInt;
}
else
{
Input_HP.Text = HP.ToString();
}
Int.TryParse is probably what you are looking for:
int HP;
if (int.TryParse(Input_HP.Text, out HP))
{
// the number is an integer at this point
}
If HP is an integer you cannot directly assign it to the Text property because this is of type String. This should be a compile time error, for this part of the code you should be using the .ToString() function...
Input_HP.Text = HP.ToString();
Of course, you should be using a TryParse for this conversion anyway. I guess what you want is something like this...
private void Input_HP_TextChanged(object sender, EventArgs e)
{
int i = 0;
if(int.TryParse(Input_HP.Text, out i))
{
HP = i;
}
else
{
Input_HP.Text = i.ToString();
}
}
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Edit add: The problem I was given amounts to making use of a text file that contains 18 differing account numbers. I'm given the option of making the program read it to an array or a List<>. Then the program should allow a user to input a number and determine if it matches an entity in the array/List<>, displaying that it's valid/invalid.
It took me a fair while to get my code to work correctly. Now, I don't mind that a bad input validation returning false is followed by the latter methods being run through, thus producing the second popup. It's rather annoying at times, however. It works fine, like I said, but I'd like to find out if there's a way to make it stop running through the rest if the validation returns false.
private void ReadAccNums(int[] accountNumArray)
{
// Try-catch to prevent file error issues.
try
{
// Increment num var.
int num = 0;
// Open ChargeAccounts.txt file.
StreamReader accNumsFile = File.OpenText("ChargeAccounts.txt");
// Read account numbers into array.
while (num < accountNumArray.Length && !accNumsFile.EndOfStream)
{
// Put each item into accountNumArray.
accountNumArray[num] = int.Parse(accNumsFile.ReadLine());
num++;
}
// Close file.
accNumsFile.Close();
}
catch (Exception ex)
{
// Display error message.
MessageBox.Show(ex.Message);
}
}
// Method to handle TextBox input
// validation.
private bool InputIsValid(ref int accNum)
{
// Flag to make sure input is good.
bool inputValid = false;
// Get and validate accountNumbersAccessTextBox input.
if (int.TryParse(accountNumberAccessTextBox.Text, out accNum))
{
// Did we get this far? Confirm input validation.
inputValid = true;
}
// Display error message for accNum.
else
{
MessageBox.Show("Please input a non-decimal, seven digit number" +
" for the account number.");
// Reset Focus to accountNumbersAccessTextBox.
accountNumberAccessTextBox.Focus();
}
// Return result.
return inputValid;
}
// Method to find out if input
// has a match in ChargeAccounts.txt.
private int AccNumSearch(int accNum,
int[] accountNumArray)
{
// Bool flag for matching accNum.
bool accNumFound = false;
// Index var.
int num = 0;
// Position of Sequential Search.
int position = -1;
// Get input from TextBox.
if (InputIsValid(ref accNum))
{
// Read through array to find
// matching accNum.
while (!accNumFound && num < accountNumArray.Length)
{
if (accountNumArray[num] == accNum)
{
// Found a match? Yay! Access granted!
accNumFound = true;
position = num;
}
num++;
}
}
// Return.
return position;
}
// Method to determine whether input
// matches an account number.
private bool AccNumMatch(int[] accountNumArray,
ref int accNum)
{
// Bool flag to confirm
// matching accNum.
bool accNumMatch = false;
// Got a match? Tell the user.
if (AccNumSearch(accNum, accountNumArray) != -1)
{
accNumMatch = true;
MessageBox.Show("Account number correct. Access granted.");
}
else
{
// No match? Alas.
MessageBox.Show("Account number invalid. Access denied.");
}
// Return.
return accNumMatch;
}
private void accountNumberAccessButton_Click(object sender, EventArgs e)
{
// Declare array to be filled by
// ReadAccNums method.
const int SIZE = 18;
int[] accountNumArray = new int[SIZE];
// Get the account numbers.
ReadAccNums(accountNumArray);
// Var for accNum to ref.
int accNum = 0;
// Is our account number correct?
AccNumMatch(accountNumArray, ref accNum);
}
Your code seems and incredibly verbose approach to:
the user types a number into a textbox
the program checks it's numeric
the program checks it's present in a file
If I was tasked to write such a code I might:
void Login_Click(object sender, EventArgs e){
if(!int.TryParse(accountNumberTextbox.Text, out int seeking)) {
MessageBox.Show("The account number text does not appear to be numeric");
return;
}
accNumMatch = File.ReadLines("c:\\temp\\accountnumbers.txt").Any(line => line == accountNumberTextbox.Text));
if(accNumMatch) {
MessageBox.Show("Account number correct. Access granted.");
}
else {
MessageBox.Show("Account number invalid. Access denied.");
}
}
because there simply isn't any point in converting the file contents to number and then searching the number; simpler to leave them as strings and compare strings, after making sure what the user entered was a number
And if I used a numericupdown so the user couldn't even enter a non number:
void Login_Click(object sender, EventArgs e){
accNumMatch = File.ReadLines("c:\\temp\\accountnumbers.txt").Any(line => line == accountNumberNumericUpDown.Value.ToString()));
if(accNumMatch) {
MessageBox.Show("Account number correct. Access granted.");
}
else {
MessageBox.Show("Account number invalid. Access denied.");
}
}
YOu can just convert what they entered to text and launch straight into reading the file and looking for a line bearing what they entered
I appreciate you might be learning, so using LINQ is a bit of a cheat, but even so:
void Login_Click(object sender, EventArgs e){
if(!int.TryParse(accountNumberTextbox.Text, out int seeking)) {
MessageBox.Show("The account number text does not appear to be numeric");
return;
}
accNumMatch = false;
StreamReader accNumsFile = File.OpenText("ChargeAccounts.txt");
while (!accNumsFile.EndOfStream && !accNumMatch)
{
string line = accNumsFile.ReadLine();
accNumMatch = (line == accountNumberTextbox.Text);
}
}
I'll forego lecturing about using/making sure you close and dispose your file readers etc for now ;)
If you have to read a file into an array, you can use System.IO.File.ReadAllLines() as a quick way to read a file. I won't use it here, but you can look it up if you want to see
If you have to read up to X lines from a file, into an array of ints, and then see if any of the ints are the one you seek:
void Login_Click(object sender, EventArgs e){
bool validInput = int.TryParse(accountNumberTextbox.Text, out int seeking);
if(!validInput) {
MessageBox.Show("The account number text does not appear to be numeric");
return;
}
int[] numbers = new int[100];
StreamReader accNumsFile = File.OpenText("ChargeAccounts.txt");
for(int i = 0; i < numbers.Length && !accNumsFile.EndOfStream; i++)
{
string line = accNumsFile.ReadLine();
numbers[i] = int.Parse(line);
}
accNumMatch = false;
foreach(int number in numbers){
if(number == seeking) { //seeking comes from earlier
accNumMatch = true;
break;
}
}
}
You could break these into separate methods. Make a method that takes an input and gives an output:
void Login_Click(object sender, EventArgs e){
int seek = ConvertToAccountNumber(accountNumberTextbox.Text);
if(seek == -1){
MessageBox.Show("Enter a valid number");
return
}
int[] numbers = GetAccountNumbersInFile("ChargeAccounts.txt");
accNumMatch = ArrayContainsNumber(numbers, seek);
}
//this is basically a variation of int.Parse/int.TryParse
public int ConvertToAccountNumber(string s){
bool validInput = int.TryParse(accountNumberTextbox.Text, out int seeking);
if(!validInput)
return -1; //we will use -1 to signify invalid input, because no account number is ever -1
else
return seeking;
}
//File.ReadAllLines can help with this, as can LINQ Select/int parse
public int[] GetAccountNumbersInFile(string p){
int[] numbers = new int[100];
StreamReader accNumsFile = File.OpenText(p);
for(int i = 0; i < numbers.Length && !accNumsFile.EndOfStream; i++)
{
string line = accNumsFile.ReadLine();
numbers[i] = int.Parse(line);
}
}
//there exist helper methods for doing this too, look at the Array class - https://learn.microsoft.com/en-us/dotnet/api/system.array?view=netcore-3.1
public bool ArrayContainsNumber(int[] array, int seeking){
foreach(int number in numbers){
if(number == seeking) {
return true;
}
}
return false;
}
I know why you used ref but you should avoid it. Actually the framework uses out when it parses text to a number and returns a boolean to indiccate the success and a number, but you can easily take the approach that something like string.IndexOf takes - it returns -1 if the needle is not found in the haystack. You haven't learned about exceptions yet (probably) but this would be an opportunity to use them too - throw an exception instead of returning a value if the input data is bad
All in, it's one of the few places where out might be reasonable in your career, so use it if you must (for academicc reasons, but don't use ref - ref is for methods that take a variable in with the intention of using its value before possibly overwriting it with something else. This is an out scenario, where the input variable shouldn't have a value and will be overwritten by the method) but
I'm a noobie who is trying to make it's so that the user can't increase the number in a textbox from a .mdf file, but when I test run and test this part of the program it crashes and I see a "System.FormatException: 'Input string was not in a correct format.'" error message.
private void HoeveelheidTextBox_TextChanged(object sender, EventArgs e)
{
if (42 < int.Parse(hoeveelheidTextBox.Text))
{
MessageBox.Show("je kan niet schoenen erbij doen");
{
hoeveelheidTextBox.ToString();
hoeveelheidTextBox.Text = "";
}
}
}
(je kan niet schoenen erbij doen = you can't add anymore shoe's
hoeveelheid = amount)
As you can see in the code I tried converting the TextBox back into a string, However, I still get the error.
My desired outcome is that the program clears the TextBox when the number is larger then what it first was.
Well, it seems that there's a possibility that HoeveelheidTextBox has a value which is not a valid int value (say, an empty string); let's use TryParse instead of Parse:
private void HoeveelheidTextBox_TextChanged(object sender, EventArgs e) {
if (int.TryParse(hoeveelheidTextBox.Text, out int value)) {
// TryParse succeeded; hoeveelheidTextBox.Text has an integer value
// Let's check what the value is
if (42 < value) {
// hoeveelheidTextBox.Text has an integer value that exceeds 42
MessageBox.Show("je kan niet schoenen erbij doen");
hoeveelheidTextBox.Text = "";
}
else {
// hoeveelheidTextBox.Text has an integer value which is 42 or below it
}
}
else { // TryParse failed;
// hoeveelheidTextBox.Text doesn't have an integer value
// (it can be an empty string, "bla-bla-bla" etc.)
hoeveelheidTextBox.Text = "";
}
}
Good day fellow helpers, i have following problem:
(running MS Visual Community Edition 2015)
private void button4_Click(object sender, EventArgs e) // Senden
{
serialPort2.WriteLine("SR,00,002\r\n");
textBox1.Text = "gesendet";
textBox3.Text = "";
try
{
System.IO.StreamReader file = new System.IO.StreamReader("C:\\blub.txt");
String line = file.ReadToEnd();
string Hallo = line; \\in the beginning there is "0" in the file
file.Close();
decimal counter = Convert.ToDecimal(Hallo); \\just for testing
counter++;
string b = serialPort2.ReadLine();
string[] b1 = Regex.Split(b, "SR,00,002,"); \\cuts off unwanted input from device
decimal b2 = decimal.Parse(b1[1]); \\number like -3000
System.IO.StreamWriter test = new System.IO.StreamWriter("C:\\blub.txt");
test.WriteLine(counter);
test.Close();
textBox7.Text = "Das ist counter:" + counter;
}
catch (TimeoutException)
{
textBox3.Text = "Timeout";
throw;
}
}
Now, the Serialport is a device that returns a lengthmeasurment. As it is a bit weird, or just the way its build it start with a negitve number (between -5000 and -3370). Now as i want to get measurement on the screen that is realistic i want to set the value to 0 and calculate the difference.
Means: I start the programm - press send - get a value (say -3000) - press send again (after pushing the seonsor in) and get the value that its been pushed in > 0 by adding the difference to 0.
I only learned to store values externally when i had a C course a year back like i did within my programm. Is there a way to store the value from the first measurement in the programm so i can use it on the next send/try?
The counter was just for testing and I would exchange it for the "decimal b2"
I hope there is an easy fix for that, not really a pro with C# yet but i'm eager to learn. I thank the willing helpers in advance, MfG, Chris
OK, I will simplify this in order to show concept so it will not have all the code you are actually using.
So, what you want is to click on button, get some values and store them for next click.
Value is stored in variable. If you have variable in function that is handler for click event, as soon as function completes execution, value will be destroyed.
So, what you need is to create variable in outer scope (class level). Your function is already in class of the form so let's get to code:
class Form1
{
string BetweenClickStorage;
private void button4_Click(object sender, EventArgs e)
{
//Load data here
BetweenClickStorage = LoadedData;
}
}
After this, when you click again on the button, value will still be in BetweenClickStorage. It will be also available to all other buttons click handlers and other code in that form.
If I'm understanding your question correctly, the answer is simply to declare a variable outside the try/catch:
//declare variable //
var measurement;
// TRY #1 //
try
{
//assign value to the variable here
}
catch
{
}
// TRY #2 //
try
{
// reference variable here
}
catch
{
}
I find this code from here to add a unit like minutes or kg at the end of a textbox after the number was entered. in C#
private void CowAgetxtBox_Leave(object sender, EventArgs e)
{
{
CowAgetxtBox.Text = CowAgetxtBox.Text + " Month";
}
}
private void CowAgetxtBox_Enter(object sender, EventArgs e)
{
{
CowAgetxtBox.Text = CowAgetxtBox.Text.Replace(" Month", "");
}
}
but I don't know how get that number,
I use this Code but it doesn't work
int Age = int.Parse(CowAgetxtBox.Text);
Actually it's not a good idea to put the unit inside the textbox, this will cause a lot of problems in data validation, localization, casting, ...
better to put it outside the textbox :)
You just need to do a process similar you when the user focused on the text box.
int Age = int.Parse(CowAgetxtBox.Text.Replace(" Month", ""));
This will get the job done.
It seems that
CowAgetxtBox.Text
this statement contains value other then number thats why this statment
int Age = int.Parse(CowAgetxtBox.Text);
is not working remove " Month" from the first function
If the unit label changes, this might work in more cases for you:
int Age = int.Parse(CowAgetxtBox.Text.Split(' ')[0]);
You can add a property like the following:
int Age {
get { return Convert.ToInt32(CowAgetxtBox.Text.Replace(" Month", "")); }
}
I'm working on a programming assignment, and I'm trying to make this button take the values from two textboxes, and calculate the new location for the form window. I'm having trouble converting the textbox values to type int, and being made usable by the btnCompute_click method.
private void btnCompute_Click(object sender, EventArgs e)
{
int x = Convert.ToInt32(txtXvalue);
int y = Convert.ToInt32(txtYvalue);
Location = new Point(x,y);
}
private void xValue_TextChanged(object sender, EventArgs e)
{
int xValue =
Convert.ToInt32(txtXvalue);
}
private void yValue_TextChanged(object sender, EventArgs e)
{
int y =
Convert.ToInt32(txtYvalue);
}
I forgot to add some additional info, the acceptable values for x and y must be positive. Would I use an if...else statement to control the acceptable values?
user29... i have no idea why death... replied that. it makes no sense to me. but you question makes sense to me. i suppose death... did not understand your question.
First off, everything you ask does not need anything in the TextChanged methods.
Do all your handling in the btnCompute_Click() method because you want to do something *when you click your button, not when the user edits the text of the text boxes, according to your question.
The code that is in your TextChanged() methods will get executed whenever the Text values of those text boxes change. that's not what you asked for it to do. But you could use these events for example, if you wanted a label to become visible or hidden and to set the text of a label which shows text, so you can use it as an error message label, for instance if the integer value of a text box is negative or even if it cannot be parsed.
So in your btnCompute_Click() methods, you first want to get the int values. You need to decide exactly what you want your code to do if the text is not integers. In my opinion, most beginners code things like message boxes or something. I like to give the user feedback with Labels or a status bar message, depending on what I feel is appropriate. Since my first choice would be to use a Label to show the 'error' message when text boxes cannot be parsed to integers, then i would simply return from the button click method without doing anything when the values are not what i want. That way the user gets their messages without annoying popup message boxes or anything. But it's up to you whether you want to pop up a message box or not. Others have given you good code to do that. I want to give you good code that avoids what i consider annoying popup boxes.
When converting strings to an int, Convert.ToInt32 will throw an error if the string cannot be parsed. int.TryParse is the silver bullet for truly parsing strings to integers without any error. Here is the entire code i would use. I made a new project just to make sure i'm not giving you buggy code. I give you my code on how I handle this.
In your updated prerequisite, you mention x & y must be positive and not negative. I note to you that these are not the same. For instance, 0 is neither positive nor negative. I assume that you technically mean that x and y cannot be negative, (and that it does not need to be positive, since 0 should be allowed).
private void Form1_Load(object sender, EventArgs e)
{
lblErrorX.Text = null;
lblErrorY.Text = null;
}
private void btnMoveForm_Click(object sender, EventArgs e)
{
int x = 0; if (int.TryParse(txtX.Text, out x) == false) { return; }
int y = 0; if (int.TryParse(txtY.Text, out y) == false) { return; }
if (x < 0 || y < 0) { return; }
this.Location = new Point(x, y);
}
private void txtX_TextChanged(object sender, EventArgs e)
{
int x = 0;
if (int.TryParse(txtX.Text, out x) == false)
{ lblErrorX.Text = "X is not an valid integer."; return; }
if (x < 0) { lblErrorX.Text = "X cannot be negative."; return; }
lblErrorX.Text = null;
}
private void txtY_TextChanged(object sender, EventArgs e)
{
int y = 0;
if (int.TryParse(txtY.Text, out y) == false)
{ lblErrorY.Text = "Y is not an valid integer."; return; }
if (y < 0) { lblErrorY.Text = "Y cannot be negative."; return; }
lblErrorY.Text = null;
}
In my project, on the form, in the following left to right order: lblX, txtX, lblErrorX. I have the same corresponding for Y: lblY, txtY, lblErrorY. Then i have one Button: btnMoveForm. So my txtX corresponds to your txtXvalue. my btnMoveForm corresponds to your btnCompute, but to me, 'compute' means to calculate, which is not really what this button is doing. this button is moving the form, so that's why i name it as such.
I have played with setting both the Location and the DesktopLocation and it seems to do the same thing. I've always used Location and i just learned that DesktopLocation works too, but since Location is shorter, i use it.
Someone asked why i don't use if(!int.TryParse(...)) { return; } rather than my if(int.TryParse(...) == false) { return; }. My reason is unfortunately that i think ! is an easy one character to miss when reading code, so i avoid it, especially when that little mistake means the opposite of what the code really would do. So my use of '== false' is always for human clarity. But i do like the C# ease of only needing one character. I just think it's a shame that in my opinion, it's a lot safer to write code that is better for humans so we don't mistake it. That's the only reason i use '== false' instead of !. Use ! if you like. It's quite convenient. I regret not using it. hehe.
Oh, and the reason i set the lblErrorX.Text = null; and lblErrorY.Text = null; is on my form in design view, i give them a text value so i can see them. :) so when the program runs, i set the Text to be blank. But you can use the Visible property if you prefer. I just leave them always visible and only set their Text properties.
Based on your expanded criteria you can check for negative numbers conditionally or use Math.Abs to get the absolute value. Something like this.
int x, y;
if (int.TryParse(txtXvalue.Text, out x) && int.TryParse(txtYvalue.Text, out y))
{
if (x < 0 || y < 0)
{
MessageBox.Show("Negative numbers not allowed");
}
else
Location = new Point(x, y);
}
else
{
MessageBox.Show("Must be an Integer");
}
or
int x, y;
if (int.TryParse(txtXvalue.Text, out x) && int.TryParse(txtYvalue.Text, out y))
{
Location = new Point(Math.Abs(x), Math.Abs(y));
}
else
{
MessageBox.Show("Must be an Integer");
}
I think you are looking for this.
private void btnCompute_Click(object sender, EventArgs e)
{
int x = Convert.ToInt32(txtXvalue.Text);
int y = Convert.ToInt32(txtYvalue.Text);
DesktopLocation = new Point(Math.Abs(x), Math.Abs(y));
}
This gets the location for the desktop. Also you need the .Text to get the text inside the textbox. You should also check to make sure the text is not null or empty before using or it will cause an error.
If this isn't what you are looking for please explain a little more.