Why is this code causing an ArgumentOutOfRangeException? - c#

I'm building an application to transform fractions to percentages. I want it so that if I edit the text in the fraction it refreshes and recalculates the percentage.
When I test it, the first time I edit the fraction it doesn't error and works fine but the second time I change something in the fraction it errors. I get this error
An unhandled exception of type System.ArgumentOutOfRangeException occurred in mscorlib.dll
What can I do to fix this?
I'm fairly new to C# so try to dumb it down if at all possible.
Additional information: Index and length must refer to a location within the string."
Here's what I have so far:
private void fractionNumerator_KeyPress(object sender, KeyPressEventArgs e)
{
if (!(char.IsNumber(e.KeyChar) || ((e.KeyChar) == Convert.ToChar(Keys.Back))))
{
e.Handled = true;
}
else
{
if (!((fractionNumerator.Text == "") && (fractionDenominator.Text == "")))
{
if ((e.KeyChar == Convert.ToChar(Keys.Back)))
{
string numer = (fractionNumerator.Text.Substring(0, (fractionNumerator.Text.Length) - 1));
string denom = (fractionDenominator.Text);
outputPercentage.Text = (((((Convert.ToDouble(numer) / Convert.ToDouble(denom)) * 100).ToString()).Substring(0, 6)) + "%");
}
else
{
string numer = ((fractionNumerator.Text) + e.KeyChar.ToString());
string denom = (fractionDenominator.Text);
outputPercentage.Text = (((Convert.ToDouble(numer)/Convert.ToDouble(denom)*100).ToString()).Substring(0, 6));
}
}
}
}
private void fractionDenominator_KeyPress(object sender, KeyPressEventArgs e)
{
if (!(char.IsNumber(e.KeyChar) || ((e.KeyChar) == Convert.ToChar(Keys.Back))))
{
e.Handled = true;
}
else
{
if (!((fractionNumerator.Text == "") && (fractionDenominator.Text == "")))
{
if ((e.KeyChar == Convert.ToChar(Keys.Back)))
{
string denom = (fractionDenominator.Text.Substring(0, (fractionDenominator.Text.Length) - 1));
string numer = (fractionNumerator.Text);
outputPercentage.Text = (((((Convert.ToDouble(numer) / Convert.ToDouble(denom)) * 100).ToString()).Substring(0, 6)) + "%");
}
else
{
string denom = ((fractionDenominator.Text) + e.KeyChar.ToString());
string numer = (fractionNumerator.Text);
outputPercentage.Text = (((Convert.ToDouble(numer) / Convert.ToDouble(denom) * 100).ToString()).Substring(0, 6));
}
}
}
}

From the code you provided i can tell that one of your Substring methods throws this exception. So its probably has invalid second parameter (its either less than 0 or higher than string length). Check msdn for details: http://msdn.microsoft.com/ru-ru/library/aka44szs%28v=vs.110%29.aspx
As mentioned in the comments by mike z, you should use format strings instead of Substring method to format your output. For example doubleValue.ToString("#.####") will return 4 digits of fractional part.

Use yourDoubleExpr.ToString("P4") to convert from number to percentage string. The multiplication by 100.0 is automatic.
Your problem was that cases like (3.0 / 4.0).ToString() lead to a short string, like "0.75", and you cannot take out a .Substring of length 6 from that.

Related

How to validate DataGridView for Decimal values 0.00 in c#

I am validating my textbox for allowing decimal values ad 12.00, 12.50.
My code is
double x;
double.TryParse(tb.Text, out x);
tb.Text = x.ToString("0.00");
It will add decimal places in textbox when it leaves. As this I want to add .00 to my datagrid view cell for my particular cell. Thank you
I think you need to display values up to 2 decimal places in your DataGridView Cell
you can try by setting the DefaultCellStyle property of the column to N2 (2 decimal places)
dataGridView1.Columns["YourColumn"].DefaultCellStyle.Format = "N2";
private void dataGridView2_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.dataGridView2.Columns[e.ColumnIndex].Name == "Aidat")
{
string deger=(string)e.Value;
deger = String.Format("{0:0.00}", deger);
}
}
thanks
i use dataGridView1.Columns["YourColumn"].DefaultCellStyle.Format = "N";
this is good and work.
The above answers are good enough but you can also design your own function for the same task , The below function will convert 23 to 23.00 , 23.0 to 23.00 , 23. to 23.00 , 23.1 to 23.10 and 23.11 will remain as it is , It is just an example to explain the logic
//This function is used to do the formatting of the float values to two places of decimals
private string fn_decimal_formatting(float val)
{
String str = val.ToString();
int pos = str.IndexOf('.');
if (pos == -1) //IndexOf returns negative one if . does not found in the string
str += ".00";
else if (str.Length == pos + 1)
str += "00";
else if (str.Length == pos + 2)
str += "0";
else
{
int start = 0;
int end = pos + 2;
str = str.Substring(start, end + 1);
}
return str;
}

how to currency format under textbox?

I want enter number in textbox, an my textbox convert automatically it in comma(,) format. I have tried to do this, but it works wrong. Help me? Like this 1,20(I JUST ENTER 120);
private bool IsNumeric(int Val)
{
return ((Val >= 48 && Val <= 57) || (Val == 8) || (Val == 46));
}
String str;
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
int KeyCode = e.KeyValue;
if (!IsNumeric(KeyCode))
{
if (KeyCode == 13)
{
e.Handled = true;
vendas();
str = null;
}
e.Handled = true;
return;
}
else
{
e.Handled = true;
}
if (((KeyCode == 8) || (KeyCode == 46)) && (str.Length > 0))
{
str = str.Substring(0, str.Length - 1);
}
else if (!((KeyCode == 8) || (KeyCode == 46)))
{
str = str + Convert.ToChar(KeyCode);
}
if (str.Length == 0)
{
textBox1.Text = "";
}
if (str.Length == 1)
{
textBox1.Text = "0,0" + str;
}
else if (str.Length == 2)
{
textBox1.Text = "0," + str;
}
else if ((str.Length > 2) && (str.Length != 6) && (str.Length != 9) && (str.Length != 12))
{
textBox1.Text = str.Substring(0, str.Length - 2) + "," + str.Substring(str.Length - 2);
textBox1.Text = textBox1.Text;
}
else if ((str.Length > 6) && (str.Length != 8) && (str.Length != 10) && (str.Length != 12))
{
textBox1.Text = str.Substring(0, str.Length - 3) + "," + str.Substring(str.Length - 1);
textBox1.Text = textBox1.Text;
}
}
It shows me 10,01 instead 0,01?
What you want is a MaskedTextBox.
Simply set of mask of "$999,999,990.00" and any input the user enters must be digits, and there must be at least 3, but the entry can be any number up to the hundreds of millions (if you need billions and trillions, just add more 9s and commas). As the user enters these digits, the formatting will adjust based on the mask. Here's the kicker; MaskedTextBox respects culture information, so if you specify the French culture, the commas become spaces, the decimal becomes a comma, and the dollar sign becomes the Euro symbol.
I was originally going to suggest MaskedTextBox, but MTB is designed for left-to-right style formatting of a fixed (or known in advanced, at least) length string, which makes it not so suitable for currency.
First, I'd recommend you avoid doing anything using keycodes or the like, and stick to something a bit more straightforward by just validating and editing the text when it changes:
void tb_TextChanged(object sender, EventArgs e)
{
//Remove previous formatting, or the decimal check will fail
string value = tb.Text.Replace(",", "").Replace("$", "");
decimal ul;
//Check we are indeed handling a number
if (decimal.TryParse(value, out ul))
{
//Unsub the event so we don't enter a loop
tb.TextChanged -= tb_TextChanged;
//Format the text as currency
tb.Text = string.Format(CultureInfo.CreateSpecificCulture("en-US"), "{0:C2}", ul);
tb.TextChanged += tb_TextChanged;
}
}
The main part is string.Format(CultureInfo.CreateSpecificCulture("en-US"), "{0:C2}", ul); the en-US ensures it'll always show $ and decmials as '.'s. The {0:C2} formats the string as a number (0) of currency (:C) to 2 decimal spaces (2).
This doesn't prevent the user from entering text, but you can keep the previous text (eg '$23.00') and if the user enters something that isn't a number, decimal.TryParse will fail, at which point you can revert the text back to what it was before the user changed it (just by inserting an else block near the end of this event handler).
I'd recommend setting the TB text to '$0.00' or something initially, or the cursor will jump when it formats the first change. It also has some selection issues when commas are adding, which you could get around by storing the selection position just before formatting and changing it afterward, or doing something more complex, it's just an example.
Well, at first glance, I notice that nothing about your code whatsoever makes any sense.
First and foremost, learn coding standards for indentation. This code is extremely hard to read. I'm tempted to flag this question as offensive for having had to look at it.
Next, this line:
if (!IsNumeric(KeyCode){
Says: if the keycode is NOT numeric do the following stuff, where "the following stuff" is a whole bunch of numeric operations on a keycode which is presumed to be numeric.
Next, str is not defined anywhere in your method. Maybe it's defined globally, but that would just be silly. Rather, you should just get the current value of it programmatically.
And finally:
you don't need to reinvent the wheel. There are tons of tools out there that will do this kind of thing for you. In fact, I'm fairly sure win forms has a native control that'll do this. It might even be an attribute of textbox, I don't remember.

Getting integer from textbox

I want to write the event handler method button1_Click to calculate whether student’s Grade is “PASS” or “FAIL”. The student passes the course if the total score is greater than or equal to 50. The total score is Midterm(textbox1) + Final(textbox2) scores. However, teacher can give student Extra Credit(checkbox1) which is worth 10 points. The result will present in the textBox3
Here's my code:
private void button1_Click(object sender, EventArgs e)
{
int midtermInt = int.Parse(textBox1.Text);
int finalInt = int.Parse(textBox2.Text);
if (checkBox1.Checked)
{
if ((midtermInt + finalInt) + 10 >= 50)
{
grade.Text = "PASS";
}
else if ((midtermInt + finalInt) + 10 < 50)
{
grade.Text = "FAIL";
}
}
else if (!checkBox1.Checked)
{
if ((midtermInt + finalInt) >= 50)
{
grade.Text = "PASS";
}
else if ((midtermInt + finalInt) < 50)
{
grade.Text = "FAIL";
}
}
When I run it, it says "Inut string was not in a correct format.. :(
I'm very new to C# please advise me if my code is wrong anywhere
The input will only be integers never texts..
You should use int.TryParse insted int.Parse, it's check is specified string is in correct format.
You code may looks like this:
int midtermInt;
if (!int.TryParse(textBox1.Text, out midtermInt))
{
labelError.Text = "Icorrect value in field 'textBox1'".
return;
}
If you type non-numeric characters in your textbox and try to parse the text, it will throw you this exception. Try trimming the input and definitely consider adding UI validation to your forms.
You can add checking, if text in text box is in correct format in TextChanged event:
private void textBox_TextChanged(object sender, EventArgs e)
{
int val;
if (textBox.Text.Length == 0 || !int.TryParse(textBox.Text, out val))
tsPassingScore.Text = "0";
}
And in your click you can check if there is number in textBox again with int.TryParse
Also you can improve your code:
If final summ is not bigger then 50 - it is automatically smaller! And it would be more readable, if you introduce extra variable - for teachers extra credit:
int extraCredit = checkBox1.Checked ? 10 : 0;
int finalScore = midtermInt + finalInt + extraCredit;
if (finalScore >= 50)
grade.Text = "PASS";
else
grade.Text = "FAIL";

Why my form is getting closed when i move the Tab to and fro from the textbox

I have the following code in my TextBox leave event:
private void txtAmount_Leave(object sender, EventArgs e)
{
int x = Convert.ToInt32(txtAmount.Text);
double res = (double)x / 100;
txtAmount.Text = "$" + res.ToString();
}
But if move back to the previous control by hitting Shift+Tab and again moving back to the same textbox and then trying to move to other the form is getting closed automatically. Why does this happen?
The call to Convert.ToInt32() is probably throwing an exception, likely due to being unable to convert the string in your TextBox to an integer. Convert.ToInt32() can throw the following exceptions (descriptions from MSDN):
FormatException - value does not consist of an optional sign followed by a sequence of digits (0 through 9).
OverflowException - value represents a number that is less than Int32.MinValue or greater than Int32.MaxValue.
It's likely a FormatException, thrown when you leave the TextBox after the $ is prepended to your string, or after you enter any non-numeric characters (letters, etc). To fix this, you have a couple of options:
Add a try / catch block around your code to handle any exceptions.
Use Int32.TryParse() instead of Convert.ToInt32().
Add some code that will prevent non-numeric characters from being entered in your TextBox
Here's an improved version of your event handler:
private void txtAmount_Leave(object sender, EventArgs e)
{
string toParse = txtAmount.Text.TrimStart('$');
int parsed;
if (Int32.TryParse(toParse, out parsed))
{
double res = (double)parsed / 100;
txtAmount.Text = "$" + res.ToString();
}
}
The first time you leave this textbox, its contents will be changed to "$123" (for example). The second time you leave, trying to convert that to int will throw an exception.
You could use the overload of TryParse that takes a NumberStyle, something like this, assuming your goal is to just show a currency value with no decimal places.
double number;
if (double.TryParse(txtAmount.Text, NumberStyles.Currency, CultureInfo.CurrentUICulture, out number))
{
txtAmount.Text = number.ToString("C0");
}
else
{
MessageBox.Show("Could not convert.");
}
After reading #Donut's comment on his answer, I am not sure what your goal is. If you'd like to truncate the cents off but still show the ".00", you can do this:
txtAmount.Text = ((int)number).ToString("C");
Or do this, which will round:
txtAmount.Text = (Convert.ToInt32(number)).ToString("C");
If this does not help, please clarify and let us know what you are trying to accomplish.
Try this:
private void txtAmount_Leave(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(txtAmount.Text) && txtAmount.Text.StartsWith("$"))
txtAmount.Text = txtAmount.Text.Substring(1);
int x = Convert.ToInt32(txtAmount.Text);
double res = (double)x / 100;
txtAmount.Text = "$" + res.ToString();
}
Check the txtAmount.Text for the $ sign, before trying to convert it to an int. If the $ sign is present, strip it out, and convert the rest of the input to an int.
Also, you might want to use the Int32.TryParse method, as that will help you figuring out whether the entered text can be converted into an int or not.
You may want to change your code to remove the $ before working with the number:
private void txtAmount_Leave(object sender, EventArgs e)
{
int x = 0;
int.TryParse(txtAmount.Text.Replace("$", string.Empty), out x);
double res = (double)x / 100;
txtAmount.Text = "$" + res.ToString();
}
I got the solution
private void txtAmount_Leave(object sender, EventArgs e)
{
string strAmnt = string.Empty;
strAmnt = txtAmount.Text;
if (strAmnt.Contains(".") && !strAmnt.Contains("$"))
{
txtAmount.Text = "$" + strAmnt;
while (txtAmount.Text.Length - txtAmount.Text.IndexOf(".") <= 2)
{
txtAmount.Text += "0";
}
}
else
if (strAmnt.Contains("$") && !strAmnt.Contains("."))
{
Int64 amnt = 0;
strAmnt = strAmnt.Replace("$", "");
try
{
amnt = Convert.ToInt64(strAmnt);
double amt = (double)amnt / 100;
txtAmount.Text = "$" + amt.ToString();
}
catch (FormatException ie)
{
MessageBox.Show("Invalid Format");
}
}
else
if (!strAmnt.Contains(".") && !strAmnt.Contains("$"))
{
try
{
int x = Convert.ToInt32(txtAmount.Text);
double res = (double)x / 100;
txtAmount.Text = "$" + res.ToString();
while (txtAmount.Text.Length - txtAmount.Text.IndexOf(".") <= 2)
{
txtAmount.Text += "0";
}
}
catch (FormatException ie)
{
MessageBox.Show("InvalidFormat");
}
}
while (txtAmount.Text.Length - txtAmount.Text.IndexOf(".") <= 2)
{
txtAmount.Text += "0";
}
}

How do I check if a number in a textbox is greater than a predefined value

im doing an exercise where i have to make a parking lot application.
The objectives are: Create a form with a numericUpDown control for choosingthe amount of time a vehicle was parked. Add option buttons to show if the vehicle is a car or truck. Clearly label each box and button. Add a label or text box to show the amount to pay.
Also, i have to set some limits. Cars shouldn't pay more than $38.00 for 24 hours, and trucks no more than $44.50 for 24 hours.
The only problem i find is that i cannot set these limits. It gives an error: Use of unassigned local variable 'result' .
Check the commented /// code.
Any help much appreciated. It's not a schoolwork project, i'm just learning c# by myself and doing some exercises.
Here's the code:
private void calculate_Click(object sender, EventArgs e)
{
double carhours = 3;
double truckhours = 3.50;
double carFirsthour = 5;
double truckFirsthour = 6;
int hrs = (int)numericUpDown.Value;
double result;
int maxCarFee = 38;
if (numericUpDown.Value < 1)
{
MessageBox.Show("NO WAY");
return;
}
if (carButton.Checked == true && (numericUpDown.Value == 1))
{
result = (hrs * carFirsthour);
fee.Text = "$" + result;
}
if (carButton.Checked == true && (numericUpDown.Value > 1))
{
result = ((hrs - 1) * carhours + carFirsthour);
fee.Text = "$" + result;
}
if (truckButton.Checked == true && (numericUpDown.Value == 1))
{
result = (hrs * truckFirsthour);
fee.Text = "$" + result;
}
if (truckButton.Checked == true && (numericUpDown.Value > 1))
{
result = ((hrs - 1) * truckhours + truckFirsthour);
fee.Text = "$" + result;
}
/// limits
///if (carButton.Checked == true && (numericUpDown.Value < 24) && (result > maxCarFee))
///{
/// fee.Text = "$" + maxCarFee;
///}
}
Try something like this:
private void calculate_Click(object sender, EventArgs e) {
double carhours = 3.0;
double truckhours = 3.5;
double carFirsthour = 5.0;
double truckFirsthour = 6.0;
double maxCarFee = 38.0;
double maxTruckFee = 44.5;
int hrs = (int)numericUpDown.Value;
double result;
if (hrs < 1) {
MessageBox.Show("NO WAY");
return;
}
if (carButton.Checked) {
result = (hrs-1) * carhours + carFirsthour;
if (result > maxCarFee) {
result = maxCarFee;
}
}
else {
result = (hrs-1) * truckhours + truckFirsthour;
if (result > maxTruckFee) {
result = maxTruckFee;
}
}
fee.Text = "$" + result;
}
However, you don't really make it clear what should happen if a car/truck stays for more than 24 hours (or more than 48 hours). You might end up with more consistent results with something like this:
private void calculate_Click(object sender, EventArgs e) {
double hourlyFee = 3.0;
double firstHourFee = 5.0;
double max24hrFee = 38.0;
if (!carButton.Checked) {
hourlyFee = 3.5;
firstHourFee = 6.0;
max24hrFee = 44.5;
}
int hrs = (int)numericUpDown.Value;
if (hrs < 1) {
MessageBox.Show("NO WAY");
return;
}
double result = 0.0;
if (hrs >= 24) {
result = (hrs / 24) * max24hrFee;
hrs = hrs % 24;
}
if (hrs > 0) {
result = result + firstHourFee + ((hrs-1) * hourlyFee);
}
fee.Text = "$" + result;
}
you need to convert numericUpDown.Value
to int32
or becuase you did this:
int hrs = (int)numericUpDown.Value;
you can just use hrs instead of numericUpDown.Value in the if statement
The problem is that none of the conditional (if) statements are executed so result is never assigned a value. Assign result in its declaration -- double result = 0D; -- and the code will run so you can debug the conditional logic.
You check if numericUpDown.Value is smaller than 24, i think you mean is greater (>)?!
Use of unassigned local variable 'result'
means you do not initialise the variable. you have to do something like this
result = 0
before you go to the if construct.
int hrs = (int)numericUpDown.Value;
You get value in hrs so you can use this in your if conditions.
if (carButton.Checked == true && (numericUpDown.Value == 1))
Write it like following. No need of == true
if (carButton.Checked && (numericUpDown.Value == 1))

Categories