.NET String.Format Include Mining Sign in Count для заполнения 0

Я переношу некоторый код C++, который использует _vsnwprintf_s для преобразования чисел в 11-символьные строки. Если число отрицательное, оно все равно возвращает строку из 11 символов.

Мне нужно воспроизвести это поведение на С#. Если я использую:

String.Format("{0:D11}",-30800322);
String.Format("{0:D11}",30800322);

Проблема заключается в том, что отрицательное число приводит к выводу 12 символов, а не 11. То есть оно выводит -00030800322, но я хочу, чтобы оно выводило -0030800322, а 30800322 должно выводить 00030800322.

Я могу решить эту проблему, проверив, является ли число отрицательным, и используя {0:D10} для отрицательных чисел и {0:D11} для положительных чисел, однако мне интересно, есть ли лучший способ более точно воспроизвести версию C++, которая включает знак минус в счетчике.


person Malcolm McCaffery    schedule 14.03.2020    source источник


Ответы (1)


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

var s = -30800322;
var u = 30800322;

<сильный>1. строка.Заменить


Быстрый и простой способ:

Console.WriteLine(string.Format("{0:D11}", s).Replace("-0", "-"));
Console.WriteLine(string.Format("{0:D11}", u).Replace("-0", "-"));

<сильный>2. IFormatProvider


Создайте собственный IFormatProvider. использовать его с функцией string.Format(..):

public class vsnwprintf : IFormatProvider, ICustomFormatter
{
    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        if (arg == null || !int.TryParse(arg.ToString(), out int x))
            return null;

        var f = "{0:D11}";

        if (x < 0)
            return string.Concat("-", string.Format(f, x).Substring(2));
        else
            return string.Format(f, x);
    }

    public object GetFormat(Type formatType)
    {
        return (formatType == typeof(ICustomFormatter)) ? this : null;
    }
}

Использование:

Console.WriteLine(string.Format(new vsnwprintf(), "{0}", s));
Console.WriteLine(string.Format(new vsnwprintf(), "{0}", u));

<сильный>3. ТоСтрока()


Создайте новый класс и переопределите функцию ToString():

public class vsnwprintf
{
    private readonly int Value;
    private readonly int Length;

    private vsnwprintf() { }

    public vsnwprintf(int val, int length) : this()
    {
        Value = val;
        Length = length;
    }

    public override string ToString()
    {
        var f = string.Concat("{0:D", Length, "}");

        if (Value < 0)
            return string.Concat("-", string.Format(f, Value).Substring(2));
        else
            return string.Format(f, Value);
    }
}

Использование:

Console.WriteLine(new vsnwprintf(s, 11));
Console.WriteLine(new vsnwprintf(u, 11));

<сильный>4. Метод расширения


Создайте статический класс и создайте метод расширения для типа int:

public static class Extensions
{
    public static string Tovsnwprintf(this int Value, int Length = 11)
    {
        var f = string.Concat("{0:D", Length, "}");

        if (Value < 0)
            return string.Concat("-", string.Format(f, Value).Substring(2));
        else
            return string.Format(f, Value);
    }
}

Использование:

Console.WriteLine(s.Tovsnwprintf());
Console.WriteLine(u.Tovsnwprintf(11));

Каждый из которых возвращает:

-0030800322
00030800322
person Community    schedule 14.03.2020