Для начала выделим регулярные выражения для чисел и действий:
private const string RegexBr = "\\(([1234567890\\.\\+\\-\\*\\/^%]*)\\)"; // Скобки
private const string RegexNum = "[-]?\\d+\\.?\\d*"; // Числа
private const string RegexMulOp = "[\\*\\/^%]"; // Первоприоритетные числа
private const string RegexAddOp = "[\\+\\-]"; // Второприорететные числа
Теперь метод, который полученную строку разделяет на элементы и рекурсивно их вычисляет:
public static double Parse(string str)
{
// Парсинг скобок
var matchSk = Regex.Match(str, RegexBr);
if (matchSk.Groups.Count > 1)
{
string inner = matchSk.Groups[0].Value.Substring(1, matchSk.Groups[0].Value.Trim().Length - 2);
string left = str.Substring(0, matchSk.Index);
string right = str.Substring(matchSk.Index + matchSk.Length);
return Parse(left + Parse(inner).ToString(CultureInfo.InvariantCulture) + right);
}
// Парсинг действий
var matchMulOp = Regex.Match(str, string.Format("({0})\\s?({1})\\s?({2})\\s?", RegexNum, RegexMulOp, RegexNum));
var matchAddOp = Regex.Match(str, string.Format("({0})\\s?({1})\\s?({2})\\s?", RegexNum, RegexAddOp, RegexNum));
var match = matchMulOp.Groups.Count > 1 ? matchMulOp : matchAddOp.Groups.Count > 1 ? matchAddOp : null;
if (match != null)
{
string left = str.Substring(0, match.Index);
string right = str.Substring(match.Index + match.Length);
return Parse(left + ParseAct(match).ToString(CultureInfo.InvariantCulture) + right);
}
// Парсинг числа
try
{
return double.Parse(str, CultureInfo.InvariantCulture);
}
catch (FormatException)
{
throw new FormatException(string.Format("Неверная входная строка '{0}'", str));
}
}
И последним напишем метод, который непосредственно вычисляет значение действия:
private static double ParseAct(Match match)
{
double a = double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
double b = double.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture);
switch (match.Groups[2].Value)
{
case "+": return a + b;
case "-": return a - b;
case "*": return a * b;
case "/": return a / b;
case "^": return Math.Pow(a, b);
case "%": return a % b;
default: throw new FormatException($"Неверная входная строка '{match.Value}'");
}
}
Такое вот «ненормальное программирование» у меня было. Исходный текст полностью приводить не вижу никакого смысла — вряд ли это кому-нибудь пондобится. Но в любом случае составить класс из трех кусков — дело пары секунд. Спасибо за внимание.
This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.
Комментариев нет:
Отправить комментарий