Match '$GPGGA' expression - c#
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();
}
}
}
}
}
Related
why method "equals" skips the necessary chars although they are written in unicode?
I splitted csv-file by "," but some numbers were written with using of this symbol so some numbers were splitted on some parts. The beginning and the end of the every splitted number are signed by """ so i tried to paste parts of the number focusing on quotation marks... string[] inputData = File.ReadAllLines("file.csv"); string[,] allData = new string[inputData.GetLength(0) - 1, 8]; for (int i = 1; i < inputData.GetLength(0); i++) { string[] arrayHelpStupied = inputData[i].Split(","); string[] arrayHelpSmart = new string[8]; int m = 0; int flagMistake = 0; string compoundingOfSplittedNumber = ""; Console.WriteLine("\u0022"); for (int j = 0; j < arrayHelpStupied.Length; j++) { string prov = arrayHelpStupied[j]; if ((prov[0].Equals("\"")) || (flagMistake == 1)) { flagMistake = 1; compoundingOfSplittedNumber += arrayHelpStupied[j]; if (arrayHelpStupied[j][^1].Equals("\u0022")) { flagMistake = 0; arrayHelpSmart[m++] = compoundingOfSplittedNumber; continue; } continue; } arrayHelpSmart[m++] = arrayHelpStupied[j]; } but numbers that start with quotation mark is ignored :( please could you explain me the reason of such behaviour and how can i cope this difficulty please
If I'm reading the question correctly, you have a CSV file you're splitting on , and some of the "values" you're looking for also have a , in them and you don't want it to split on the , in the value... Sorry, but it's not going to work. String.Split does not have any overrides, or regex matching. Your best bet is to sanitize your data first by removing the , from the values, or ensuring the , separating your values matches differently than the , in the values. For example... 12,345 , 23,1566 , 111 , 1 you can split the above on " , " instead of just "," and since the pattern of " , " is consistent, then it will work Alternately, you could open your csv in Excel and save it as a Tab delimited text file and then split on the tab "/t" character
Skipping a range of values in for loop C#
I'm trying to cycle through chars in a string. string cycleMe = "Hi StackOverflow! Here is my string." However, I want to skip over certain ranges of indexes. The ranges I want to skip over are stored in a List of objects, delims. List<Delim> delims = delimCreator(); To retrieve each starting index and ending index for a range, I have to write a loop that accesses each "delim": delims[0].getFirstIndex() //results in, say, index 2 delims[0].getLastIndex() //results in, say, index 4 delims[1].getFirstIndex() //results in, say, index 5 delims[1].getLastIndex() //results in, say, index 7 (there can be infinitely many "delim" objects in play) If the above were my list, I'd want to print the string cycleMe, but skip all the chars between 2 and 4 (inclusive) and 5 and 7 (inclusive). Expected output using the numbers above: HiOverflow! Here is my string. Here is the code I have written so far. It loops far more often than I'd expect (it loops ~x2 the number of characters in the string). Thanks in advance! =) List<Delim> delims = delimAggregateInator(displayTextRaw); for (int x = 0; x < cycleMe.Length;x++){ for (int i = 0; i < delims.Count; i++){ if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){ Debug.Log("test"); } }
I assume that by skipping you meant you want to omit those characters from the original string. If that is the case, you can try Aggregate extension method like below. string result = delims.Aggregate<Delim, string>(cycleMe, (str, d) => cycleMe = cycleMe.Remove(d.FirstIndex, (d.LastIndex - d.FirstIndex) + 1)); Make sure that the delim list is in the proper order.
Solution might be converting the string to char array, replacing the desired parts to spaces, and converting the output back to string. Here is the modified version of your code: string cycleMe = "Hi StackOverflow! Here is my string." var charArray = cycleMe.ToCharArray(); // Converting to char array List<Delim> delims = delimAggregateInator(displayTextRaw); for (int x = 0; x < cycleMe.Length;x++){ for (int i = 0; i < delims.Count; i++){ // ORIGINAL: if (!(x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex())){ if (x >= delims[i].getFirstIndex() && x <= delims[i].getLastIndex()){ Debug.Log("test"); charArray[x] = ' '; // Replacing the item with space } } string output = new string(charArray); // Converting back to string P.S. This is probably not the most optimal solution but at least it should work.
You should use LINQ for that struct Delim { public int First { get; set; } public int Last { get; set; } } static void Main(string[] args) { string cycleMe = "Hi StackOverflow! Here is my string."; var delimns = new List<Delim> { new Delim { First=2, Last=4}, new Delim { First = 5, Last = 7 } }; var cut = cycleMe.Where((c, i) => !delimns.Any(d => i >= d.First && i <= d.Last)); Console.WriteLine(new string(cut.ToArray()); } That means I am basically only selecting letters, at positions which are not part of any cutting range. Also: Fix your naming. A delimiter is a character, not a position (numeric)
Import x and y coordinates from .txt file
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]);
Getting true in equal() when more characters look like
How to recognize two strings when most characters are similar I want get true in this samples "Hello Wolrld" == "HelloWorld" OR "hello world!!" == "helloworld" I know that these are not equal, But since most of the characters are the same, it is enough for me Thanks in advance
Use this Regex.Replace(textBox1.Text, #"[^0-9a-zA-Z]+", "").ToLower() == your string in lower case
You can compute the Levenshtein distance of the two strings (see for example this C# implementation) and then define a threshold up to which you consider the strings to be "equal". What a reasonable threshold is depends on your requirements. Probably, defining the predicate as d <= a * Math.Min(string1.Length, string2.Length) should work, where d is the Levenshtein distance of the strings and a is a factor of "similarity" between 0 and 1. In your examples a==0.3 should work.
If you're looking for a very basic check, you can enumerate over the characters using Zip to compare them, count the matching letters, and report true if the number of matches are above a certain threshold. This won't capture it if one string is a shifted version of the other; it'll only catch letters in common at the same index. public static class ExtensionMethods { public static bool FuzzyCompare(this string lhs, string rhs, float ratioRequired) { var matchingLetters = lhs.Zip ( rhs, (a,b) => a == b ? 1 : 0 ) .Sum(); return (float)matchingLetters / (float)lhs.Length > ratioRequired; } } To compare two strings to see if they match on at least half of the letters, pass a ratioRequired of 0.5. public static void Main() { var a = "ABCD"; var b = "ABCDEFGHI"; Console.WriteLine( a.FuzzyCompare(b, 0.5F) ); } Output: True Code on DotNetFiddle
This give true if 80% words are similer Try this String str1 = "Hello world"; String str2 = "Helloworld!!"; char[] charArray; int per = 0; int c = 0; if (str1.length() > str2.length()) { per = (str1.length() * 80) / 100; // 80% per match logic charArray = str1.toCharArray(); for (int i = 0; i < str1.length(); i++) { String chars = String.valueOf(charArray[i]); if (str2.contains(chars)) { c++; } } } else { per = (str1.length() * 80) / 100; // 80% per match logic charArray = str2.toCharArray(); for (int i = 0; i < str2.length(); i++) { String chars = String.valueOf(charArray[i]); if (str1.contains(chars)) { c++; } } } if (c >= per) { Toast.makeText(getApplicationContext(), "true", 0).show(); } else { Toast.makeText(getApplicationContext(), "false", 0).show(); }
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,