Why am I getting FormatException on this? - c#

I am trying to convert a System.string to a System.double, the input is: He: 4.002602 amu
Code:
string[] data = line.Replace(" ", "").Replace("amu", "").Split(new char[] { ':' });
double i = Convert.ToDouble(data[1]);
I have tried:
string[] data = line.Replace(" ", "").Replace("amu", "").Split(new char[] { ':' });
double i = Convert.ToDouble(data[1], CultureInfo.InvariantCulture);

You can use following regular expression without splitting a string which mixed with number and words:
// using System.Text.RegularExpressions
var resultString = Regex.Match(line, #"\d.\d+").Value;

If format of input is something+blank+doubleNumber+blank+something you can use following code:
string line = "He: 4.002602 amu";
int intLspacePos = line.IndexOf(" ") + 1;
int intRspacePos = line.LastIndexOf(" ");
string strNumber = line.Substring(intLspacePos, intRspacePos - intLspacePos);
double dblNumber = Convert.ToDouble(strNumber);

Instead of Convert.ToDouble() use the double.Parse() method, preferably using the invariant culture when the user input is always using a period sign as decimal separator.
So try something like this:
double i = double.Parse(data[1], CultureInfo.InvariantCulture);
EDIT:
I've seen in the screenshot you posted in the comments above that you're not actually checking the contents of data[1] before passing it to the Convert.ToDouble method.
According to MSDN the only case when a FormatException is thrown should be when providing a non-numeric text value (see here). Therefor I'd suggest to add a check for empty strings and null values before, passing the value to the Convert.ToDouble() method. Try updating your code to something like this:
foreach (string line in raw) {
string[] data = line.Replace(" ", "").Replace("amu", "").Split(new char[] { ':' });
if (!string.IsNullOrWhiteSpace(data[1]) {
double i = Convert.ToDouble(data[1], CultureInfo.InvariantCulture);
} else {
// Invalid value in data[1]
// Maybe set a breakpoint here and investigate further if necessary
}
}
If this still throws a FormatException then the contents of data[1] must be some non-numeric and non-empty text value, so in that case you should probably check the contents of the data array using the debugger and find out how / why that invalid value got there.

you can convert with specific culture info as below. 2057 is LCID for English (UK).
double i = Convert.ToDouble(data[1], CultureInfo.GetCultureInfo(2057));

Related

Remove substring if exists

I have 3 possible input cases
string input = ""; // expected result: ""
string input = "bar-foo"; // expected result: "foo"
string input = "foo"; // expected result: "foo"
And I have to remove everyting including the first separator char - if exists.
Working approach:
string output = input.Split('-').LastOrDefault();
I want to solve this without Split() - my NOT working approach:
string output = input.Substring(input.IndexOf('-') );
How can I handle the IndexOutOfRangeException / make this code work?
Try to add 1:
string output = input.Substring(input.LastIndexOf('-') + 1);
If there's no - in the input, LastIndexOf returns -1 and so you'll have the entire string.
I've assumed that your are looking for input's suffix, that's why I've put LastIndexOf:
"123-456-789" -> "789"
If you want to cut off the prefix:
"123-456-789" -> "456-789"
please, change LastIndexOf into IndexOf
i think you should use Contains Method to identify - is available or not.
string a = "";
if (a.Contains("-"))
{
string output = input.Substring(input.LastIndexOf('-') + 1);
}
Why not just remove it from the string without checking:
input = input.Replace("-foo", string.Empty);

Extract string parts that are separated with commas

I need to extract a string into 3 different variables.
The input from the user will be in this format 13,G,true.
I want to store the number in an integer, the "G" in a character and "true" into a string.
But I don't know how to specify the comma location so the characters before or after the comma can be stored in another variable.
I'm not allowed to use the LastIndexOf method.
string msg = "13,G,true";
var myArray = msg.Split(",");
// parse the elements
int number;
if (!Int32.TryParse(myArray[0], out number) throw new ArgumentException("Whrong input format for number");
string letter = myArray[1];
string b = myArry[2];
// or also with a boolean instead
bool b;
if (!Int32.TryParse(myArray[2], out b) throw new ArgumentException("Whrong input format for boolean");
use String.Split
string str='13,G,true';
string[] strArr=str.Split(',');
int32 n=0,intres=0;
char[] charres = new char[1];
string strres="";
if(!Int32.TryParse(strArr[0], out n))
{
intres=n;
}
if(strArr[0].length>0)
{
charres[0]=(strArr[1].toString())[0];
}
strres=strArr[2];
//you'll get 13 in strArr[0]
//you'll get Gin strArr[1]
//you'll get true in strArr[2]
var tokens = str.Split(","); //Splits to string[] by comma
var first = int32.Parse(tokens[0]); //Converts first string to int
var second = tokens[1][0]; //Gets first char of the second string
var third = tokens[2];
But be aware, that you also need to validate the input
You are going to need method String.Split('char'). This method splits string using specified char.
string str = "13,G,true";
var arrayOfStrings=str.Split(',');
int number = int.Parse(arrayOfStrings[0]);
// original input
string line = "13,G,true";
// splitting the string based on a character. this gives us
// ["13", "G", "true"]
string[] split = line.Split(',');
// now we parse them based on their type
int a = int.Parse(split[0]);
char b = split[1][0];
string c = split[2];
If what you are parsing is CSV data, I would check out CSV parsing libraries related to your language. For C#, Nuget.org has a few good ones.

Insert spaces into string using string.format

I've been using C# String.Format for formatting numbers before like this (in this example I simply want to insert a space):
String.Format("{0:### ###}", 123456);
output:
"123 456"
In this particular case, the number is a string. My first thought was to simply parse it to a number, but it makes no sense in the context, and there must be a prettier way.
Following does not work, as ## looks for numbers
String.Format("{0:### ###}", "123456");
output:
"123456"
What is the string equivalent to # when formatting? The awesomeness of String.Format is still fairly new to me.
You have to parse the string to a number first.
int number = int.Parse("123456");
String.Format("{0:### ###}", number);
of course you could also use string methods but that's not as reliable and less safe:
string strNumber = "123456";
String.Format("{0} {1}", strNumber.Remove(3), strNumber.Substring(3));
As Heinzi pointed out, you can not have format specifier for string arguments.
So, instead of String.Format, you may use following:
string myNum="123456";
myNum=myNum.Insert(3," ");
Not very beautiful, and the extra work might outweigh the gains, but if the input is a string on that format, you could do:
var str = "123456";
var result = String.Format("{0} {1}", str.Substring(0,3), str.Substring(3));
string is not a IFormattable
Console.WriteLine("123456" is IFormattable); // False
Console.WriteLine(21321 is IFormattable); // True
No point to supply a format if the argument is not IFormattable only way is to convert your string to int or long
We're doing string manipulation, so we could always use a regex.
Adapted slightly from here:
class MyClass
{
static void Main(string[] args)
{
string sInput, sRegex;
// The string to search.
sInput = "123456789";
// The regular expression.
sRegex = "[0-9][0-9][0-9]";
Regex r = new Regex(sRegex);
MyClass c = new MyClass();
// Assign the replace method to the MatchEvaluator delegate.
MatchEvaluator myEvaluator = new MatchEvaluator(c.ReplaceNums);
// Replace matched characters using the delegate method.
sInput = r.Replace(sInput, myEvaluator);
// Write out the modified string.
Console.WriteLine(sInput);
}
public string ReplaceNums(Match m)
// Replace each Regex match with match + " "
{
return m.ToString()+" ";
}
}
How's that?
It's been ages since I used C# and I can't test, but this may work as a one-liner which may be "neater" if you only need it once:
sInput = Regex("[0-9][0-9][0-9]").Replace(sInput,MatchEvaluator(Match m => m.ToString()+" "));
There is no way to do what you want unless you parse the string first.
Based on your comments, you only really need a simple formatting so you are better off just implementing a small helper method and thats it. (IMHO it's not really a good idea to parse the string if it isn't logically a number; you can't really be sure that in the future the input string might not be a number at all.
I'd go for something similar to:
public static string Group(this string s, int groupSize = 3, char groupSeparator = ' ')
{
var formattedIdentifierBuilder = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
if (i != 0 && (s.Length - i) % groupSize == 0)
{
formattedIdentifierBuilder.Append(groupSeparator);
}
formattedIdentifierBuilder.Append(s[i]);
}
return formattedIdentifierBuilder.ToString();
}
EDIT: Generalized to generic grouping size and group separator.
The problem is that # is a Digit placeholder and it is specific to numeric formatting only. Hence, you can't use this on strings.
Either parse the string to a numeric, so the formatting rules apply, or use other methods to split the string in two.
string.Format("{0:### ###}", int.Parse("123456"));

Convert string value to decimal with thousand separator?

This might be a very simple question.
Suppose text box show value 10,000.12 when user edits data by mistake he remove first two numbers like ,000.12 and using this textbox in the calculation then it gives an exception. I want a just validate text box.
For Example:
string str = ",100.12;"
Convert to
decimal number = 100.12;
Any Idea?.
It shows only whole number when user remove any thousand separator.
This is pretty messed up and I am not sure if all of you strings will look the same, but in case they do this might do the trick:
string str = ",0,100.12";
decimal number;
bool converted = decimal.TryParse(str.Substring(str.LastIndexOf(",") + 1), out number);
The variable converted will tell you whether or not your string was converted and you will not an exception.
Good luck!
If I understood the question, you want to remove all characters that would prevent the parse routine from failing.
string str = ",0,100.12";
var modified = new StringBuilder();
foreach (char c in str)
{
if (Char.IsDigit(c) || c == '.')
modified.Append(c);
}
decimal number= decimal.Parse(modified.ToString());
string a = "100.12";
decimal b = Convert.ToDecimal(a);
string str = ",0,100.12;";
var newstr = Regex.Replace(str,#"[^\d\.]+","");
decimal d = decimal.Parse(newstr, CultureInfo.InvariantCulture);

Can't double.Parse string

I have a problem with parsing a string to a double. I have a StreamWriter reading lines from a text file. The text file has the following lines:
17-09-2012: (100,98)
17-09-2012: (50,57)
Now, I want to use the values from inside the parantheses, add them together and display them in a textbox. So far I have the following:
int counter = 0;
double res = 0;
string line;
System.IO.StreamReader file = new System.IO.StreamReader("d:\\test.txt");
while ((line = file.ReadLine()) != null)
{
string par = Regex.Match(line, #"\(([^)]*)\)").Value;
double par2 = double.Parse(par);
res += par2;
counter++;
}
file.Close();
textBox1.Text = res.ToString();
However, apparently the input string is not in a correct format, which I find rather odd, since the regex should remove everything but the numbers inside the parantheses. I have even checked for this by writing the string to the textbox without first adding them together, and it showed "100,9850,57". So truly, I do not understand, why it cannot convert the string to a double.
I hope you can tell me, what I am doing wrong.
Your "par" variable is containing a string that looks like: "(100,98)" which is why it's failing to parse.
change your regex to (?<=\()(([^)]*))(?=\))
You can try with - based on InvariantCulture
var culture = CultureInfo.InvariantCulture;
double result = double.Parse(par , culture);
Setting your regex to (?<=\()(([^)]*))(?=\)) and using this helper should solve your problems:
public static double ParseDouble(string input)
{
// unify string (no spaces, only . )
string output = input.Trim().Replace(" ", "").Replace(",", ".");
// split it on points
string[] split = output.Split('.');
if (split.Count() > 1)
{
// take all parts except last
output = String.Join("", split.Take(split.Count() - 1).ToArray());
// combine token parts with last part
output = String.Format("{0}.{1}", output, split.Last());
}
// parse double invariant
double d = Double.Parse(output, CultureInfo.InvariantCulture);
return d;
}
You can force double.Parse to use a culture that uses , as a decimal separator, like this:
CultureInfo culture = new CultureInfo("de-DE");
double d = double.Parse(par, culture);
That's a good idea anyway, if you want your program to work also on computers with different regional settings.
I made it work, by making a try, catch:
string par = Regex.Match(line, #"(?<=\()(([^)]*))(?=\))").Value;
try
{
double par2 = double.Parse(par);
res += par2;
}
catch
{
}
Thanks, everyone for your help.

Categories

Resources