C#, добавление лидирующих нолей к строковому представлению числа.

Преамбула

Задача опять же учебная, но может пригодиться и в реальной программе. Итак, нам даны числа, скажем, от 1 до 1000, необходимо вывести их на экран или в файл последовательно, добавив лидирующие ноли, исходя из максимального числа. Если максимум 1000, то числа должны быть выведены так:
0001
0002
0003
...
0100
0101
0102
...
1000

Если максимум 100, то:

001
002
...
099
100

Решение

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

int maxnumber = 1998;

Далее, понадобится получить количество цифр числа. Это мы уже делали, причем разными способами (копия), выбираем подходящий.

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

public static int CountDigitsRec(int n)
{
    n = (int)Math.Abs(n);
    if (n <= 9)
    {
        return 1;
    }
    else
    {
        return CountDigitsRec(n / 10) + 1;
    }
}

В основной программе получаем количество цифр числа:

int maxdigits = AddLZ.CountDigitsRec(maxnumber);

Далее в цикле перебираем все числа, и скармливаем их функции, которая будет добавлять лидирующие ноли (AddLZ.AddLeaderZeroString(maxdigits, i));

for (int i = 0; i <= maxnumber ; i++)
{
    string Result = AddLZ.AddLeaderZeroString(maxdigits, i);
    //...
}

На вход функции подается два параметра — максимальное количество цифр и текущее число.

Внутри функции

Получаем строковое представление текущего числа:

string scurnum = ((int)Math.Abs(curnum)).ToString();

Получаем длину строки из лидирующих нолей, которая должна быть равна количеству цифр максимального числа, минус длина (количество цифр) текущего числа. Оно получено выше.

int LenLZ = maxnum - scurnum.Length;

Далее, надо сформировать строку нужной длины из одного символа ('0') (копия):

StringBuilder sb = new StringBuilder(maxnum);
for (int i = 0; i < LenLZ; i++)
{
    sb.Append('0');
}

Далее добавляем строковое представление текущего числа:

sb.Append(scurnum);

И возвращаем значение:

return sb.ToString();

Функция целиком

public static string AddLeaderZeroString(int maxnum, int curnum)
{
    string scurnum = ((int)Math.Abs(curnum)).ToString();
    int LenLZ = maxnum - scurnum.Length;

    StringBuilder sb = new StringBuilder(maxnum);
    for (int i = 0; i < LenLZ; i++)
    {
        sb.Append('0');
    }
    sb.Append(scurnum);

    return sb.ToString();
}

Исходники

Тестовый пример на GitHub
Класс AddLZ

Карельские коты получили книгу Алины Витухновской

Завтра приедет котокурьер из милой котокомпании и доставит книжку заказчику и котам из ЮВА. Котокомпанию нам рекламировать нельзя, т.к. права такого не имею. Но доставляют быстро, 15 рабочих дней максимум по всему миру. Карельские коты им делали сайт, так что у них кроме гонорара еще три промокода на бесплатную доставку по всей планете. Уже два.

C#, сгенерировать строку нужной длины из одного символа.

Преамбула

Продолжаем задачки по генерации всяких паттернов. Недавно мы генерировали массив, заполненный одним значением (копия). Теперь будем генерировать строку из одного символа, но нужной длины. Строку из случайных символов мы уже делали

Теперь будем делать строку-паттерн из одного заранее заданного символа.

Заведем три переменных:

int strlen = 100000; // длинна строки
string symbol = "a"; // символ заполнения
string Result = ""; // результирующая строка

«В лоб», с использованием стандартной конкатенации строк

Т.е. в цикле for, используя конструкцию s=s+"a":

for (int i = 0; i < strlen; i++)
{
    Result = Result + symbol;
}

С использованием StringBuilder

StringBuilder sb = new StringBuilder(strlen);
for (int i = 0; i < strlen; i++)
{
    sb.Append(symbol);
}

Result = sb.ToString();

Тесты

For + standart string concatenation: 00:00:05.7493288
Test For + StringBuilder.Append: 00:00:00.0030001

Даже на 10000 символов видна разница, здесь показана на 100000, а 500000 для for я вообще не дождался.

Примечание: Тут мы делали строку заданной длины из одного паттерна, поэтому StringBuilder был уместен, т.к. он напрямую работает с памятью, и не использует механизм .NET, которому нужно строку скопировать, а потом добавить символ. См. ссылку ниже.

Эффективная конкатенация строк в .NET

Тестовый пример на GitHub

C#, Количество цифр (разрядов) числа.

Пост из серии «спрашивали — отвечаем», довольно стандартная учебная задача, никакой особой военной хитрости нет, но раз уж, что б нет то.

Преобразование числа в строку и подсчет символов

Самый простой, дубовый, но самый медленный по времени выполнения способ. Обычно в школе за него по рукам бьют 🙂

static int CountDigitsStr(int n)
{
    return ((int)Math.Abs(n)).ToString().Length;
}

Получаем модуль числа [(int)Math.Abs(n)], чтоб исключить ситуацию, если в n окажется отрицательное число, преобразуем число в строку и получаем количество символов в строке, т.е. количество цифр числа.

Подсчет цифр делением нацело

Способ заключается в том, чтобы последовательно делить число на 10, оставляя от деления целую часть, пока целая часть не станет равна 0.

Можно сделать в двух вариантах.

В цикле:

static int CountDigitsCycle(int n)
{
    n = (int)Math.Abs(n); //берем модуль числа
    int count = 0; //заводим счетчик
    if (n == 0) count = 1; // n == 0? Цифра одна.
    while (n != 0) //пока n не равно 0
    {
        n = n / 10; //делим число на 10
        count++; //прибавляем счетчик
    }
    return count;
}

Какая-то специальная функция для деления нацело в C# не нужна, при делении переменной цельночисленного типа (byte, sbyte, short, ushort, int, uint, long, ulong) на целое число или цельночисленную переменную, результатом будет целое число, т.е. деление нацело произойдет автоматически.

Рекурсией:

static int CountDigitsRec(int n)
{
    n = (int)Math.Abs(n);
    if (n <= 9)
    {
        return 1;
    }
    else
    {
       return CountDigitsRec(n / 10) + 1;
    }
}

Использование десятичного логарифма.

static int CountDigitsLog10(int n)
{
    if (n == 0)
    {
        return 1;
    }
    return (int)Math.Log10(Math.Abs(n)) + 1;
}