Чтение строки с одного символа на другой - PullRequest
0 голосов
/ 17 февраля 2019

У меня есть следующая строка:

FB: 77: CB: 0B: EC: 09 {W: 0,623413, X: 0,015374, Y: 0,005306, Z:-0,781723}

Я хочу считать значения W, X, Y, Z в виде числа с плавающей запятой / десятичного числа.Значения не всегда имеют одинаковую длину.

Как я могу прочитать эту строку из одного символа в другой, не используя относительные позиции?

Ответы [ 4 ]

0 голосов
/ 17 февраля 2019

Вот еще один пример регулярного выражения, который анализирует число до десятичного числа и включает в себя плюс и минус.

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);

        }
    }
}
0 голосов
/ 17 февраля 2019

Чтобы ответить на ваш вопрос, этот метод будет делать:

int GetIntValue(string input, char prefix)
{
  return int.Parse(input.Substring(input.IndexOf($"{prefix}: ") + 3, 1));
}

Это, однако, вернет 0 для всех ваших входных выборок.Причина, по которой мы анализируем только ноль, заключается в том, что они все равно будут игнорироваться анализатором int.

Если, как я подозреваю, вам нужно не целое число, а вместо полного числа, используйте что-то вроде этого:

decimal GetValue(string input, char prefix)
{
  return decimal.Parse(input.Substring(input.IndexOf($"{prefix}: ") + 3).Split(new[] { ", ", "}" }, StringSplitOptions.None).First());
}

Не стесняйтесь заменить decimal на то, что вы хотитекак.

Назовите это так:

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

Для этого нужно определить местоположение префикса, а затем проанализировать подстроку с начала следующего числа до разделителя (, или }).

0 голосов
/ 17 февраля 2019
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;
    }
0 голосов
/ 17 февраля 2019

Я бы предложил сопоставить «внутреннюю» часть с регулярным выражением, но сначала удалил «внешнюю» часть вручную - просто, чтобы регулярное выражение было как можно более простым.

Вот полный пример сметод, который возвращает результат как Dictionary<string, string>.Непонятно, как вы хотите затем преобразовать заданные вами значения выборки (например, «0,623413») в целые числа, но я бы отнесся к этому как к отдельной задаче от начального анализа.

Я предполагаю, что можно убрать все конечные запятые из значений:

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(','));
    }
}

Вывод:

Key = 'W', Value = '0,623413'
Key = 'X', Value = '0,015374'
Key = 'Y', Value = '0,005306'
Key = 'Z', Value = '-0,781723'

Преобразование этих значений в целые числа может быть простымкак удаление запятых, обрезание начальных нулей, а затем использование int.Parse - но это действительно зависит от того, какие результаты вы хотите получить.

...