Convert string array value to int when empty string value is possible - c#

I am having trouble converting a value in a string array to int since the value could possibly be null.
StreamReader reader = File.OpenText(filePath);
string currentLine = reader.ReadLine();
string[] splitLine = currentLine.Split(new char[] { '|' });
object.intValue = Convert.ToInt32(splitLine[10]);
This works great except for when splitLine[10] is null.
An error is thrown: `System.FormatException: Input string was not in a correct format.
Can someone provide me with some advice as to what the best approach in handling this would be?

Don't use convert, it is better to use
int.TryParse()
e.g.
int val = 0;
if (int.TryParse(splitLine[10], out val))
obj.intValue = val;

You can use a TryParse method:
int value;
if(Int32.TryParse(splitLine[10], out value))
{
object.intValue = value;
}
else
{
// Do something with incorrect parse value
}

if (splitLine[10] != null)
object.intValue = Convert.ToInt32(splitLine[10]);
else
//do something else, if you want
You might also want to check that splitLine.Length > 10 before getting splitLine[10].
If you're reading something like a CSV file, and there's a chance it could be somewhat complicated, such as reading multiple values, it probably will make sense for you to use a connection string or other library-sorta-thing to read your file. Get example connection strings from http://www.connectionstrings.com/textfile, using Delimited(|) to specify your delimiter, and then use them like using (var conn = new OleDbConnection(connectionString)). See the section in http://www.codeproject.com/Articles/27802/Using-OleDb-to-Import-Text-Files-tab-CSV-custom about using the Jet engine.

I would go with
object.intValue = int.Parse(splitLine[10] ?? "<int value you want>");

if you're looking for the least code to write, try
object.intValue = Convert.ToInt32(splitLine[10] ?? "0");
If you want to preserve the meaning of the null in splitLine[10], then you will need to change the type of intValue to be of type Nullable<Int32>, and then you can assign null to it. That's going to represent a lot more work, but that is the best way to use null values with value types like integers, regardless of how you get them.

Related

CSVhelper any way to ignore "=" present in CSV

I have an application which generates CSV data. This application "helpfully" includes the Excel fix of using = as a preamble to quoted 0-filled numeric data, to prevent the Excel interpreter from eating the leading 0.
I want to use CSVHelper to read these records. However, when mapping to a number, CSVhelper reports an error for these values with the = prefix.
Other than search/replace to pull the "=" out, is there a way to tell CSVhelper to ignore the leading equals and process successfully? I see options for including = in the written output but not to allow them in the parse.
Here is an example record:
"XYZ INC","R1G202113","R2G",="202113","D-SRS PRO FLD SM/2",157.49,122.53,True,50,50,0.00,1,False,"N",4.00,6.00,8.00,6.00,""
Any hep with this is appreciated.
This is a guess, and there may be a much better way, but perhaps you could do something like this with your mapping:
public class MyData
{
//map the raw input to this field as a string
public string MappedIntField {get;set;}=null;
// use an integer property not mapped to any column to shadow the string, and lazy-convert to an integer the first time you read it.
public int ActualIntField
{
get {
if (MappingReady || string.IsNullOrEmpty(MappedIntField)) return _ActualIntField;
//clean up the extra = character.
if (MappedIntField[0] == '=') MappedIntField = MappedIntField.Substring(1);
int result;
if (int.TryParse(MappedIntField, out result))
{
_ActualIntField = result;
MappingReady = true;
return result;
}
return _ActualIntField;
}
set {
_ActualIntField = value;
MappingReady = true;
}
}
private int _AcutalIntField;
// We don't want to re-parse the string on every read, so also flag when this work is done. You could also use a nullable int? to do this.
private bool MappingReady = false;
}

Is it good practice to use ToString() to convert a number directly to a string?

Is it good practice to convert a number to a string directly using ToString()? Like this:
string numStr = 0.ToString();
Or should the number be entered into an int variable first and then use ToString() on that? Like this:
int num = 0;
string numStr = num.ToString();
Its a Good practice to store your numbers in a Variable and then using the ToString() See example at the end
ToString() accepts an over load like ToString(IFormatProvider provider) where you can specify culture-specific format information
Console.WriteLine(value.ToString(CultureInfo.InvariantCulture));
The Alternative to ToString() is to use Convert.ToString(Int value) the difference is that Convert also handles null values
var str = Convert.ToString(value);
var str1 = Convert.ToString(value,CultureInfo.InvariantCulture);
Is it good practice to convert a number to a string directly using
ToString()? Like this:
Example
1.ToString(); // Compiles fine
-1.ToString(); // Compile error, note you can surround it with parenthesis to get it to compile
when you say "string a = 0.ToString();"
----------------------^-----here you are already declaring that its a string so saying .ToString(); is redundant

C# - Input string was not in a correct format

I am working on a simple windows forms application that the user enters a string with delimiters and I parse the string and only get the variables out of the string.
So for example if the user enters:
2X + 5Y + z^3
I extract the values 2,5 and 3 from the "equation" and simply add them together.
This is how I get the integer values from a string.
int thirdValue
string temp;
temp = Regex.Match(variables[3], #"\d+").Value
thirdValue = int.Parse(temp);
variables is just an array of strings I use to store strings after parsing.
However, I get the following error when I run the application:
Input string was not in a correct format
Why i everyone moaning about this question and marking it down? it's incredibly easy to explain what is happening and the questioner was right to say it as he did. There is nothing wrong whatsoever.
Regex.Match(variables[3], #"\d+").Value
throws a Input string was not in a correct format.. FormatException if the string (here it's variables[3]) doesn't contain any numbers. It also does it if it can't access variables[3] within the memory stack of an Array when running as a service. I SUSPECT THIS IS A BUG The error is that the .Value is empty and the .Match failed.
Now quite honestly this is a feature masquerading as a bug if you ask me, but it's meant to be a design feature. The right way (IMHO) to have done this method would be to return a blank string. But they don't they throw a FormatException. Go figure. It is for this reason you were advised by astef to not even bother with Regex because it throws exceptions and is confusing. But he got marked down too!
The way round it is to use this simple additional method they also made
if (Regex.IsMatch(variables[3], #"\d+")){
temp = Regex.Match(variables[3], #"\d+").Value
}
If this still doesn't work for you you cannot use Regex for this. I have seen in a c# service that this doesn't work and throws incorrect errors. So I had to stop using Regex
I prefer simple and lightweight solutions without Regex:
static class Program
{
static void Main()
{
Console.WriteLine("2X + 65Y + z^3".GetNumbersFromString().Sum());
Console.ReadLine();
}
static IEnumerable<int> GetNumbersFromString(this string input)
{
StringBuilder number = new StringBuilder();
foreach (char ch in input)
{
if (char.IsDigit(ch))
number.Append(ch);
else if (number.Length > 0)
{
yield return int.Parse(number.ToString());
number.Clear();
}
}
yield return int.Parse(number.ToString());
}
}
you can change the string to char array and check if its a digit and count them up.
string temp = textBox1.Text;
char[] arra = temp.ToCharArray();
int total = 0;
foreach (char t in arra)
{
if (char.IsDigit(t))
{
total += int.Parse(t + "");
}
}
textBox1.Text = total.ToString();
This should solve your problem:
string temp;
temp = Regex.Matches(textBox1.Text, #"\d+", RegexOptions.IgnoreCase)[2].Value;
int thirdValue = int.Parse(temp);

Read content as integer of empty XML element

I encountered a problem while parsing XML in C# with XMLReader.
Here is an example:
string text = xNode.ReadElementContentAsString().Length > 0 ? xBonusesNode.ReadElementContentAsString() : null;
int nmb = xNode.ReadElementContentAsInt();
So, where I'm trying to get string value there is simple inline if statement to check if element has data or not.
How can I do something similar with integer? Or how to catch exception correctly and in best way, for this?
You can use int.TryParse like this:
int number;
bool result = Int32.TryParse(xNode.ReadElementContentAsString, out number);
string text = xNode.ReadElementContentAsString().Length > 0 ? xBonusesNode.ReadElementContentAsString() : null;
Int32.TryParse(text,out myInt);
Should work.
I'm not sure whether the xml library supports nullable types (int?) but the above should work anyway - basically I'm reading it as a string then trying to parse it. If TryParse fails myInt will remain as it was before (and tryParse returns 'false')

Trouble formatting string from DataTable

I'm saving a numeric value into a datatable cell (no datatype for the cell has been explicitly declared), then later retrieving that data and trying to format it into a string. Problem is that nothing I've tried will properly format the string.
50000 --> 50,000
I've tried (where r is the row in a loop):
String.Format("{0:0,0}", r["columnName"])
r["columnName"].ToString("n0")
And several variations without any luck. Most of the time I just get the number without the comma.
String.Format("{0:0,0}",int.Parse(r["columnName"].ToString()))
Probably not the most elegant solution, but you could just iterate backwards from the tail-end of the string (or from the decimal point) adding a comma every three characters until you run out.
It might be helpful to have more context for what you're trying to do, but here is an example of getting a value out of a DataTable and then formatting it as desired.
DataTable dt = new DataTable();
dt.Columns.Add( "cellName", typeof( double ) );
dt.Rows.Add( 123.45 );
string val = ( (double)dt.Rows[0]["cellName"] ).ToString( "N" ); // val = "123.45"
I'm explicitly casting the value back to a double before calling ToString. You could also call string.Format on that value instead of ToString and it should work just as well.
EDIT: If you're storing the value as a string and then want to format it, use this:
string val = ( double.Parse( dt.Rows[0]["cellName"] ) ).ToString( "N" );
This does assume that the value is parsable though (i.e. isn't null).
The problem with these methods is that depending on the structure of the underlying table that field may be null. If you try to cast a null value held as an object (in the DataTable) to string,integer, decimal, or what have you... your app will blow up 100% of the time. Unless your DataSet is a strongly typed data set you will always want to do this error checking. As a matter of fact, writing a small data reading class to read string, decimals, date times, integers, whatever... is a must in any Data access operations having to do with Database....
So here is more error proof approach which idealy should be wrapped in a helper method as shown here:
public static string GetFormatedDecimalString(DataRow row, string columnName, string format)
{
string ColumnNameStringValue = String.Empty;
decimal ColumnNameValue = Decimal.Zero;
if( row[columnName) == DBNull.Value )
{
ColumnNameValue = Decimal.Zero;
}
else
{
ColumnNameStringValue = row[columnName].ToString();
if( ! Decimal.TryParse(ColumnNameStringValue, out ColumnNameValue )
{
ColumnNameValue = Decimal.Zero;
}
// if the if statement evaluated to false the ColumnNameValue will have the right
// number you are looking for.
}
return ColumnNameValue.ToString(format);
}
passing "N" or "{0:0,0}" as the format string will work just fine.

Categories