Input string not in correct format exception c# - c#

I have read data from a text file. I want to change data in that file into an Int array. I don't know why it wrong.
class Program
{
public static int[,] provincial = new int[100, 100];
public static void loadProvincial()
{
string[] s = System.IO.File.ReadAllLines("C:\\Users\\Lyn203\\Desktop\\data\\final-graph.txt");
for (int i = 0; i < s.Length; ++i)
{
string[] splitedArray = s[i].Replace("\t","_").Split('_');
//Console.WriteLine(splitedArray[i]);
for (int j = 0; j < splitedArray.Length-1; ++j)
{
provincial[i,j] = int.Parse(splitedArray[j].ToString());
}
}
Console.ReadLine();
}
static void Main(string[] args)
{
loadProvincial();
}
}
and TextFile:
http://textuploader.com/djhbe

I suggest you to call the overload of Split that removes the empty entries. In other words, if you have two consecutive tabs without a value between the two tabs your result will contain an empty string. That string is not convertible by Int32.Parse
string[] splitedArray = s[i].Replace("\t","_")
.Split(new char[] {'_'},
StringSplitOptions.RemoveEmptyEntries);
Instead if you want to add a zero when your code meets an empty string then replace the Int32.Parse with Int32.TryParse. This will allow you to check the result of the conversion without getting an exception in case of a missing value
for(.....)
{
int value;
Int32.TryParse(splitedArray[j], out value);
// if conversion fails, value will be set to the default value for integers (0)
provincial[i,j] = value;
}

Related

How do I split my textfile into a 2d array with delimiters in c#?

My textfile contains contents such as:
1/1/2018;0;29;10
1/2/2018;0;16;1
1/3/2018;0;32;1
1/4/2018;0;34;15
1/5/2018;0;19;2
1/6/2018;0;21;2
Further down in the textfiles are decimals which is why I am trying to use double
1/29/2018;0.32;52;38
1/30/2018;0.06;44;21
I am trying to split up the semicolons and assign each value between the semicolons into a 2D array that contains 31 rows and 4 columns.
private void button1_Click(object sender, EventArgs e)
{
// 2d array
double[,] testarray = new double[31, 4];
string inputFile = File.ReadAllText("testywesty.txt");
char[] spearator = {';',' '};
for (int row = 0; row < 31; row++)
{
for (int column = 0; column < 4; column++)
{
string[] strlist = inputFile.Split(spearator);
testarray [row,column] = double.Parse(strlist[column]);
}
}
}
I believe that I have the right loop needed to insert my values into the 2d array, however, I am getting an error for my input and I believe it is because of the slashes.
Is my code sufficient for holding the text file's contents into my array? And how do I deal with the '/' characters?
You'd be getting an error on the slashes because you're trying to convert them to doubles, which is not possible. One thing you can do is first convert them to a DateTime using the Parse method of that class, and then use the ToOADate method to convert it to a double. Note that if you need to convert it back, you can use the DateTime.FromOADate method as I've done in the output below.
Also, it might be helpful to use File.ReadAllLines to read the file into an array of strings, where each string is a file line (this assumes that each line contains the four parts you need as you've shown in the sample file contents in the question). This way each line represents a row, and then we can split that line to get our columns.
For example:
private static void button1_Click(object sender, EventArgs e)
{
var lines = File.ReadAllLines("testywesty.txt");
var items = new double[lines.Length, 4];
var delims = new[] {';', ' '};
for (var line = 0; line < lines.Length; line++)
{
var parts = lines[line].Split(delims);
var maxParts = Math.Min(parts.Length, items.GetLength(1));
for (var part = 0; part < maxParts; part++)
{
if (part == 0)
{
// Parse first item to a date then use ToOADate to make it a double
items[line, part] = DateTime.Parse(parts[part]).ToOADate();
}
else
{
items[line, part] = double.Parse(parts[part]);
}
}
}
// Show the output
var output = new StringBuilder();
for (var row = 0; row < items.GetLength(0); row++)
{
var result = new List<string>();
for (var col = 0; col < items.GetLength(1); col++)
{
result.Add(col == 0
? DateTime.FromOADate(items[row, col]).ToShortDateString()
: items[row, col].ToString());
}
output.AppendLine(string.Join(", ", result));
}
MessageBox.Show(output.ToString(), "Results");
}
Output
Of course, you can read the data and parse it into an array. But since it is polymorphic the array needs to be of object[,] type. This is how I would approach this:
class Program
{
static void Main(string[] args)
{
object[,] array = ReadFileAsArray("testywesty.txt");
}
static object[,] ReadFileAsArray(string file)
{
// how long is the file?
// read it twice, once to count the rows
// and a second time to read each row in
int rows = 0;
var fs = File.OpenText(file);
while (!fs.EndOfStream)
{
fs.ReadLine();
rows++;
}
fs.Close();
var array = new object[rows, 4];
fs = File.OpenText(file);
int row = 0;
while (!fs.EndOfStream)
{
// read line
var line = fs.ReadLine();
// split line into string parts at every ';'
var parts = line.Split(';');
// if 1st part is date store in 1st column
if (DateTime.TryParse(parts[0], out DateTime date))
{
array[row, 0] = date;
}
// if 2nd part is flaot store in 2nd column
if (float.TryParse(parts[1], out float x))
{
array[row, 1] = x;
}
// if 3rd part is integer store in 3rd column
if (int.TryParse(parts[2], out int a))
{
array[row, 2] = a;
}
// if 4rd part is integer store in 4rd column
if (int.TryParse(parts[3], out int b))
{
array[row, 3] = b;
}
row++;
}
fs.Close();
return array;
}
}
But I feel this is clunky. If the data types represented by the file are predetermined than filling in a collection of a custom type feels more natural in C#, as you let the type handle its own data and parsing. Consider the example below:
class Program
{
static void Main(string[] args)
{
IEnumerable<MyData> list = ReadFileAsEnumerable("testywesty.txt");
Debug.WriteLine(MyData.ToHeading());
foreach (var item in list)
{
Debug.WriteLine(item);
}
// date x a b
// 1/1/2018 0 29 10
// 1/2/2018 0 16 1
// 1/3/2018 0 32 1
// 1/4/2018 0 34 15
// 1/5/2018 0 19 2
// 1/6/2018 0 21 2
// 1/29/2018 0.32 52 38
// 1/30/2018 0.06 44 21
}
public static IEnumerable<MyData> ReadFileAsEnumerable(string file)
{
var fs = File.OpenText(file);
while (!fs.EndOfStream)
{
yield return MyData.Parse(fs.ReadLine());
}
fs.Close();
}
}
/// <summary>
/// Stores a row of my data
/// </summary>
/// <remarks>
/// Mutable structures are evil. Make all properties read-only.
/// </remarks>
public struct MyData
{
public MyData(DateTime date, float number, int a, int b)
{
this.Date = date;
this.Number= number;
this.A=a;
this.B=b;
}
public DateTime Date { get; }
public float Number { get; }
public int A { get; }
public int B { get; }
public static MyData Parse(string line)
{
// split line into string parts at every ';'
var parts = line.Split(';');
// if 1st part is date store in 1st column
if (DateTime.TryParse(parts[0], out DateTime date)) { }
// if 2nd part is flaot store in 2nd column
if (float.TryParse(parts[1], out float number)) { }
// if 3rd part is integer store in 3rd column
if (int.TryParse(parts[2], out int a)) { }
// if 4rd part is integer store in 4rd column
if (int.TryParse(parts[3], out int b)) { }
return new MyData(
date,
number,
a,
b);
}
public static string ToHeading()
{
return $"{"date",-11} {"x",-4} {"a",-4} {"b",-4}";
}
public override string ToString()
{
return $"{Date.ToShortDateString(),-11} {Number,4} {A,4} {B,4}";
}
}

Cannot convert from void to bool when trying to use an array in my reverse function

Just as the heading states, I am trying to reverse a float array with my own reverse function.
The reverse function must not return a variable. The logic of the program may be off, so I am probably approaching this wrong.
Now the error I get is that it cannot convert from void to bool.
public static void reverse(float[] floatArr)
{
for (int i = 0; i < floatArr.Length; i++)
{
Console.WriteLine(floatArr[i]);
}
for (int i = 0; i < floatArr.Length / 2; i++)
{
float tmp = floatArr[i];
floatArr[i] = floatArr[floatArr.Length - i - 1];
floatArr[floatArr.Length - i - 1] = tmp;
}
}
static void Main(string[] args)
{
float[] floatArr = new float[5] { 5.6F, 6.4F, 4.2F, 3.6F, 8.4F };
Console.WriteLine(reverse(floatArr)); // cannot convert from void to bool
}
I know that I could fix this by having the reverse function be a float function and thus returning a float, but question stated that it must not return a value.
You are trying to print a function which returns type is void.
Console.WriteLine(reverse(floatArr)); // cannot convert from void to bool -> this is correct error
You should first call reverse(floatArr) and if the intention to print then you should loop on array to print the values. like as follows:
reverse(floatArr);
foreach(var val in floatArr)
{
Console.WriteLine(val);
}
This will print the values in different lines on console. If you want to print all values in one line then use the below line (credit to #LeonidVasilyev)
Console.WriteLine(string.Join(",", floatArr));

Write an array to a file in c#

I am trying to write an array to a file with C# and am having issues.
I've started learning c# the last few days and now can't figure out why this happens.
namespace Arrays
{
class Program
{
static void Sort()
{
}
public static void Random()
{
int[] test2 = new int[5];
int Min = 1;
int Max = 100;
Random randNum = new Random();
for (int i = 0; i < test2.Length; i++)
{
test2[i] = randNum.Next(Min, Max);
Console.WriteLine(test2[i]);
}
Console.WriteLine("");
for (int ii = 0; ii < test2.Length; ii++)
{
Array.Sort(test2);
Console.WriteLine(test2[ii]);
}
String writeToText = string.Format("{0}", test2);
System.IO.File.WriteAllText(#"C:\\Users\\hughesa3\\Desktop\\log.txt", writeToText); // Writes string to text file
}
static void Main(string[] args)
{
Random();
}
}
}
It generates a random 5 numbers and puts it into the array, When I try to write this to a file it prints System.Int32[]
I understand that because im trying to print a formated string but how would i go about printing each int ? I've tried using a loop but it will only save the last int as i put it inside the loop?
Can anyone give me some advice ?
Thanks
Use WriteAllLines and pass string array as input.
System.IO.File.WriteAllLines("filename", test2.Select(i=>i.ToString()).ToArray());
or, if you want to write in , separated form use this.
System.IO.File.WriteAllText("filename", string.Join(",", test2.Select(i=>i.ToString()).ToArray());
The problem is that String writeToText = string.Format("{0}", test2); calls ToString method of the test2 array and it returns System.Int32[]
Change it to
String writeToText = string.Join("", test2.Select(x=>x.ToString())
or
String writeToText = string.Format("{0}", test2.Select(x=>x.ToString().Aggregate((c,n)=>string.Format("{0}{1}", c,n))
//Add this method and use in System.IO.File.WriteAllText(#"C:\\Users\\hughesa3\\Desktop\\log.txt", ArrayToString(test2));
public static String ArrayToString(int[] arr)
{
return arr.Aggregate("", (current, num) => current + (num + " "));
}

Better way to update values in string[]

I am looking for a better way to update values in my List/Array:
My code is like -
String[] values = baseValue.Split(new []{'+'});
Because the 'values' can have decimal/string values - I want to update items in this list to remove any value after decimal -
for (int i = 0; i < values.Count(); i++)
{
decimal newvalue;
if (Decimal.TryParse(values[i], out newvalue))
{
values[i] = Decimal.ToInt32(newvalue).ToString();
}
}
Is there a better way to achieve above using Linq/without Linq ?
You could use string operations, instead of converting to decimal then to int and finally back to string.
string[] values = baseValue.Split('+');
for (int i = 0; i < values.Length; i++)
{
int pos = values[i].IndexOf('.');
if (pos >= 0) {
values[i] = values[i].Substring(0, pos);
}
}
Of cause no rounding occurs here.
String.Split has an overload with one argument params char[] separator. Because of the params keyword, you can specify as many characters as you want, without having to create an array explicitly.
string[] result = s.Split('x', 'y', 'z');
Use values.Length which is a property built into array types. values.Count() is a LINQ extension method, which enumerates all the array items and is therefore not efficient.
You could use an extension method:
public static void ConvertDecimalToInts(this string[] values)
{
for (int i = 0; i < values.Count(); i++)
{
decimal newvalue;
if (Decimal.TryParse(values[i], out newvalue))
{
values[i] = Decimal.ToInt32(newvalue).ToString();
}
}
}
And use it as so:
String[] values = baseValue.Split(new[] { '+' });
values.ConvertDecimalToInts();
Olivier's answer is probably better in that it doesn't require three conversions, but you can do this with Linq if you wish:
values = baseValue.Split('+')
.Select(v => Decimal.ToInt32(Decimal.Parse(v)).ToString());

How to implement C# code for Order id separated by commas and range separated by hyphens, and display all info of order

Ex: 1,4-90, 292,123
It needs to display the whole order information of
1
4,5,6....90
292
123.
Whats the gud approach to solve this.
It is similar to tracking in UPS or fedex if multiple orders are given in search box.
I meant if in a search box I giv 1,4-90, 292,123 this string the result that needs to come back is a grid representation of all the data which is corresponding to each of the order id respectively. I want to know how to parse the string into collection and send them to the database and show the information in the grid for...
1
4,5,6....90
292
123.
as a different row...from where I can generate reports too (alternative)
Please try.
static ArrayList list;
static void Main(string[] args)
{
string str = "1,4-90,292,123";
string[] arr = str.Split(',');
list = new ArrayList();
for (int i = 0; i < arr.Length; i++)
{
string tmp = arr[i];
if (tmp.IndexOf('-') != -1)
{
Range(tmp);
}
else list.Add(int.Parse(tmp));
}
list.Sort();
object[] intResult = list.ToArray();
//print the final result
for (int i = 0; i < intResult.Length; i++)
{
Console.WriteLine(intResult[i].ToString());
}
Console.Read();
}
static void Range(string range)
{
string[] tmpArr = range.Split('-');
int stInt = int.Parse(tmpArr[0]);
int edInt = int.Parse(tmpArr[1]);
int[] intArr = new int[(edInt - stInt) + 1];
for (int i = 0; stInt <= edInt; i++)
{
list.Add(stInt++);
}
}

Categories

Resources