How to convert a map point string to double? - c#

I have a string such as 45,5235234096284 or 112,013574120648. I want to convert it to double. I have tried following code but i got error 'System.Globalization.CultureInfo' does not contain a definition for 'GetCultureInfo
' because of framework version. I'm not able to change framework option.I have looked some another solution but i couldn't understand clearly.What is the best way converting these string to double with their commas.
var convertedMapPoint = double.Parse(mapPoint, CultureInfo.GetCultureInfo(1053));

First, you should split your input on spaces, since that is the separator:
string input = "45,5235234096284 112,013574120648";
string[] splitted = input.Split(' ');
Then you can iterate over the result of the splitting, and convert each to a double:
List<double> doubles = new List<double>();
foreach (string s in splitted)
{
doubles.Add(double.Parse(s, new CultureInfo("fr-FR")));
}
I used fr-fr, since it has a comma as decimal separator, but you can use any culture that does that.
If that doesn't work for you, and you are 100% sure there is no . as thousand separator, you can use this:
doubles.Add(double.Parse(s.Replace(",", ".")));
Then you might want to add the invariant culture to be platform independent:
doubles.Add(double.Parse(s.Replace(",", ".", CultureInfo.InvariantCulture)));

You should split the string into array delimited by Space, and than convert each part.
string mapPoint = "45,5235234096284 112,013574120648";
var mapPoints = mapPoint.Split(' ');
var convertedMapPointX = double.Parse(mapPoints[0], CultureInfo.GetCultureInfo(1053));
var convertedMapPointY = double.Parse(mapPoints[1], CultureInfo.GetCultureInfo(1053));
Console.WriteLine("X: {0}\tY: {1}", convertedMapPointX, convertedMapPointY);
Output:
X: 45.5235234096284 Y: 112.013574120648

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StringToMapPoint
{
class Program
{
static void Main(string[] args)
{
string mapPointStr = "45,5235234096284 112,013574120648";
MapPoint mp = mapPointStr.ToMapPoint();
Console.WriteLine(mp.ToString());
}
}
public class MapPoint
{
public double X { get; set; }
public double Y { get; set; }
public override string ToString()
{
return "X: " + X + " Y: " + Y;
}
}
public static class MapPointHelper
{
public static MapPoint ToMapPoint(this string str)
{
var split = str.Replace(".", ",").Split(' ');
return new MapPoint() { X = Double.Parse(split[0]), Y = Double.Parse(split[1]) };
}
}
}

Related

Reading a string from one char to another

I have the following string:
FB:77:CB:0B:EC:09{W: 0,623413, X: 0,015374, Y: 0,005306, Z: -0,781723}
I want to read out the values of W,X,Y,Z as a float/decimal. The values are not always the same length.
How can I read this string from one character to another without using relative positions?
I'd suggest matching the "inner" part with a regular expression, but removing the "outer" part manually first - just to keep the regex as simple as possible.
Here's a complete example, with a method that returns the result as a Dictionary<string, string>. It's not clear how you'd then want to convert the sample values you've given (e.g. "0,623413") into integers, but I'd treat that as a separate task from the initial parsing.
I'm assuming that it's fine to strip all trailing commas from values:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
class Test
{
static void Main()
{
string input = "FB:77:CB:0B:EC:09{W: 0,623413, X: 0,015374, Y: 0,005306, Z: -0,781723}";
var parsed = Parse(input);
foreach (var entry in parsed)
{
Console.WriteLine($"Key = '{entry.Key}', Value = '{entry.Value}'");
}
}
static readonly Regex regex = new Regex(#"(?<key>[A-Z]+): (?<value>[-\d,]+)");
static IDictionary<string, string> Parse(string input)
{
int openBrace = input.IndexOf('{');
if (openBrace == -1)
{
throw new ArgumentException("Expected input to contain a {");
}
if (!input.EndsWith("}"))
{
throw new ArgumentException("Expected input to end with }");
}
string inner = input.Substring(openBrace + 1, input.Length - openBrace - 2);
var matches = regex.Matches(inner);
return matches.Cast<Match>()
.ToDictionary(match => match.Groups["key"].Value,
match => match.Groups["value"].Value.TrimEnd(','));
}
}
Output:
Key = 'W', Value = '0,623413'
Key = 'X', Value = '0,015374'
Key = 'Y', Value = '0,005306'
Key = 'Z', Value = '-0,781723'
Converting those values to integers may be as simple as removing the commas, trimming leading zeroes, and then using int.Parse - but it really depends on what you want the results to be.
To answer your question, this method will do:
int GetIntValue(string input, char prefix)
{
return int.Parse(input.Substring(input.IndexOf($"{prefix}: ") + 3, 1));
}
This will, however, return 0 for all of your sample input. The reason why we only parse the zero is that they'll be ignored by the int parser anyway.
If, as I suspect, you don't want an integer but instead the full number, use something like this:
decimal GetValue(string input, char prefix)
{
return decimal.Parse(input.Substring(input.IndexOf($"{prefix}: ") + 3).Split(new[] { ", ", "}" }, StringSplitOptions.None).First());
}
Feel free to replace decimal with whatever you would like.
Call it like this:
var input = "FB:77:CB:0B:EC:09{W: 0,623413, X: 0,015374, Y: 0,005306, Z: -0,781723}";
var W = GetValue(input, 'W'); // 0.623413
var X = GetValue(input, 'X'); // 0.015374
var Y = GetValue(input, 'Y'); // 0.005306
var Z = GetValue(input, 'Z'); // -0.781723
What this does is to identify the location of the prefix, and then parse a substring from the beginning of the following number until the delimiter (, or }) has been reached.
static void Main(string[] args) {
string str = "FB:77:CB:0B:EC:09{W: 0,623413, X: 0,015374, Y: 0,005306, Z: -0,781723}";
char[] delims = { ':', ' ' };
var parsed = Parse(str, delims);
foreach (var p in parsed) {
Console.WriteLine($"{p.Key} : {p.Value}");
}
}
static Dictionary<string, double> Parse(string input, char[] delims) {
int first = input.IndexOf('{') + 1;
int second = input.IndexOf('}');
string str2 = input.Substring(first, second - first);
string[] strArray = str2.Split(delims, StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, double> pairs = new Dictionary<string, double>();
for (int i = 1; i < strArray.Length; i++) {
if (double.TryParse(strArray[i].TrimEnd(','), out double result)) {
pairs.Add(strArray[i - 1], result);
}
i++;
}
return pairs;
}
Here is another Regex example that parses number to decimal and includes plus and negative sign.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string input = "FB:77:CB:0B:EC:09{W: 0,623413, X: 0,015374, Y: 0,005306, Z: -0,781723}";
string pattern = #"W:\s*(?'W'[-+]?\d+,\d+),\s*X:\s*(?'X'[-+]?\d+,\d+),\s*Y:\s*(?'Y'[-+]?\d+,\d+),\s*Z:\s*(?'Z'[-+]?\d+,\d+)";
CultureInfo info = new CultureInfo("en");
info.NumberFormat.NumberDecimalSeparator = ",";
Match match = Regex.Match(input, pattern);
decimal W = decimal.Parse(match.Groups["W"].Value, info);
decimal X = decimal.Parse(match.Groups["X"].Value, info);
decimal Y = decimal.Parse(match.Groups["Y"].Value, info);
decimal Z = decimal.Parse(match.Groups["Z"].Value, info);
}
}
}

How to correctly convert letters to numbers?

I have a string which comprise lots of letters. I have used the following code to convert it to numbers, but the new string t still gives me imperfect result.
For example:
tung2003 -> -1-1-1-12003
What I expected: 1161171101032003 (116 is the ASCII code of t, 117 is the ASCII code of u
string t=null;
foreach (char c in Properties.Settings.Default.password)
{
int ascii = (int)Char.GetNumericValue(c);
int counter=0;
counter = ascii;
t = t + Convert.ToString(counter);
}
The problem is the - character. I want my new string only comprises numbers.
It looks like you do not want the ASCII values of the numbers based on your expected output. In that case you can just do something like this:
string input = "tung2003";
string output = string.Empty;
foreach(char c in input)
{
if(char.IsNumber(c))
{
output += c;
}
else
{
output += ((byte)c).ToString();
}
}
//output is now: 1161171101032003
Fiddle here
Also added as a Linq expression for a short hand solution.
// Method 1 Linq
string output = string.Concat(("tung2003".ToCharArray()
.Select(s=> char.IsDigit(s) ? s.ToString() : ((int)s).ToString())));
// Method 2
string input = "tung2003";
string output = string.Empty;
foreach (char c in input)
{
if (Char.IsDigit(c)) output += c.ToString();
else output += ((int)c).ToString();
}
Extrapolating your output it looks like you want two different things. You want to tally each ascii character as long as it is a letter and extract the numeric values to append. The following provides three options, the first is to tally the ascii values from letters and the other two are ways to extract only digits. Because your code example uses a Password I am assuming you are trying to do some sort of custom hashing and if that is the case you should use a Hash implementation from the Cryptography namespace or some other package.
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
var combined = OnlyLettersToAscii("tung2003") + OnlyNumbers("tung2003");
Console.WriteLine($"Input: tung2003 Output: {OnlyNumbers("tung2003")}");
Console.WriteLine($"Input: tung2003 Output Regex: {OnlyNumbersWithRegex("tung2003")}");
Console.ReadKey();
}
private static string OnlyLettersToAscii(string originalString)
{
if (string.IsNullOrWhiteSpace(originalString)) return originalString;
return string.Join(string.Empty, originalString.ToArray()
.Where(w => char.IsLetter(w))
.Select(s => ((int)s).ToString()));
}
private static string OnlyNumbers(string originalString)
{
if (string.IsNullOrWhiteSpace(originalString)) return originalString;
return new string(originalString.Where(w => char.IsDigit(w)).ToArray());
}
public static string OnlyNumbersWithRegex(string originalString)
{
return Regex.Replace(originalString, #"[^\d]", string.Empty);
}
}
}
string t = "";
foreach (char c in Properties.Settings.Default.password)
{
if (IsNumber(x)) t += System.Convert.ToInt32(c).ToString();
else
{
t += c.ToString();
}
}
Moreover, if you just want to get rid off '-' the use this code: t =String.Replace(t, '-');

How can I split a string like "12-15" into two numbers?

My front-end application sends strings that look like this:
"12-15"
to a back-end C# application.
Can someone give me some pointers as to how I could extract the two numbers into two variables. Note the format is always the same with two numbers and a hyphen between them.
string stringToSplit = "12-15";
string[] splitStringArray;
splitStringArray = stringToSplit.Split('-');
splitStringArray[0] will be 12
splitStringArray[1] will be 15
Split the string into parts:
string s = "12-15";
string[] num = s.Split('-');
int part1 = Convert.ToInt32(num[0]);
int part2 = Convert.ToInt32(num[1]);
int[] numbers = "12-15".Split('-')
.Select(x => {
int n;
int.TryParse(x, out n);
return n;
})
.ToArray();
We call Split on a string instance. This program splits on a single character
string s ="12-15";
string[] words = s.Split('-');
foreach (string word in words)
{
int convertedvalue = Convert.ToInt32(word );
Console.WriteLine(word);
}
string[] ss= s.Split('-');
int x = Convert.ToInt32(ss[0]);
int y = Convert.ToInt32(ss[1]);
more info
You can use the below code to split and it will return string for each value, then you can typecast it to any type you wish to ...
string myString = "12-15-18-20-25-60";
string[] splittedStrings = myString.Split('-');
foreach (var splittedString in splittedStrings)
{
Console.WriteLine(splittedString + "\n");
}
Console.ReadLine();
Here is the correct version without the wrong code
string textReceived = "12-15";
string[] numbers = textReceived.Split('-');
List<int> numberCollection = new List<int>();
foreach (var item in numbers)
{
numberCollection.Add(Convert.ToInt32(item));
}
String numberString = "12-15" ;
string[] arr = numberString.Split("-");
Now you will get a string array , you can use parsing to get the numbers alone
int firstNumber = Convert.ToInt32(arr[0]);
Helpful answer related to parsing :
https://stackoverflow.com/a/199484/5395773
You could convert that string explicitly to an integer array using Array.ConvertAll method and access the numbers using their index, you can run the below example here.
using System;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
var number = "12-15";
var numbers = Array.ConvertAll(number.Split('-'), int.Parse);
Console.WriteLine(numbers[0]);
Console.WriteLine(numbers[1]);
}
}
}
Or you can explicitly convert the numeric string using int.Parse method, the int keyword is an alias name for System.Int32 and it is preffered over the complete system type name System.Int32, you can run the below example here.
using System;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
var number = "12-15";
var numbers = number.Split('-');
var one = int.Parse(numbers[0]);
var two = int.Parse(numbers[1]);
Console.WriteLine(one);
Console.WriteLine(two);
}
}
}
Additional read: Please check int.Parse vs. Convert.Int32 vs. int.TryParse for more insight on parsing the input to integer
string str = null;
string[] strArr = null;
int count = 0;
str = "12-15";
char[] splitchar = { '-' };
strArr = str.Split(splitchar);
for (count = 0; count <= strArr.Length - 1; count++)
{
MessageBox.Show(strArr[count]);
}

Find and Replace RegEx with wildcard search and addition of value

The below code is from my other questions that I have asked here on SO. Everyone has been so helpful and I almost have a grasp with regards to RegEx but I ran into another hurdle.
This is what I basically need to do in a nutshell. I need to take this line that is in a text file that I load into my content variable:
X17.8Y-1.Z0.1G0H1E1
I need to do a wildcard search for the X value, Y value, Z value, and H value. When I am done, I need this written back to my text file (I know how to create the text file so that is not the problem).
X17.8Y-1.G54G0T2
G43Z0.1H1M08
I have code that the kind users here have given me, except I need to create the T value at the end of the first line, and use the value from the H and increment it by 1 for the T value. For example:
X17.8Y-1.Z0.1G0H5E1
would translate as:
X17.8Y-1.G54G0T6
G43Z0.1H5M08
The T value is 6 because the H value is 5.
I have code that does everything (does two RegEx functions and separates the line of code into two new lines and adds some new G values). But I don't know how to add the T value back into the first line and increment it by 1 of the H value. Here is my code:
StreamReader reader = new StreamReader(fDialog.FileName.ToString());
string content = reader.ReadToEnd();
reader.Close();
content = Regex.Replace(content, #"X[-\d.]+Y[-\d.]+", "$0G54G0");
content = Regex.Replace(content, #"(Z(?:\d*\.)?\d+)[^H]*G0(H(?:\d*\.)?\d+)\w*", "\nG43$1$2M08"); //This must be created on a new line
This code works great at taking:
X17.8Y-1.Z0.1G0H5E1
and turning it into:
X17.8Y-1.G54G0
G43Z0.1H5M08
but I need it turned into this:
X17.8Y-1.G54G0T6
G43Z0.1H5M08
(notice the T value is added to the first line, which is the H value +1 (T = H + 1).
Can someone please modify my RegEx statement so I can do this automatically? I tried to combine my two RegEx statements into one line but I failed miserably.
Update1: Stephen in the comments below suggests, "there's no arithmetic operators in regex, you'll need to use a group to pull out the H value, turn it into an int, add one and build a new string.". But I have no idea on how to do this in C# code.
The easiest way to do this is with a simple program that uses a few Regex patterns that capture (named) groups, I had a little spare time so here you go:
Program.cs
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
const string InputFileName = #"input.txt";
const string OutputFileName = #"output.txt";
List<Line> parsedLineList = new List<Line>();
using (StreamReader sr = new StreamReader(InputFileName))
{
string inputLine;
int lineNum = 0;
while ((inputLine = sr.ReadLine()) != null)
{
lineNum++;
Line parsedLine = new Line(inputLine);
if (parsedLine.IsMatch)
{
parsedLineList.Add(parsedLine);
}
else
{
Debug.WriteLine("Line {0} did not match pattern {1}", lineNum, inputLine);
}
}
}
using (StreamWriter sw = new StreamWriter(OutputFileName))
{
foreach (Line line in parsedLineList)
{
sw.WriteLine(line.ToString());
}
}
}
}
}
With input.txt containing:
X17.8Y-1.Z0.1G0H1E1
this program creates output.txt containing:
X17.8Y-1.G54G0T2G43Z0.1H1M08
The above code in Program.cs requires the following simple Line and Fragment class definitions:
Line.cs
namespace Fragments
{
class Line
{
private readonly static Regex Pattern =
new Regex(#"^(?<X>X[^Y]+?)(?<Y>Y[^Z]+?)(?<Z>Z[^G]+?)(?<G>G[^H]+?)(?<H>H[^E]+?)(?<E>E[^$])$");
public readonly string OriginalText;
public string Text
{
get
{
return this.X.ToString() + this.Y.ToString() + this.G54.ToString() + this.G.ToString() + this.T.ToString() + Environment.NewLine +
this.G43.ToString() + this.Z.ToString() + this.H.ToString() + this.M08.ToString();
}
}
public readonly bool IsMatch;
public Fragment X { get; set; }
public Fragment Y { get; set; }
public readonly Fragment G54 = new Fragment("G54");
public Fragment G { get; set; }
public Fragment T { get; set; }
public readonly Fragment G43 = new Fragment("G43");
public Fragment Z { get; set; }
public Fragment H { get; set; }
public readonly Fragment M08 = new Fragment("M08");
public Fragment E { get; set; }
public Line(string text)
{
this.OriginalText = text;
Match match = Line.Pattern.Match(text);
this.IsMatch = match.Success;
if (match.Success)
{
this.X = new Fragment(match.Groups["X"].Value);
this.Y = new Fragment(match.Groups["Y"].Value);
this.G = new Fragment(match.Groups["G"].Value);
this.Z = new Fragment(match.Groups["Z"].Value);
this.H = new Fragment(match.Groups["H"].Value);
this.E = new Fragment(match.Groups["E"].Value);
this.T = new Fragment('T', this.H.Number + 1.0);
}
}
public override string ToString()
{
return this.Text;
}
}
}
Fragment.cs
namespace Fragments
{
class Fragment
{
private readonly static Regex Pattern =
new Regex(#"^(?<Letter>[A-Z]{1})(?<Number>.+)$");
public readonly string Text;
public readonly bool IsMatch;
public readonly char Letter;
public readonly double Number;
public Fragment(string text)
{
this.Text = text;
Match match = Fragment.Pattern.Match(text);
this.IsMatch = match.Success;
if (match.Success)
{
this.Letter = match.Groups["Letter"].Value[0];
string possibleNumber = match.Groups["Number"].Value;
double parsedNumber;
if (double.TryParse(possibleNumber, out parsedNumber))
{
this.Number = parsedNumber;
}
else
{
Debug.WriteLine("Couldn't parse double from input {0}", possibleNumber);
}
}
else
{
Debug.WriteLine("Fragment {0} did not match fragment pattern", text);
}
}
public Fragment(char letter, double number)
{
this.Letter = letter;
this.Number = number;
this.Text = letter + number.ToString();
this.IsMatch = true;
}
public override string ToString()
{
return this.Text;
}
}
}
Create a new C# Console Application project, add these three files, update your using statements and you're ready to go. You can very easily alter the code in Program.cs to read the input and output filenames from Main's command line arguments to make the program reusable.
I'm not sure you can do this just with Regular Expressions, and even in case you can, thinking on maintainability of the code, I wouldn't implement it that way. What you can easily do with RegEx, is to capture the pieces you need into groups, and from those create the output expression.
Here's the code for that:
System.Text.StringBuilder content = new System.Text.StringBuilder();
using (var reader = new StreamReader(fDialog.FileName.ToString()))
{
string line = reader.ReadLine();
while (line != null)
{
var matchingExpression = Regex.Match(line, #"(X[-\d.]+)(Y[-\d.]+)(Z(?:\d*\.)?\d+)[^H]*G0H((?:\d*\.)?\d+)\w*");
content.AppendFormat(
System.Globalization.CultureInfo.InvariantCulture,
"{0}{1}G54G0T{2}\n",
matchingExpression.Groups[0].Value,
matchingExpression.Groups[1].Value,
Int32.Parse(matchingExpression.Groups[3].Value) + 1);
content.AppendFormat(
System.Globalization.CultureInfo.InvariantCulture,
"G43{0}H{1}M08\n",
matchingExpression.Groups[2].Value,
matchingExpression.Groups[3].Value);
line = reader.ReadLine();
}
}
And to get the output string you should do:
content.ToString();

Input string was not in correct format

static void Main(string[] args)
{
//read in the file
StreamReader convert = new StreamReader("../../convert.txt");
//define variables
string line = convert.ReadLine();
int conversion;
int numberIn;
float conversionFactor;
Console.WriteLine("Enter the conversion in the form (amount,from,to)");
String inputMeasurement = Console.ReadLine();
string[] inputMeasurementArray = inputMeasurement.Split(',');
while (line != null)
{
string[] fileMeasurementArray = line.Split(',');
if (fileMeasurementArray[0] == inputMeasurementArray[1])
{
if (fileMeasurementArray[1] == inputMeasurementArray[2])
{
Console.WriteLine("{0}", fileMeasurementArray[2]);
}
}
line = convert.ReadLine();
//convert to int
numberIn = Convert.ToInt32(inputMeasurementArray[0]);
conversionFactor = Convert.ToInt32(fileMeasurementArray[2]);
conversion = (numberIn * conversionFactor);
}
Console.ReadKey();
}
On the line conversionFactor = Convert.ToInt32(fileMeasurementArray[2]);, I am getting an error saying "Input string was not in correct format". Please help!
The text file consists of the following:
ounce,gram,28.0
pound,ounce,16.0
pound,kilogram,0.454
pint,litre,0.568
inch,centimetre,2.5
mile,inch,63360.0
You are trying to convert a float to an int.
Define conversionFactor as a double
also the variable conversion needs to be a double aswell.
like so
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace measurementConverter {
class Program
{
static void Main(string[] args)
{ //read in the file
StreamReader convert = new StreamReader("../../convert.txt");
//define variables
string line = convert.ReadLine();
double conversion;
int numberIn;
double conversionFactor;
Console.WriteLine("Enter the conversion in the form (amount,from,to)");
String inputMeasurement = Console.ReadLine();
string[] inputMeasurementArray = inputMeasurement.Split(',');
while (line != null)
{
string[] fileMeasurementArray = line.Split(',');
if (fileMeasurementArray[0] == inputMeasurementArray[1])
{
if (fileMeasurementArray[1] == inputMeasurementArray[2])
{
Console.WriteLine("{0}", fileMeasurementArray[2]);
}
}
line = convert.ReadLine();
//convert to int
numberIn = Convert.ToInt32(inputMeasurementArray[0]);
conversionFactor = Convert.ToDouble(fileMeasurementArray[2]);
conversion = (numberIn * conversionFactor);
}
Console.ReadKey();
}
}
}
According to the line of the text file, fileMeasurementArray[2] will be 28.0 pound. This cannot be converted to an int. You should remove the string and keep only the number 28.0.
UPDATE: the question was updated and the line of text file corrected. So my previous answer does'nt make sense anymore.
The problem occurs probably because you are trying to convert a float to an int.
'28.0 pound' isn't an integer. I'd imagine that's where your problem lies.
numberIn and conversionFactor are floats, not Ints. Use:
float numberIn;
float conversionFactor;
...
//convert to float
numberIn = Convert.ToSingle(inputMeasurementArray[0]);
conversionFactor = Convert.ToSingle(fileMeasurementArray[2]);

Categories

Resources