Import x and y coordinates from .txt file - c#

I need to read coordinates from text file for my project,but the text file is like this
1 37.4393516691 541.2090699418
2 612.1759508571 494.3166877396
3 38.1312338227 353.1484581781
and with more space in front.I have code that i tried but i couldn't make the seperators work.
1 1150.0 1760.0
2 630.0 1660.0
3 40.0 2090.0
The code:
string[] cityPositions = File.ReadAllLines(ofd.FileName);
foreach (string cityP in cityPositions)
{
int startIndexX = cityP.IndexOf(" ", StringComparison.CurrentCultureIgnoreCase) + 3;
int endIndexX = cityP.IndexOf(" ", StringComparison.CurrentCultureIgnoreCase);
int X = int.Parse(cityP.Substring(startIndexX, endIndexX - startIndexX));
int startIndexY = cityP.IndexOf(" ", StringComparison.CurrentCultureIgnoreCase) + 3;
int endIndexY = cityP.IndexOf("", StringComparison.CurrentCultureIgnoreCase);
int Y = int.Parse(cityP.Substring(startIndexY, endIndexY - startIndexY));
create_City(new Point(X, Y));
}

If you want to make use of Regular Expressions, try this:
String expression = #"(\d)([\d\.]*)([\d\.]*)";
Regex r = new Regex(expression);
foreach (String cityPosition in cityPositions)
{
MatchCollection mc = r.Matches(cityPosition);
int index = Convert.ToInt32(mc[0].Value);
decimal coOrdX = Convert.ToDecimal(mc[1].Value);
decimal coOrdY = Convert.ToDecimal(mc[2].Value);
Console.WriteLine(String.Format("{0} {1} {2}", index, coOrdX, coOrdY));
}
This code will produce this output:
1 1150.0 1760.0
2 630.0 1660.0
3 40.0 2090.0
It should disregard the varying amount of space between the values and make it easier to parse the three different values in the file.

First of all your data type doesnt match. You should use double for coordinates, and use Split method, for example:
double X = double.Parse(cityP.Split()[1], CultureInfo.InvariantCulture);
double Y = double.Parse(cityP.Split()[2], CultureInfo.InvariantCulture);
Split function with no parameters given will split by whitespace.
EDIT
It's not clear in the question but, if your lines dont have the same pattern, and have different spaces use Split method like this:
double X = double.Parse(cityP.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[1], CultureInfo.InvariantCulture);

Instead of working with indices, you could Replace multiple whitespaces with a single whitespace, like
RegexOptions options = RegexOptions.None;
Regex regex = new Regex("[ ]{2,}", options);
cityP = regex.Replace(cityP, " ");
then use split to get the coordinates
var x = double.Parse(cityP.Split()[1]);
var y = double.Parse(cityP.Split()[2]);

Related

Match '$GPGGA' expression

I have a GPS device that outputs multiple separate strings every 1 second, like this(few seconds worth of data):
$GPGGA,021225.000,5425.7163,N,01341.7347,E,1,14,0.73,-5.2,M,41.5,M,,*44
$GNRMC,021225.000,A,5425.7163,N,01341.7347,E,0.00,324.63,041017,,,A*70
$GPVTG,324.63,T,,M,0.00,N,0.00,K,A*3D
$GPGGA,021226.000,5425.7163,N,01341.7347,E,1,14,0.73,-5.2,M,41.5,M,,*47
$GNRMC,021226.000,A,5425.7163,N,01341.7347,E,0.00,324.63,041017,,,A*73
$GPVTG,324.63,T,,M,0.00,N,0.00,K,A*3D
$GPGGA,021227.000,5425.7163,N,01341.7347,E,1,14,0.73,-5.2,M,41.5,M,,*46
$GNRMC,021227.000,A,5425.7163,N,01341.7347,E,0.00,324.63,041017,,,A*72
$GPVTG,324.63,T,,M,0.00,N,0.00,K,A*3D
My objective is simple, I only need the (whole) string starting in $GPGGA. So instead, of seeing all the above strings, I simply need:
$GPGGA,021225.000,5425.7163,N,01341.7347,E,1,14,0.73,-5.2,M,41.5,M,,*44
$GPGGA,021226.000,5425.7163,N,01341.7347,E,1,14,0.73,-5.2,M,41.5,M,,*47
$GPGGA,021227.000,5425.7163,N,01341.7347,E,1,14,0.73,-5.2,M,41.5,M,,*46
Simples, right?!
For reference, this is the code I am using:
string numbers = Encoding.ASCII.GetString(e.Data);
var ismatch = Regex.Match(numbers, #"");
if (ismatch.Success)
{
tbData.AppendText(numbers);
}
else
{
tbData.AppendText("Invalid");
}
I am quite sure the code is working okay, because with #"" it returns all the strings (in the textbox in the UI) without showing 'Invalid' instead.
I've tried a million different expressions, including very simple ones but I can't get a handle for the language.
So for the Regex geniuses out there, could you enlighten me to what expression will work for '$GPGGA.......' ?
$ is a special character in RegEx. You need to escape it to match it (\$).
So something like this should work:
var ismatch = Regex.Match(numbers, #"^(\$GPGGA,.*)$", RegexOptions.Multiline);
Let's break this down:
^ - Match the start of the input
( - Start of a capture group
\$GPGGA, - Match this specific text (note the escaped $)
.* - Match everything else
) - End of the capture group
$ - End of the input
In order to get capture groups for each line starting with $GPGGA, I had to enable Multiline (RegexOptions.Multiline).
FYI, I often use this site for testing Regular Expressions. Their reference page is also helpful.
I've put together a fiddle for you.
The answer does not use Rengex, but it works, and took me a while to make sure it contain no error.
//assume you have your string from Serial Port (COM)
string[] strArr = data.Split('$'); //split different GPS string
for (int j = 0; j < strArr.Length; j++)
{
string strTemp = strArr[j];
debug = strTemp;
string[] lineArr = strTemp.Split(',');
if (lineArr[0] == "GPGGA")
{
try
{
//Latitude
if (lineArr.Length >= 7 && lineArr[2] != "")
{
//Latitude
double converted = Convert.ToDouble(lineArr[2]) / 100;
string[] lat = converted.ToString().Split('.');
string altered = lat[1] + "000000000000000000000000";
double me = Convert.ToDouble(lat[0].ToString()) + ((Convert.ToDouble(altered.Substring(0, 6)) / 60)) / 10000;
Latitude = lineArr[3].ToString() + me.ToString();
//Longitude
double converted1 = Convert.ToDouble(lineArr[4]) / 100;
string[] lon = converted.ToString().Split('.');
string altered1 = lon[1] + "000000000000000000000000";
double me1 = Convert.ToDouble(lon[0].ToString()) + ((Convert.ToDouble(altered1.Substring(0, 6)) / 60)) / 10000;
Longitude = lineArr[5].ToString() + me1.ToString();
//Time
string timeMinAndSec = lineArr[1][0].ToString() + lineArr[1][1].ToString();
//Altitude
if (lineArr.Length >= 10)
{
Altitude = lineArr[9].ToString();
}
}
}
}
}

How to remove invalid entries from a decimal number in wpf text box

In WPF I want to allow the text box to accept only decimal point numbers with maximum 2 digits after decimal point. For example 330.33 is valid and 333.333 is not valid. Text box should restrict all the other special characters. I created two functions one for returning the invalid string and other for comparing the string with characters pressed by user and if the string contains invalid character remove that character. I think this approach of hard coding the invalid chars in a string and comparing it with invalid key stroke is not correct. Is there any better way of doing this?.
private string GetInvalidstring()
{
string invalidCharacterString = #" ! "" # $ % & ' ( ) * + , - / : ; < = > ? # A B C D \ | _ ~ ^";
invalidCharacterString += #" E F G H I J K L M N O P Q R S T U V W X Y Z ";
return invalidCharacterString;
}
private string CheckValidEntry(string input)
{
string invalidCharacters = GetInvalidstring();
char[] tocheck = input.ToCharArray();
string copy = input;
foreach (char c in tocheck )
{
if (invalidCharacters.Contains(c))
{
// int i = input.IndexOf(c);
copy = input.Replace(c, ' ');
}
}
return new string(copy.ToList().Where(c => c != ' ' ).ToArray());
}
You can use this regex to allow only decimal numbers upto two places to decimal
^(\d+)?+([\.]{1})?+([\d]{1,2})?$
REGEX DEMO
Also take a look at Restrict a textbox to allow decimal upto two places
You could do this:
private bool IsValid(string input)
{
decimal temp;
return decimal.TryParse(input,out temp) && Math.Round(temp,2)==temp;
}
Use Math.Round() function:
Math.Round(value, 2);
If value is = 333.333333, Math.Round(value,2) return 333.33

Reading two integers at the end of text

I am getting values from the form in the following format:
text 2234-7755
What i want to do is read first four integers than the last four integer values separately.
Please let me know how can i read that. Thanks
string[] nums = text.Split("-");
int num1 = Convert.ToInt32(nums[0]);
int num2 = Convert.ToInt32(nums[1]);
If you want to be safer, you can use int.TryParse
If the number is always at the end, has 8 digits and is separated by - you don't need regex:
string number = text.Substring(text.Length - 9);
string[] both = number.Split('-');
int firstNum, secondNum;
if (both.Length == 2
&& int.TryParse(both[0], out firstNum)
&& int.TryParse(both[1], out secondNum))
{
Console.Write("First number is: {0}\r\nSecond number is: {1}", firstNum, secondNum);
}
Are you looking for something like this?
string text = "text 2234-7755";
var matches = Regex.Matches(text, #"(\d+)");
if (matches.Count == 2)
{
int value1 = Convert.ToInt32(matches[0].Groups[1].Value);
int value2 = Convert.ToInt32(matches[1].Groups[1].Value);
}
use split function and get the first value.
A link for the same
var original="2234-7755";
var intArray = original.Split("-");
int part1 = Convert.ToInt32(intArray[0]);
int part2 = Convert.ToInt32(intArray[1]);
You can also use Int32.TryParse method if you want more control.

Using Substring to get digit before a string

I am reading a file in C#. I want to check value from a string. The line consists as following:
15 EMP_L_NAME HAPPENS 5 TIMES.
40 SUP HAPPENS 12 TIMES.
I want to find the number of times which is in the string before the string "TIMES". I have written the following code:
int arrayLength = 0;
int timesindex = line.IndexOf("TIMES");
if (timesindex > 0)
{
//Positon of the digit "5" in the first line
int indexCount = timesindex - 2;
if (int.TryParse(line.Substring(indexCount, 1), out occursCount))
{
arrayLength = occursCount;
}
}
Using the above code, I can find the number of "TIMES" for a single digigt number. But if it is a double digit, it won't work( e.g the second line). I have to develop a logic to find the digit which is separted by a space with "TIMES". How I can do that?
You can do:
Split your string on space and remove empty enteries.
Find Index of "TIMES."
Access element Index - 1
Like:
string str = "15 EMP_L_NAME HAPPENS 5 TIMES. ";
string[] array = str.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
int index = Array.IndexOf(array, "TIMES.");
int number;
if (!int.TryParse(array[index - 1], out number))
{
//invalid number
}
Console.WriteLine(number);
If the input is reliable you can do a quicky with String.Split()...
int arrayLength = 0;
int timesindex = line.IndexOf("TIMES");
if (timesindex > 0)
{
string[] items = line.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
if (int.TryParse(items[items.Length - 2], out occursCount))
{
arrayLength = occursCount;
}
}
This method relies on the desired number being the second from last "word" in each line
If your strings are always the same format, with exactly five words or "sections" or whatever you want to call them, you could use:
int times = 0;
Int32.TryParse(line.Split(' ')[3], out times);
This would have to be more robust there's a chance the number may not exist in the string, or the string is in a completely different format.
Look at LastIndexOf combined with your timesindex. You can look for the space before the space before (timesindex-1), and then you have the two positions around the number.
int timesindex = line.IndexOf("TIMES");
int firstSpace = line.LastIndexOf(" ", timesindex-1);
string number = line.Substring(firstSpace, timesindex-firstSpace);
Though this might need some adjustments on the indexes, but that's the idea anyway
Try this
int timesindex = line.IndexOf("TIMES");
int happensindex = line.IndexOf("HAPPENS") + 7; //Add 7 cause HAPPEND is 7 chars long
if (timesindex > 0)
{
//Positon of the digit "5" in the first line
if (int.TryParse(line.Substring(happensindex, timesindex).trim(), out occursCount))
{
arrayLength = occursCount;
}
}
A Regex would be cleaner:
var regex = new Regex(#"(\d+)\sTIMES"); // match a number followed by whitespace then "TIMES"
string num = regex.Match(" 15 EMP_L_NAME HAPPENS 5 TIMES").Groups[1].ToString();
int val = int.Parse(num);
Using LINQ:
string[] lines = {"15 EMP_L_NAME HAPPENS 5,1 TIMES.", "40 SUP HAPPENS 12 TIMES. "};
var allValues = lines.Select(line =>
{
double temp;
var words = line.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
var value = words[Array.IndexOf(words,"TIMES.") - 1];
if (double.TryParse(value, out temp)) return temp;
else return 0;
}).ToList();
foreach (var value in allValues)
{
Console.WriteLine(value);
}
// Output:
// 5,1
// 12
You can use System.Text.RegularExpressions.Regex, i.e. a regular expression, in order to find a pattern in a string:
string input = "40 SUP HAPPENS 12 TIMES.";
Match match = Regex.Match(input, #"(?<=HAPPENS\s)\d+(?=\sTIMES)");
if (match.Success) {
Console.WriteLine(match.Value); '==> "12"
}
Explanation of the regular expression: It uses the general pattern (?<=prefix)find(?=suffix) in order to find a position between a prefix and suffix.
(?<=HAPPENS\s) Prefix consisting of "HAPPENS" plus a whitespace (\s)
\d+ A digit (\d) repeated one or more times (+)
(?=\sTIMES) Suffix consisting of a whitespace (\s) plus "TIMES"
If you only want to test for "TIMES" but not for "HAPPENS", you can just drop the first part:
Match match = Regex.Match(input, #"\d+(?=\sTIMES)");
Since you are using the same search pattern many times, it is advisable to create a Regex once instead of calling a static method:
Regex regex = new Regex(#"\d+(?=\sTIMES)");
// Use many times with different inputs
Match match = regex.Match(input);

Converting number to comma separated values

I need to convert numbers into a comma separated format to display in C#.
For Example:
1000 to 1,000
45000 to 45,000
150000 to 1,50,000
21545000 to 2,15,45,000
How to achieve this in C#?
I tried the below code:
int number = 1000;
number.ToString("#,##0");
But it is not working for lakhs.
I guess you can do this by creating a custom number format info for your needs
NumberFormatInfo nfo = new NumberFormatInfo();
nfo.CurrencyGroupSeparator = ",";
// you are interested in this part of controlling the group sizes
nfo.CurrencyGroupSizes = new int[] { 3, 2 };
nfo.CurrencySymbol = "";
Console.WriteLine(15000000.ToString("c0", nfo)); // prints 1,50,00,000
if specifically only for numbers then you could also do
nfo.NumberGroupSeparator = ",";
nfo.NumberGroupSizes = new int[] { 3, 2 };
Console.WriteLine(15000000.ToString("N0", nfo));
Here's a similar thread to yours add commas in thousands place for a number
and here's the solution that worked perfectly for me
String.Format("{0:n}", 1234);
String.Format("{0:n0}", 9876); // no decimals
If you want to be unique and do extra work that you don't have to here is a function I created for integer numbers you can place commas at whatever interval you want, just put 3 for a comma for each thousandths or you could alternatively do 2 or 6 or whatever you like.
public static string CommaInt(int Number,int Comma)
{
string IntegerNumber = Number.ToString();
string output="";
int q = IntegerNumber.Length % Comma;
int x = q==0?Comma:q;
int i = -1;
foreach (char y in IntegerNumber)
{
i++;
if (i == x) output += "," + y;
else if (i > Comma && (i-x) % Comma == 0) output += "," + y;
else output += y;
}
return output;
}
Have you tried:
ToString("#,##0.00")
Quick and dirty way:
Int32 number = 123456789;
String temp = String.Format(new CultureInfo("en-IN"), "{0:C0}", number);
//The above line will give Rs. 12,34,56,789. Remove the currency symbol
String indianFormatNumber = temp.Substring(3);
An easy solution would be to pass a format into the ToString() method:
string format = "$#,##0.00;-$#,##0.00;Zero";
decimal positiveMoney = 24508975.94m;
decimal negativeMoney = -34.78m;
decimal zeroMoney = 0m;
positiveMoney.ToString(format); //will return $24,508,975.94
negativeMoney.ToString(format); //will return -$34.78
zeroMoney.ToString(format); //will return Zero
Hope this helps,

Categories