непонятная ошибка в программе

using System;
using System.Text.RegularExpressions;


public static class Kata
{
    public static void Main(string[] args)
    {
        Console.WriteLine(DuplicateEncode("(( @"));
    }
    public static string DuplicateEncode(string word)
    {
        string str = "";
        foreach (char i in word.ToLower())
        {
           /* Console.WriteLine(i+i.ToString());*/  
            if (i.ToString() != "(" || i.ToString() != ")")
            {
                if ((Regex.Matches(word, i.ToString()).Count) == 1)
                {
                    str += "(";
                }
                else
                {
                    str += ")";
                }
            }
        }
        return str;
    }
}

код должен возвращать строку из скобок, которые расставляются по следующему принципу - если буква/знак/пробел встречаются 1 раз ставится "(", если больше одного раза, ставится ")" но при обработке строки "(( @" компилятор требует закрыть скобки. почему?


Ответы (1 шт):

Автор решения: Daniil Loban

Как не банально прозвучит, но ошибка в вашей логике. Я вижу что Вы пытались избежать обработки скобок, но тут Вы допустили небольшую но повлиявшую на результат оплошность. Дело в том что проверка через || это настоящая лазейка для бага. Чтобы ее прикрыть достаточно заменить || на &&.

Давайте попробуем на примере собак, кошек и попугаев. Собак и кошек мы не хотим пропускать.

if (animal.type != "собака" || animal.type != "кошка" ) {
   // какой-то код
} 

Теперь представьте что у нас на входе собака, первая часть условия явно запретит

animal.type != "собака" // false

Но вторая разрешит ведь

"собака" != "кошка" // true

а мы обрабатываем || т.е. если хоть одна часть true, то мы выполняем тело условия.

В случае если мы используем && пройдут только попугаи.

Что касается самой ошибки, она не непонятная, просто в регулярках которые Вы пытались использовать скобки - это часть синтаксиса, если они не экранированы, по этой причине Вы и получали ошибку, это ошибка паттерна регулярки, скобки в регулярках отвечают за группу.

Иными словами ошибку вызывает такая запись:

Regex.Matches(word, "(").Count == 1

А такая бы не вызвала:

Regex.Matches(word, "\(").Count == 1 // с экранированием

Как подсказал @AlexanderPetrov в комментарии код можно было бы записать таким образом:

using System;
using System.Text.RegularExpressions;

public static class Kata
{
    public static void Main(string[] args)
    {
        Console.WriteLine(DuplicateEncode("(( @"));
    }
    public static string DuplicateEncode(string word)
    {
        string str = "";
        foreach (char i in word.ToLower())
        {
            if ((Regex.Matches(word, Regex.Escape(i.ToString())).Count) == 1)
            {
                str += "(";
            }
            else
            {
                str += ")";
            }
        }
        return str;
    }
}

и результат был бы таким:))((

→ Ссылка