This question already has answers here:
int.Parse, Input string was not in a correct format
(7 answers)
Closed last year.
So, today I was trying to make an app in which the user enters the coordinates of their car and the app calculates the easiest way to reach a gas station before the fuel tank runs out. But when I wanted to test if the app displays the data which is stored in a .txt file, I get a System.FormatException error which I cannot solve. I have used this method many many times before and I am not sure what is the problem here.
The error occurs at the line:
int xcoor = int.Parse(s.Substring(k + 1));
Code:
int n = 10;
string[] cities = new string[n];
int[] x = new int[n];
int[] y = new int[n];
System.IO.StreamReader sr = new System.IO.StreamReader(
#"..\..\CitiesGPS.txt", Encoding.GetEncoding(1250));
for (int i = 0; i < n; i++)
{
string s = sr.ReadLine();
int k = s.IndexOf(";");
string city = s.Substring(0, k);
cities[i] = city;
int xcoor = int.Parse(s.Substring(k + 1));
x[i] = xcoor;
int k2 = s.IndexOf(";");
int ycoor = int.Parse(s.Substring(k2 + 1));
y[i] = ycoor;
}
sr.Close();
Console.WriteLine("Data in the file:");
for (int i = 0; i < n; i++)
{
Console.WriteLine(cities[i] + ";" + x[i] + ";" + y[i]);
}
Data:
Nagyváros;150;30
Kisváros;250;300
TanyaBenzunkúttal;290;310
Szépváros;500;10
Alsóváros;250;0
Felsőváros;560;560
Középváros;300;300
FolyópartiVáros;380;400
HáromBenzinkutasváros;10;400
Nagyvárosbvezetőútja;380;230
Thanks in advance,
Blaise
You don't have any length on the middle Substring call, so it takes the rest of the line.
int xcoor = int.Parse(s.Substring(k + 1, /* missing length*/));
But, please use a CSV-parser. There is no reason to re-invent the wheel every time you need it.
EDIT
I just noticed you're getting the same index of ";" into both k and k2, so it won't work at all.
Again, use a CSV-parser.
EDIT 2
If you won't use a CSV-parser, here is a solution with Split as #ADyson suggests:
for (int i = 0; i < n; i++)
{
var parts = sr.ReadLine().Split(";");
string city = parts[0];
cities[i] = city;
int xcoor = int.Parse(parts[1]);
x[i] = xcoor;
int k2 = s.IndexOf(";");
int ycoor = int.Parse(parts[2]);
y[i] = ycoor;
}
Apart from the general advice to use a ready-made CSV / delmimited-file parser for this task, your own code is massively over-complicating the problem, and suffers from various logical flaws when trying to detect the location of the delimiters and calculate the correct lengths of the strings in between them.
It's much simpler to just use the String.Split method.
Also your onward data structure (consisting of separate arrays for cities, x coords and y coords) doesn't make much sense if you're intending to then match the co-ordinates to the location names - if you want to do that, keep the data together. A simple object structure would make it easier to work with later on. And lists are generally easier to work with than arrays, too.
Also for simplicity you should just read to the end of the file, not a specific number of lines.
Lastly, best practice with a disposable item like a StreamReader is to initialise it in conjunction with a using block to ensure it's properly disposed afterwards (see StreamReader documentation examples.
e.g.
public class LocationData
{
public string Name {get; set;}
public int X {get; set;}
public int Y {get; set;}
}
and then
using (System.IO.StreamReader sr = new new System.IO.StreamReader(#"..\..\CitiesGPS.txt", Encoding.GetEncoding(1250)))
{
List<LocationData> locationList = new List<LocationData>();
while ((s = sr.ReadLine()) != null)
{
string[] data = s.Split(';');
LocationData loc = new LocationData()
{
Name = data[0],
X = int.Parse(data[1]),
Y = int.Parse(data[2])
};
locationList.Add(loc);
}
}
foreach (LocationData loc in locationList)
{
Console.WriteLine(loc.Name + ";" + loc.X + ";" + loc.Y);
}
P.S. Super-simple demo of processing a single row using string.split: https://dotnetfiddle.net/vGXu2O
The fail is with the substring in the line
int xcoor = int.Parse(s.Substring(k + 1));
You are trying to parse to int the value 150;30. And obviously it can't be parsed as a number.
I recommend split every line by ; to get the values for each position.
You can do this inside for loop:
string[] line = s.Split(";");
var city = line[0];
var xcoor = int.Parse(line[1]);
var ycoor = int.Parse(line[2]);
cities[i] = city;
x[i] = xcoor;
y[i] = ycoor;
Edit to add how it works using substring().
Substring method takes two arguments:
1st: Is the position where start.
2nd: Is how many positions more do you want to get.
So, the solution is get the ondex of all ; (I've used a lambda expression) and then use substring in a correct way.
That is: Saying the program to start where a semicolon has been found and end as many position as there exists until the next semicolon.
var indexes = Regex.Matches(s, ";").Cast<Match>().Select(m => m.Index).ToList();
var city = s.Substring(0,indexes[0]);
var xcoor = s.Substring(indexes[0]+1,(indexes[1]-indexes[0])-1);
var ycoor = s.Substring(indexes[1]+1, (s.Length-indexes[1])-1);
cities[i] = city;
x[i] = int.Parse(xcoor);
y[i] = int.Parse(ycoor);
With this code, you can see the position where to start and 'cut' the substring.
Related
I got an idea that i wanted to make today but ran into the problem that i have a string variable with paragraph, but i need an Array of single lines. So I tried to do this with the String.Substring and the String.IndexOf functions but this only worked kinda because i dont exactly know how VisualStudio handels the Index of Paragraphs and how strings work with paragraphs because i just learned C# this year.
I tried it in Windows-Forms btw.
Can anyone tell me how index's with paragraphs work or especialy how to use them correctly.
This is the code i tried which only works for the 1st line and works kinda with the 2nd but not with any further
string input_raw;
string[] input = new string[100];
int index_zeile = 0;
int x = 0, y = 0;
input_raw = input_text_box.Text;
for (int i = 0; i < 100; i++)
{
if (i == 0)
{
y = input_raw.IndexOf(";");
input[i] = input_raw.Substring(index_zeile, y);
x = y + 1;
}
else
{
index_zeile = input_raw.IndexOf(";", x);
input[i] = input_raw.Substring(x, index_zeile-3);
x = x + index_zeile;
}
}
I wish you entered your text input, but you can split the string into an array. The following code assigns a multi-line string to an array.
string[] lines = input_text_box.Text.Split('\n');
I have a list of postal codes and the cities the codes are for in a text file. The data looks like this:
2450,København SV
2500,Valby
2600,Glostrup
2605,Brøndby
2610,Rødovre
2625,Vallensbæk
2630,Taastrup
2635,Ishøj
2640,Hedehusene
There are 580 lines of text there.
I started by converting the text to jagged array[][] but that's not really meeting my needs farther along in my code. So a simple array[,] is preferable.
Unfortunately I'm apparently too new in c# to be able to get there myself.
string testing = File.ReadAllText(#"U:\Testing.txt");
int i = 0, j = 0;
string[,] result = new string[580, 2];
foreach (var row in testing.Split('\n'))
{
j = 0;
foreach (var col in row.Trim().Split(','))
{
result[i, j] = col.Trim();
j++; //Line 26 - this is where I get the exception error
}
i++;
}
I can't figure out why I'm getting the following error and I've begun tearing out my hair. Any ideas??
System.IndexOutOfRangeException
HResult=0x80131508
Message=Index was outside the bounds of the array.
Source=Testing
StackTrace:
at Testing.Analysis.Main() in U:\Uddannelse\Testing\Testing\Program.cs:line 26
You are getting the error because somewhere in your file, some rows have a comma in the city name.
If you want to get the whole name, try something like this -
var row = "2450,København, SV"
var values = row.Split(new[] {','}, 2);
//With the extra int param to the Split function, you are saying no matter how many substrings you can form , only give me this specific number of substrings.
//With a value of 2, you are essentially splitting at the first instance of the comma.
This will give you two values, the first being "2450" and the second "København, SV"
This is assuming that every row has atleast a comma, if not, you'll need to put in a check for it as well.
You can try this that corrects the indexing.
static void Test()
{
var testing = File.ReadAllLines(#"c:\Testing.txt");
string[,] result = new string[testing.Length, 2];
int i = 0, j = 0;
foreach ( var line in testing )
{
j = 0;
foreach ( var col in line.Trim().Split(',') )
result[i, j++] = col.Trim();
i++;
}
for ( int index = result.GetLowerBound(0); index < result.GetUpperBound(0); index++ )
Console.WriteLine($"Code = {result[index, 0]}, Name = {result[index,1]}");
}
Here is one way you can approach this:
string file_path = "...";
//read all lines from the file
var lines = File.ReadAllLines(file_path);
//You could also use StreamReader to read the file in line by line
string[,] result = new string[lines.Length, 2];
string line;
char[] separator = new char[] { ',' };
//loop over the lines until the end of the file
for(int current_line = 0; current_line < lines.Length; current_line++)
{
//second argument limits you to two parts, so additional commas will not cause issues
var parts = line.Trim().Split(separator, 2);
//make sure the data was in your expected format (i.e. two parts)
if(parts.Length == 2)
{
result[current_line, 0] = parts[0];
result[current_line, 1] = parts[1];
}
}
Hi sorry guys I'm pretty new to C# and programming in general.
I have a text file that I'm reading from which contains 10 lines (all but the first of which are relevant).
I want to split each line (besides the first since it's only one word) by the commas, then retrieve the 5th one along of each line, adding it to a total.
Currently all I have been able to do is essentially split and add the same value to the total 10 times, instead of adding the 9 different values together, or face a "System.IndexOutOfRangeException".
int totalValues = 0;
string[] larray = lines.ToArray(); //create array from list
string vehicleValue;
for (int i = 0; i < larray.Length; i++)
{
string[] bits = larray[i].Split(',');
vehicleValue = bits[4];
int vvint = int.Parse(vehicleValue);
totalValues = totalValues + vvint;
}
totalValue.Text = totalValues.ToString();
As it stands, the above code results in a "System.IndexOutOfRangeException" highlighting "vehicleValue = bits [4];"
Every line of the file looks like this, besides the first one.
Car,Ford,GT40,1964,250000,987,Red,A1,2,4,FALSE
The value I want out of this specific line would be '250000' - the 5th one along. I'm trying to get the 5th one along from every line.
Your problem is that you are trying to parse also the first line (which does not contain enough entries so you get the exception). You can skip the first line by starting your iteration at index 1:
int totalValues = 0;
string[] larray = lines.ToArray(); //create array from list
string vehicleValue;
for (int i = 1; i < larray.Length; i++)
{
string[] bits = larray[i].Split(',');
vehicleValue = bits[4];
int vvint = int.Parse(vehicleValue);
totalValues = totalValues + vvint;
}
totalValue.Text = totalValues.ToString();
bits[4] is the fifth item in the array as indexing starts from zero, to get the fourth item you should get bits[3]
int totalValues = 0;
string[] larray = lines.ToArray(); //create array from list
string vehicleValue;
for (int i = 0; i < larray.Length; i++)
{
string[] bits = larray[i].Split(',');
vehicleValue = bits[3];
int vvint = int.Parse(bits[3]);
totalValues = totalValues + vvint;
}
totalValue.Text = totalValues.ToString();
Good day. I would like to ask if it is possible to concatenate 2 strings to get another variable.
Lets say I have this code:
string num1 = "abcdefgh";
string num2 = "ijklmnop";
int numLength = 0;
And I want to get the value of both num1 and num2 using a forloop
for(int i =1; i<= 2; i++)
{
numLength = ("num" + i).Length + numLength;
}
Console.WriteLine("Length is {0}", numLength);
I want it to output
Length is 16
I did the above code but it actually gives me different value.
Edit1: (P.S. I will be using more than 10 variables, I just indicated 2 of it to make it simple)
Edit2: Yes, yes. I want ("num"+i).Length to give me num1.Legnth + num2.Length.
First way:
I suggest you to add all of your strings into the List and then get the total length with Sum method.
List<string> allStrings = new List<string>();
allStrings.Add(num1);
allStrings.Add(num2);
...
allStrings.Add(num10);
var totalLength = allStrings.Sum(x => x.Length);
Second way
Or if you want to calculate total length with for loop:
int totalLength = 0;
for (int i = 0; i < allStrings.Count; i++)
{
totalLength = totalLength + allStrings[i].Length;
}
Third way
If you don't want to use List, then you can use String.Concat and then Length property.
var totalLength = String.Concat(num1, num2).Length;
The result is 16 in your case.
Edit:
In my opinion you think that, ("num" + i).Length will give you num1.Length and num2.Length. This is wrong.
Lets say we have some strings and we want the total length for all this strings.
In this case you need to store all strings in an array, so you can counter them and use indexes.
and after that a simple for (or foreach) loop can solve the problem:
string[] texts = new string[20]; //You can use any number u need, but in my code I wrote 20.
texts[0] = "sample text 1";
texts[1] = "sample text 2";
// add your strings ...
int totalLenght = 0;
foreach (string t in texts)
{
totalLenght += t.Length;
}
Console.WriteLine("Length is {0}", totalLenght);
If you need a variable with unlimited size, use List<T>
here is example:
List<string> texts = new List<string>();
texts.Add("sample text 1");
texts.Add("sample text 2");
// add your strings ....
int totalLenght = 0;
for (int i = 0; i < texts.Count; i++)
{
totalLenght += texts[i].Length;
}
Console.WriteLine("Length is {0}", totalLenght);
I just started work on a C# application. I need to break down a string into different parts. Is there an easy way to do this using C# patterns? I think I can do it with substrings but it might get messy and I want to do something that's easy to understand. Here's an example of the input:
AB-CDE-GHI-123-45-67-7777
variable1 = "AB-CDE-GHI"
variable2 = "123"
variable3 = "45"
variable4 = "67"
variable5 = "67-7777"
AB-CDE-GHIJKLM-123-45-67-7777
variable1 = "AB-CDE-GHIJKLM"
variable2 = "123"
variable3 = "45"
variable4 = "67"
variable5 = "67-7777"
AB-123-45-67-7777
variable1 = "AB"
variable2 = "123"
variable3 = "45"
variable4 = "67"
variable5 = "67-7777"
The first part of the string up until "123-45-67-7777" can be any length. Lucky for me the last part 123-45-67-7777 is always the same length and contains numbers that are zero padded.
I hope someone can come up with some suggestions for an easy method that uses regular expressions or something.
Input lines look like this:
aa-123-45-67-7777
HJHJH-123-45-67-7777
H-H-H--123-45-67-7777
222-123-45-67-7777
You do not need RegEx for parsing this kind of input.
You can use string.Split, in particular if the input is highly structured.
If you first split by - you will get a string[] with each part in a different index of the array.
The length property of the array will tell you how many parts you got and you can use that to reconstruct the parts you need.
You can rejoin any of the bit you need back.
string[] parts = "AB-CDE-GHI-123-45-67-7777".split('-');
// joining together the first 3 items:
string letters = string.Format("{0}-{1}-{2}", parts[0], parts[1], parts[2]);
// letters = "AB-CDE-GHI"
If the number of sections is variable (apart from the last 4), you can use the length in a loop to rebuild the wanted parts:
StringBuilder sb = new StringBuilder();
for(int i = 0; i < parts.Length - 4; i++)
{
sb.FormatAppend("{0}-", parts[i]);
}
sb.Length = sb.Length - 1; // remove trailing -
If the last part is always a known length (14 characters) you could just do something like this:
var firstPart = inputLine.Substring(inputLine.Length - 14);
var secondPart = inputLine.Substring(0, inputLine.Length - 15); // 15 to exclude the last -
Then you can just do your string splitting and job done :)
Although it is possible to use here String.Split, a better solution, in my opinion, would be to tokenize the input and then parse it.
You can use tools such as ANTLR for this purpose.
string[] str = "AB-CDE-GHI-123-45-67-7777".Split('-')
int a = str.Length;
variable1="";
for(int i=0;i=<a-5;i++)
{
variable1=str[i]+"-"+variable1;
}
// last - remove
variable1 = variable1.Remove(variable1.Length-1,1);
variable2 = str[a-4]
variable3 = str[a-3]
variable4 = str[a-2]
variable5 = str[a-2]+"-"str[a-1];
like Oded say you can use string.Split
I edit my answer like you want
string[] tab = textBox1.Text.Split('-');
int length = tab.Length;
string var1 = string.Empty;
for(int i=0; i <= length-5 ; i++)
{
var1 = var1 + tab[i] + '-';
}
var1 = var1.Remove(var1.Length-1,1);
string var2 = tab[length-4];
string var3 = tab[length-3];
string var4 = tab[length-2];
string var5 = tab[length-2] + '-' + tab[length-1];
it's the same with the answer of #Govind KamalaPrakash Malviya just you have make var1 + tab[i]