Данная строка преобразована в шестнадцатеричный формат 4-байтовыми фрагментами C #

Я начинающий энтузиаст и уже некоторое время изучаю проблему в своем коде. Мой код уродлив и неэффективен во многом потому, что я неопытен. Однако мне это нравится.

Проблема: учитывая строку, я могу успешно преобразовать ее в Hex. Однако я хочу, чтобы данная строка (несмотря на ее длину) была преобразована в 4-байтовые фрагменты в шестнадцатеричном формате. В ситуациях, когда строка больше байта, но меньше 4 байтов, я хотел бы добавить «0» справа от строки. Я обнаружил, что у меня только частичный успех, пока я манипулирую параметром totalWidth для метода PadRight. Как я могу достичь того, что ищу, не имея лишних кусков с нулями?

Пожалуйста, посмотрите точный пример кода, который я использую ниже:

// create a char array using the string provided to the encoder method
        char[] arrayCharValues = strMessage.ToCharArray();

        // create stringbuilder object
        StringBuilder sb = new StringBuilder();

        // iterate through each char and convert it to int32 then to Hex then append to stringbuilder object.
        foreach (char c in arrayCharValues)
        {
            // convert char to int32
            int intCharToNumVal = Convert.ToInt32(c);
            // convert int32 to hex
            string strNumToHexVal = String.Format("{0:X2}", intCharToNumVal);
            // append hex value to string builder object
            sb.Append(strNumToHexVal);
        }

        string s = sb.ToString();

        if (s.Length % 8 == 0)
        {
            var list = Enumerable
            .Range(0, s.Length / 8)
            .Select(i => s.Substring(i * 8, 8))
            .ToList();
            var res = string.Join(" ", list);

            // DEBUG: echo results for testing.
            Console.WriteLine("");
            Console.WriteLine("String provided: {0}", strMessage);
            Console.WriteLine("String provided total length: {0}", s.Length);
            Console.WriteLine("Hex equivalent of string provided: {0}", sb.ToString());
            Console.WriteLine("Hex in 8-digit chunks: {0}", res.ToString());
            Console.WriteLine("======================================================");
        }
        else
        {
            int intDivisibleByEight = s.Length % 8;
            int intPadRight = (8 - intDivisibleByEight) / 2;
            char pad = '0';
            //BUG: doesn't know how to handle anything over 16 bits. If I use an input string of "coolsssss" i get 636F6F6C 73737373 73000000 00000000
            //BUG: <cont'd> if i use the same input string and change the PadRight(32,pad) to PadRight(16,pad) i get 636F6F6C 73737373 and the final chunk is ignored.
            //BUG: <cont'd> I want it to work as it does with the PadRight(32, pad) method but, I want it to ignore the all zeros chunk(s) that may follow.
            //NOTE: int totalWidth = the number of characters i nthe resulting string, equal to the number of original characters plus any additional padding characters.
            s = s.PadRight(32, pad);
            var list = Enumerable
                .Range(0, s.Length / 8)
                .Select(i => s.Substring(i * 8, 8))
                .ToList();
            var res = string.Join(" ", list);

            // DEBUG: echo results for testing.
            Console.WriteLine("");
            Console.WriteLine("String provided: {0}", strMessage);
            Console.WriteLine("String provided total length: {0}", s.Length);
            Console.WriteLine("Hex equivalent of string provided: {0}", sb.ToString());
            Console.WriteLine("Hex in 8-digit chunks: {0}", res.ToString());
            Console.WriteLine("======================================================");
        }

person Gabriel Alicea    schedule 18.11.2015    source источник
comment
почему бы не дополнить строку ввода перед ее преобразованием? Тогда ваша функция конвертера может просто предположить, что все строки будут кратными (например, 8), и вам не нужно беспокоиться о таких разделениях кода.   -  person Sam Axe    schedule 18.11.2015
comment
Спасибо за совет. Я попробую это, а также пример, приведенный ниже.   -  person Gabriel Alicea    schedule 18.11.2015


Ответы (1)


Хотя все эти .Range.Select забавны, иногда проще вернуться к простому старому циклу. Шестнадцатеричная строка не нужна для результатов с фрагментами, я добавил его, чтобы показать разницу, когда фрагменты не нужны.

    string strMessage = "coolsssss";


    string hexedString = string.Join("", strMessage.Select(c => String.Format("{0:X2}", (int)c)))
                            .PadRight((strMessage.Length + 3) / 4 * 8, '0');


    StringBuilder sb = new StringBuilder(strMessage.Length * 9 / 4 + 10);
    int count = 0;
    foreach (char c in strMessage)
    {
        if (count == 4)
        {
            sb.Append(" ");
            count = 0;
        }
        sb.Append(String.Format("{0:X2}", (int)c));
        count++;
    }
    for (int i = 0; i < (4 - count) % 4; ++i)
    {
        sb.Append("00");
    }


    // DEBUG: echo results for testing.
    Console.WriteLine("");
    Console.WriteLine("String provided: {0}", strMessage);
    Console.WriteLine("Hex equivalent of string provided: {0}", hexedString);
    Console.WriteLine("Hex in 8-digit chunks: {0}", sb.ToString());
    Console.WriteLine("======================================================");

РЕДАКТИРОВАТЬ:

На вопрос @GabrielAlicea я добавил некоторые пояснения.

new StringBuilder(strMessage.Length * 9 / 4 + 10);

Это в основном создает StringBuilder с предварительно выделенной памятью до необходимого размера. Мы получаем 8 цифр из 4 букв плюс пробел, отсюда 9/4. Плюс немного отступов до четырех. Расчет неточный, при желании можно сделать именно это. Это хорошая привычка заранее выделять динамически растущие объекты, такие как List, StringBuilder, Dictionary ... если вы заранее знаете размер. Список, например, использует массив внутри. При заполнении он получает массив вдвое большего размера и копирует в него все. Когда Вы заранее знаете необходимый размер, это пустая трата времени. С StringBuilder это сложнее (и зависит от версии .net), но предварительное выделение в любом случае - хорошая идея.

(int i = 0; i < (4 - count) % 4; ++i)

Счетчик - это количество букв в последнем блоке. Мы добавляем по два нуля на каждую пропущенную букву, это означает (4 - count) раз. Он работает, за исключением пустой строки, где count равно 0, а (4 - count) равно 4. Поэтому я добавил % 4 для обработки этой конкретной ситуации.

В свой код вы, наверное, хотели написать это:

int intPadRight = 8 - intDivisibleByEight;

и это:

s = s.PadRight(s.Length + intPadRight, pad);

Но вы можете добавить % 8 в intPadRight и полностью удалить это if (s.Length % 8 == 0):

    ...
    string s = sb.ToString();

    int intDivisibleByEight = s.Length % 8;
    int intPadRight = (8 - intDivisibleByEight) % 8;
    char pad = '0';
    s = s.PadRight(s.Length + intPadRight, pad);
    var list = Enumerable
        .Range(0, s.Length / 8)
        .Select(i => s.Substring(i * 8, 8))
        .ToList();
    var res = string.Join(" ", list);

    // DEBUG: echo results for testing.
    Console.WriteLine("");
    Console.WriteLine("String provided: {0}", strMessage);
    Console.WriteLine("String provided total length: {0}", s.Length);
    Console.WriteLine("Hex equivalent of string provided: {0}", sb.ToString());
    Console.WriteLine("Hex in 8-digit chunks: {0}", res.ToString());
    Console.WriteLine("======================================================");
person Antonín Lejsek    schedule 18.11.2015
comment
Это именно то, что я хочу. Большое тебе спасибо. Не могли бы вы сказать мне, что я делал не так в своем коде? Я хочу узнать столько же, сколько и совета. Спасибо еще раз! - person Gabriel Alicea; 18.11.2015
comment
Кроме того, не могли бы вы объяснить, что происходит при создании объекта StringBuilder? (strMessage.Length * 9/4 + 10) Кроме того, не могли бы вы просто кратко рассказать о том, что делает следующее? (int i = 0; i ‹(4 - count)% 4; ++ i) Заранее спасибо ... - person Gabriel Alicea; 18.11.2015
comment
Спасибо вам за разъяснение! - person Gabriel Alicea; 19.11.2015