Проверить восьмеричное число

Является ли это допустимым способом проверки, содержит ли строка только восьмеричные числа?

public static bool IsOctal(String toCheck)
{
    if (toCheck.Contains(" "))
    {
        return false;
    }
    int parsedtoCheck;
    var parseOk = int.TryParse(toCheck, out parsedtoCheck);
    if (!parseOk)
    {
        return false;
    }
    if (Convert.ToInt32(toCheck, 8) != parsedtoCheck)
    {
        return false;
    }
    return true;
}

person benba    schedule 13.08.2014    source источник
comment
В соответствии с этим вопросом о переполнении стека похоже, что у вас может быть уже есть ответ (не то, чтобы я выступал за исключение исключений в качестве теста на преобразование)   -  person clarkitect    schedule 14.08.2014
comment
@jeffdot: ожидание никогда не должно вызываться, потому что toCheck является допустимым целым числом после TryParse, или я что-то пропустил?   -  person benba    schedule 14.08.2014
comment
Возможно: try{Convert.ToInt32(toCheck, 8);return true;}catch{return false}   -  person Tim Schmelter    schedule 14.08.2014
comment
@benba: Нет, потому что 9 преуспеет в int.TryParse, но не в Convert.ToInt32(toCheck, 8). И другие значения (например, 10), которые должны быть успешными, вернут false, потому что восьмеричное 10 не равно десятичному 10...   -  person Jon Skeet    schedule 14.08.2014
comment
@JonSkeet: первое, что я получил, перечитал их в документации. Но второй, Convert.ToInt32(10, 8), возвращает Int32 10, и по сравнению с другими 10 он должен быть таким же? Я думал, С# не знает никакого представления для восьмеричных чисел?   -  person benba    schedule 14.08.2014
comment
@benba: Как вы думаете, что делает Convert.ToInt32("10", 8)? Дело не в том, что C# знает о восьмеричной системе, а в том, что Convert.ToInt32(string, int) знает об этом. Convert.ToInt32("10", 8) вернет 8, потому что это значение 10 интерпретируется как восьмеричное значение.   -  person Jon Skeet    schedule 14.08.2014
comment
спать пора ;)   -  person benba    schedule 14.08.2014


Ответы (4)


Совершенно не ясно, чего пытается достичь ваш текущий подход, поскольку он преобразуется как в десятичный, так и в восьмеричный. Если вы просто хотите проверить, содержит ли строка только цифры 0-7, вероятно, проще всего использовать регулярное выражение:

using System;
using System.Text.RegularExpressions;

class Test
{
    public static void Main(string[] args)
    {
        // Do you want this to be valid or not?
        Console.WriteLine(IsOctal(""));
        Console.WriteLine(IsOctal("012"));
        Console.WriteLine(IsOctal("890"));
        Console.WriteLine(IsOctal("abc"));
        // Do you want this to be valid or not?
        Console.WriteLine(IsOctal("-0123"));
    }

    private static bool IsOctal(string text)
    {
        return Regex.IsMatch(text, "^[0-7]+$");
    }
}

Это предполагает, что:

  • Вас интересуют только неотрицательные значения (поэтому нам не нужно принимать начальный -)
  • Пустая строка не должна считаться действительной
  • После этого вам не нужно фактическое значение — оно может быть сколь угодно длинным.
person Jon Skeet    schedule 13.08.2014
comment
И я бы подумал, что вы пойдете с подходом linq. - person gunr2171; 14.08.2014
comment
@ gunr2171: Хотя я всегда думаю об этом варианте, в данном случае я думаю, что это будет менее читабельно, чем регулярное выражение. - person Jon Skeet; 14.08.2014
comment
Или даже 012.All(x =› x›='0' && x‹'8') - person dotNET; 14.08.2014

Если важна производительность, вы можете сравнить решение регулярного выражения со сканированием (адаптировано из этой записи):

private bool IsOctal(IEnumerable<char> chars)
{
    bool isOctal;
    foreach (var c in chars)
    {
        isOctal = (c >= '0' && c <= '7');

        if (!isOctal)
            return false;
    }
    return true;
}

И, как указывалось в предыдущих ответах, это делает некоторые предположения о ваших числовых значениях.

person Geoff    schedule 13.08.2014

Это сильно зависит от ваших правил проверки. Не существует единственно правильного определения набора символов восьмеричного числа. Иногда начинать с 0 обязательно. Я считаю, что в Python вы можете использовать _ в качестве разделителя цифр. Отрицательные? Научная/инженерная нотация? Десятичные?

Да, некоторые из них странные, но дело в том, что это зависит от того, где вы их используете.

Вам нужно, чтобы его можно было анализировать на С#? Тогда int.TryParse() - это путь. Вы только что проанализировали его и получили успех или неудачу. Нужно ли передавать его в виде строки другому сервису/API? Посмотрите правила проверки этой службы/API. Также не перепроверяйте, как вы делаете выше, это просто сбивает с толку, что такое реальный допустимый набор символов, и если вы не доверяете своей среде выполнения, вы можете также начать создавать ту, которой вы доверяете (не делайте это, это была шутка).

Узнайте, каковы настоящие правила и требования валидации, и ваш ответ будет ясен. Не переусердствуйте.

person Alowishus Drunkwater    schedule 13.08.2014

Вот решение linq:

public static void Main(string[] args)
{
    var a = IsOctal("023"); //true
    var b = IsOctal("678"); //false
}

public static bool IsOctal(string text)
{
    //get a collection of chars that each text element can be
    var possibleChars = Enumerable.Range(0, 8)
        .Select(x => x.ToString()[0]);

    //"are there any chars in 'text' that are not in 'possibleChar'?"
    var anyAreInvalid = text
        .Where(x => !possibleChars.Contains(x))
        .Any();

    //return the inverse of your question
    return !anyAreInvalid;
}

Основная работа заключается в операторе Where, который проверяет каждый символ в вашем вводе по списку «допустимых символов».

Это также использует те же предположения из ответа Джона.

person gunr2171    schedule 13.08.2014