I have one simple windows application in that amount Textbox is there. When i enter amount into amount textbox it will convert it to words in another textbox named txtrupees. Amount Textbox field maximum length is set to 11 places in that last 3 places .00.
My problem is now when i Enter amount with .00 it is working fine. But if i enter 11 places it will giving following Error:
System.OverflowException' occurred in mscorlib.dll Value was either too large or too small for an Int32.tried following code.
How can I prevent this kind of error?
private void txtamount_TextChanged(object sender, EventArgs e)
{
if (txtamount.Text != string.Empty)
{
string[] amount = txtamount.Text.Split('.');
if (amount.Length == 2)
{
int rs, ps;
int.TryParse(amount[0], out rs);
int.TryParse(amount[1], out ps);
string rupees = words(rs);
string paises = words(ps);
txtrupees.Text = rupees + " rupees and " + paises + " paisa only ";
}
else if (amount.Length == 1)
{
string rupees = words(Convert.ToInt32(amount[0]));
txtrupees.Text = rupees + " rupees only";
}
}
}
The issue comes from Convert.ToInt32(amount[0]) where amount[0] can be almost anything, including being superior to Int.MaxValue or inferior to Int.MinValue which would cause an overflow.
Use int.TryParse(amount[0], out foo); and use foo:
else if (amount.Length == 1)
{
int ps;
if(int.TryParse(amount[0], out ps))
{
string rupees = words(ps);
txtrupees.Text = rupees + " rupees only";
}
else
txtrupees.Text = "Invalid number";
}
If you want to deal with bigger numbers, you can use Int64, Double or Decimal
a number that has 11 places is larger than a Int32 number. I suggest you should use int64 instead of int32
https://msdn.microsoft.com/en-us/library/29dh1w7z.aspx
Related
I am trying to figure out what is wrong with my code. New to C#. For some reason when I enter a number in for input when the question is asked.. it just ends and says "exited with code 0". My exceptions handling DOES work but actually entering in the correct numbers doesn't seem to work. Any idea?
using System;
namespace MealInputLayton
{
class Program
{
static void Main(string[] args)
{
decimal mealOne = 0;
decimal mealTwo = 0;
decimal dessertOne = 0;
decimal dessertTwo = 0;
decimal subtotal = 0;
const decimal TIP_PERCENTAGE = 0.2m;
const decimal TAX_RATE = 0.07m;
decimal total = 0;
decimal numPeople = 2;
decimal totalPerPerson = 0;
decimal tip = 0;
decimal tax = 0;
Console.WriteLine("How much did your first meal cost?");
try
{
mealOne = Convert.ToDecimal(Console.ReadLine());
}
catch (System.FormatException)
{
Console.WriteLine("Error for 1st meal price. Input string was not in a correct format.");
Console.WriteLine("How much did your second meal cost?");
try
{
mealTwo = Convert.ToDecimal(Console.ReadLine());
}
catch (System.FormatException)
{
Console.WriteLine("Error for 2nd meal price. Input string was not in a correct format.");
Console.WriteLine("How much did your first dessert cost?");
try
{
dessertOne = Convert.ToDecimal(Console.ReadLine());
}
catch (System.FormatException)
{
Console.WriteLine("Error for 1st dessert price. Input string was not in a correct format.");
Console.WriteLine("How much did your second dessert cost?");
try
{
dessertTwo = Convert.ToDecimal(Console.ReadLine());
}
catch (System.FormatException)
{
Console.WriteLine("Error for 2nd dessert price. Input string was not in a correct format.");
subtotal = mealOne + mealTwo + dessertOne + dessertTwo;
tip = subtotal * TIP_PERCENTAGE;
tax = subtotal * TAX_RATE;
total = subtotal + tax + tip;
totalPerPerson = total / numPeople;
Console.WriteLine("Subtotal: " + "$" + "{0:0.00}", subtotal);
Console.WriteLine("Tax: " + "$" + "{0:0.00}", tax);
Console.WriteLine("Tip: " + "$" + "{0:0.00}", tip);
Console.WriteLine("Total: " + "$" + "{0:0.00}", total);
Console.WriteLine("Per Person: " + "$" + "{0:0.00}", totalPerPerson);
}
}
}
}
}
}
}
This answer summarizes what everyone mentioned in the comments - the best way to handle exceptions is to avoid them (which is a bit facetious - but true here).
Exceptions should be used for exceptional circumstances, and particularly when you need to bubble an error state up through a deep stack. Users fat-fingering a number is hardly exceptional; it's something to be expected.
As #DiplomacyNotWar pointed it, it makes sense to push all the UI into a separate function. That way, you can re-prompt if the user makes an error (again, that's something to be expected). You could also put validation in there (for example, optionally specifying min and max values (I didn't do that).
So, here's a function that prompts users for a decimal value, and doesn't let them go further until they enter a valid number (if they really want to quit, they can press <Ctrl>+C)
private static decimal PromptForDecimal(string prompt, string? onError = null)
{
if (onError == null)
{
onError = $"You must enter a valid decimal value: {prompt}";
}
Console.Write($"{prompt}: ");
while (true)
{
var response = Console.ReadLine();
if (decimal.TryParse(response, out decimal value))
{
return value;
}
//otherwise:
Console.Write($"{onError}: ");
}
}
Note that you can optionally have a separate prompt that shows up if there's an error. Otherwise, you get a canned version based on the original prompt. It's up to you what you want to do.
Also note that the string? onError = null parameter expression describes onError as a Nullable String. You don't need the question mark if you aren't using Nullable Reference Types
With that in place, your code gets a whole lot simpler:
const decimal TIP_PERCENTAGE = 0.2m;
const decimal TAX_RATE = 0.07m;
decimal numPeople = 2.0m;
var mealOne = PromptForDecimal("How much did your first meal cost?");
var mealTwo = PromptForDecimal("How much did your second meal cost?");
var dessertOne = PromptForDecimal("How much did your first dessert cost?");
var dessertTwo = PromptForDecimal("How much did your second dessert cost?");
var subtotal = mealOne + mealTwo + dessertOne + dessertTwo;
var tip = subtotal * TIP_PERCENTAGE;
var tax = subtotal * TAX_RATE;
var total = subtotal + tax + tip;
var totalPerPerson = total / numPeople;
Console.WriteLine($"Subtotal: {subtotal:0.00}");
Console.WriteLine($"Tax: {tax:0.00}");
Console.WriteLine($"Tip: {tip:0.00}");
Console.WriteLine($"Total: {total:0.00}");
Console.WriteLine($"Per Person: {totalPerPerson:0.00}");
Note that I removed all your variable declarations from the top, and put them where they are used. It makes the code easier to read. Don't worry, var in these declarations means decimal since PromptForDecimal returns a decimal value.
If you do want to pre-declare your variables, consider not initializing them. If you had left all your declarations (of mealOne, dessertTwo, tip, etc.) uninitialized, and you tried to use them before they had values, the compiler would alert your. If you forgot to use one of them, the editor would put a squiggly line under the variable name (try it out).
Finally, an expression like $"Subtotal: {subtotal:0.00}" is known as an Interpolated String. They make your code easier to read.
I have a problem with my unit converter app. I`m trying to prevent users from using any other characters than numbers but I need to allowed them to use "." How can I do this?
I spend like 2 days on that with no luck. Please help. Here is my code.
public string[] YardsToMeters(string yards)
{
if(yards == null || yards.Contains(" "))
{
string[] str = new string[1];
str[0] = "Please enter some values";
return str;
}
Here I`m checking for allowed characters:
else if((Regex.IsMatch(yards, #"^\d+$") == true) || (yards.Contains(".") && yards[0] != '.'
|| (yards.Contains('\n')) && (Regex.IsMatch(yards, #"^\d+$") == true) && !yards.Contains(".")))
{
if (!yards.Contains('\n') && Regex.IsMatch(yards, #"^\d+$") == true)
{
double d = double.Parse(yards, CultureInfo.InvariantCulture) * 0.9144f;
string[] array = new string[1];
array[0] = d.ToString();
return array;
}
else if(Regex.IsMatch(yards, #"^\d+$") == true || yards.Contains(".") && yards[0] != '.')
{
double[] doubles = new double[yards.Split("\r\n").Count()];
for (int i = 0; i < yards.Split("\r\n").Count(); i++)
{
if (yards.Contains("."))
{
double value = Convert.ToDouble(yards.Split("\r\n")[i].Replace('.',','));
doubles[i] += value;
string.Format("{0}", value * 0.9144f);
}
else
{
double value = Convert.ToDouble(yards.Split("\r\n")[i]);
doubles[i] += value;
string.Format("{0}", value * 0.9144f);
}
}
string[] strings = new string[doubles.Length];
for (int i = 0; i < yards.Split('\n').Length; i++)
{
strings[i] = string.Format("{0}", doubles[i] * 0.9144f);
}
return strings;
}
else
{
string[] str = new string[1];
str[0] = "Please use numbers only!";
return str;
}
}
else
{
string[] str = new string[1];
str[0] = "Please use numbers only! Enter is also not allowed";
return str;
}
}
Please help me with that.
I think you've reached a point where you've lost sight of the goal and you've just been endlessly modifying and tweaking a bad solution to try and cover all the cases where it falls down
Yards to Metres -> Multiply yards by 0.9144f
public double YardsToMetres(double yards){ //not sure why you're using string everywhere
return yards * 0.9144f;
}
public void YardsTextbox_TextChanged(object sender, EventArgs e){
try{
double y = double.Parse(_yardsTextbox.Text);
MessageBox.Show("In metres:" + YardsToMetres(y));
} catch(FormatException ex){
MessageBox.Show("The value you entered (" + _yardsTextbox.Text + ") cannot be converted to a number. Enter a number");
}
}
This is an example, knowing nothing about your UI.. It's a recommendation that you split off the conversion code from the rest of the code. It should take a number and return a number (don't make everything string just because the input/output supply/require it).
Your input routine that collects data from the user should parse their input into a number ready for the converter. If it fails to parse, ask them to correct it. Don't get too deep and meaningful/complex over this - just try to parse it, and if it fails, tell the user it failed - they'll work out what they did wrong. You can do SOME limited amount of help, like trimming whitespace off the start if you want (actually double.parse ignores whitespace so it's unnecessary) but i'd perhaps stop short of stripping out all non numbers etc, because youre then doing large amount of manipulation of th data the user entered, doing calcs on it and the user has no idea (unless you tell them) what data you ended up doing your calcs on.
If they write 0xFF80, and expect their hex number (equivalent of 65,408) to be converted to mtres, they might be surprised if you've stripped out the xFF, and then done the calc on 80
Similarly, double parse can be made to be sensitive to different cultures. Some people write a 1,234.5 as 1.234,5. If you decide to strip out commas because theyre thousand separators, you end up ruining someone's decimal number if they use comma as the decimal separator. Consider carefully how deep you want to get into checking and helping the user form a number correctly; you're better to just try and work with what they gave you and if it failed, tell them
I wrote a basic number guessing game from C#. It seems to return the 3rd option ("Wrong choice! Please try again.") every time no matter what var c is chosen by the user. I was trying with characters (s instead of 1 and w instead of 2 etc with c as a string) but it gave the same results. Not sure where it's going bad.
using System;
namespace Challanges
{
class Program
{
static int guess = 500;
static int low = 1;
static int high = 1000;
static bool cont = false;
static void Guess() //guesses and adjusts variables according to input.
{
int c;
Console.WriteLine("Is your number greater or less than: " + guess + Environment.NewLine + "If it is less than, press 1; if it is greater, press 2." + Environment.NewLine + "If it is your number, press 3.");
c = Convert.ToInt32(Console.Read());
if (c == 1)
{
high = 500;
guess = low + high / 2;
}
else if (c == 2)
{
low = 500;
guess = low + high / 2;
}
else if (c == 3)
{
Console.WriteLine("Congratulations!! We found your number!");
cont = true;
}
else
{
Console.WriteLine("Wrong choice! Please try again.");
Console.ReadKey();
}
}
static void Main(string[] args)
{
Console.WriteLine("Hello World!" + Environment.NewLine + "Let's play a guessing game. Think of a number between 1 and 1000." + Environment.NewLine + "Type your number :)");
int x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Your number is: " + x + Environment.NewLine + "Too easy?");
Console.ReadKey();
Console.WriteLine("Think of a number");
if(cont == false)
{
Guess();
} else
{
Console.ReadKey();
}
}
}
}
As mentioned in the comments before, Console.Read() returns a character code. The character code for the number 1 is 49, thus your conditions fail and the else block is executed.
What you wanted to do was use Console.ReadLine()which returns a string instead of character codes. If you cast that string into an Int32 you should be able to evaluate your conditions correctly.
This question already has answers here:
Split - Index was outside the bounds of the array
(7 answers)
Closed 4 years ago.
This code should basically split the user input into its component letters and then output the 1st, 3rd and 5th letter in the array
bool greater = false;
Console.WriteLine("Enter your name: ");
string userName3 = Console.ReadLine();
while (greater = false)
{
if (userName3.Length >= 5)
{
greater = true;
}
else
{
Console.WriteLine("The name must be 5 characters or more");
}
}
string[] userNameArr = userName3.Split();
Console.WriteLine(userNameArr[0] + " " + userNameArr[2] + " " + userNameArr[4]);
When I run the last line causes an error saying
Index was outside the bounds of the array
Why is this and how can I fix it?
Split() doesn't split into char it splits by detecting and spliting by WhiteSpace characters into a array of strings.
If you want to get the characters, access the input string by index char firstChar = userName3[0];
Console.WriteLine(userName3[0] + " " + userName3[2] + " " + userName3[4]);
instead of
string[] userNameArr = userName3.Split();
Console.WriteLine(userNameArr[0] + " " + userNameArr[2] + " " + userNameArr[4]);
Sidenote:
replace while (greater = false) with while (!greater) or while (greater == false) since you want to do a comparison instead of a assingment
This should work:
bool greater = false;
while (greater == false)
{
Console.WriteLine("Enter your name: ");
string userName3 = Console.ReadLine();
if (userName3.Length >= 5)
{
greater = true;
}
else
{
Console.WriteLine("The name must be 5 characters or more");
}
}
string[] userNameArr = userName3.Split();
Console.WriteLine(userNameArr[0] + " " + userNameArr[2] + " " + userNameArr[4]);
The line:
while (greater = false)
Actually assigns false to greater, meaning you will never leave the loop. Further, you need the ReadLine inside the loop so that the user will be prompted again
String is array of char, so to get specific character use indexing instead of split()
for e.g. To get 5 letter from string use userNameArr[4].
This can be correct way to read characters from string
using System;
public class Program
{
public static void Main()
{
bool greater = false;
Console.WriteLine("Enter your name: ");
string userName3 = Console.ReadLine();
while (greater == false)
{
if (userName3.Length >= 5)
{
greater = true;
}
else
{
Console.WriteLine("The name must be 5 characters or more");
}
}
//Indexing to string is used to get letters from string
Console.WriteLine(userName3[0] + " " + userName3[2] + " " + userName3[4]);
}
}
Implemenation: DotNetFiddler
userName3.Split() splits the user name on spaces by default, so if username is phuzi then splitting will result in an array with a single item ["phuzi"] then only userNameArr[0] is valid. Any attempt to acces anything else will result in the error you're seeing
This is happening because the array does not contain this index.
The line
string[] userNameArr = userName3.Split();
You want to split by what ?
I want the program to get all of the elem1-elem7 info, add it together, and put it into the totalElem variable. That part works fine.
The part I'm stuck on, is that I want to take that number (lets say 30 for example), and put it on the end of a decimal to use it as a multiplier. Therefore 30 would become 1.30.
The error I'm getting is:
Cannot implicitly convert type 'string' to 'decimal'.
Please note, that is not where the variable definitions really are in the code. I just put them there so I didn't have to post my whole program.
private void calculateButton_Click(object sender, EventArgs e)
{
int startingSheetDPS;
int chd;
int skill;
int elem7;
int elem6;
int elem5;
int elem4;
int elem3;
int elem2;
int elem1;
int totalElem;
decimal elemMultiplier;
decimal baseMultiplier;
elem1 = Convert.ToInt32(ele1.Text);
elem2 = Convert.ToInt32(ele2.Text);
elem3 = Convert.ToInt32(ele3.Text);
elem4 = Convert.ToInt32(ele4.Text);
elem5 = Convert.ToInt32(ele5.Text);
elem6 = Convert.ToInt32(ele6.Text);
elem7 = Convert.ToInt32(ele7.Text);
chd = Convert.ToInt32(chd1.Text);
skill = Convert.ToInt32(skill1.Text);
totalElem = elem1 + elem2 + elem3 + elem4 + elem5 + elem6 + elem7;
elemMultiplier = 1 + "." + totalElem;
}
In short, I want to be able to turn elemMultiplier into a decimal variable, containing 1.totalElem.
Ok, a really dirty and fast way, replace your
elemMultiplier = 1 + "." + totalElem;
with
elemMultiplier = decimal.Parse("1." + totalElem);
Be ware, this is locale-dependant.
Use this:
String elemMul = "1." + totalElem.ToString();
elemMultiplier = Convert.ToDecimal(elemMul);
Your code shows problem because "." is a string which cannot be converted to decimal implicitly.
Don't concatenate strings. Just do the math:
elemMultiplier =
Convert.ToDecimal(1 + (totalElem / Math.Pow(10, totalElem.ToString().Length)));
(Edited after Gusman noticed a problem.)