Nano Hash - криптовалюты, майнинг, программирование

Преобразование строкового массива ASCII в его массив шестнадцатеричных значений

У меня есть массив char, содержащий символы ASCII. Мне нужно знать, как получить шестнадцатеричное значение каждого символа и сохранить его в массиве uint8_t.

Например. если у меня есть

array[5] = "ABCDE"

Результат должен быть

output[5] = {0x41, 0x42, 0x43, 0x44, 0x45}

Я попытался использовать strtol, но это не сработало.

for(unsigned i = 0; i < 32; i++) {
    message[i] = (uint8_t)strtol(&incoming_message[i], NULL, 16);
}

Output:
A 0 0 0 0 0 0 0 0 0 F 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Обновление: это для программы, которую я пишу для Процессор Cortex-M0+. Я не просто просматриваю входящие данные, я обрабатываю эти данные на следующем шаге. Поэтому не используйте printf


  • uint8_t не может содержать шестнадцатеричных значений; и "ABCDE" эквивалентно {0x41,0x42,0x43,0x44,0x45,0}. Просто бросил. (Кроме того, "ABCDE" не вписывается в array[5], так как он имеет 6 элементов, потому что строки заканчиваются NUL, как показано в эквивалентном массиве байтов. 01.08.2018
  • Да. Это просто пример. Но спасибо, что указали на это. 01.08.2018
  • "ABCDE" представляет собой массив из 6 chars, так как к нему добавлен терминатор 0. Я не уверен, жалуется ли компилятор или неявно исправляет char array[5] = "ABCDE";. Однако вы можете получить доступ к первым 5 chars. Ожидаемый результат — это уже соответствующие значения ASCII (как уже указывалось) и sizeof (char) == sizeof (uint8_t). Итак, это можно свести к простой копии: memcpy(output, array, 5);. (Но если вы не можете использовать memcpy() по каким-либо причинам, подойдет и простой цикл for.) 01.08.2018
  • Что касается char array[5] = "ABCDE"; - я проверил это: компиляторы (gcc HEAD 9.0.0, clang HEAD 7.0.0, оба с -pedantic) не жалуются, но исправляют это неявно: Тестировать на Wandbox. (Рано утром, но уже кое-что узнал...) ;-) 01.08.2018
  • @Scheff: array[5] = "ABCDE" особенный. Он определяет (и инициализирует) массив char с пятью элементами (только). Здесь нет 0-терминатора. Это соответствует стандарту C11. 01.08.2018
  • @ Амадан Я упустил из виду, что вы уже упоминали char array[5] против "ABCDE" раньше. Итак, мой другой комментарий может быть интересным, а также примечание по этому поводу. 01.08.2018
  • Спасибо алк. Тем не менее - вам даже не нужен memcpy, просто каст. incoming_message является message. 01.08.2018
  • Вам даже не нужно бросать. Пожалуйста, смотрите мой ответ. 01.08.2018
  • Следовательно, нельзя использовать printf и вывод должен быть ... --› Какая функция вывода приемлема, поскольку вы запрещаете printf()? 01.08.2018
  • @chux Позвольте мне объяснить. Я разрабатываю программное обеспечение для микроконтроллера серии STM32L0, который содержит процессор CortexM0+. Он не содержит трассировки ITM, поэтому не использую printf, поскольку я не могу просматривать данные. Я создаю сообщение с помощью sprintf и отправляю его в блок аппаратного шифрования для шифрования. Я обнаружил, что мне нужно вводить эти данные в виде шестнадцатеричных значений. Я передаю это с помощью радио LoRa и обнюхиваю входящие пакеты данных с помощью приемника. 02.08.2018

Ответы:


1

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

Во-вторых, закодированное значение символов является фактическим значением элементов в вашей строке. Если вы напечатаете десятичное значение 65 (например), используя правильный спецификатор формата, то будет напечатан символ A:

printf("%c\n", 65);  // Will print an A

Точно так же при печати символа 'A' в виде десятичного целого числа будет напечатано значение 65:

printf("%d\n", 'A');  // Will print the value 65

Поэтому все, что вам нужно сделать, это напечатать значения в вашем массиве в правильном формате.


Более того... Все значения на компьютерах за последние несколько десятилетий хранятся в двоичном формате. Все они.

Десятичное, восьмеричное или шестнадцатеричное — это только то, как вы представляете значения. Хранение 0x41, 61, 0101 или 0b01000001 (для компиляторов с расширением двоичной нотации) не имеет значения, поскольку в конце концов будет сохранено двоичное значение. Если вы хотите показать пользователю шестнадцатеричное значение через некоторый вывод, вы должны отформатировать двоичное значение как таковое при печати или записи.

01.08.2018
  • Я думаю, что OPхочет также сохранить hexзначения в массиве uint8_t, как он упомянул. 01.08.2018
  • @Alan Что действительно невозможно (добавлено примечание об этом). 01.08.2018
  • программист Увидел, не подумал! Ваше здоровье. 01.08.2018
  • Спасибо за ваш ответ. Извините, забыл упомянуть, это для встроенной системы. printf у меня недоступен. 01.08.2018
  • @ADGAN Тогда вы, вероятно, используете какой-то другой метод представления значений? Потому что независимо от того, что это просто вопрос презентации. 01.08.2018

  • 2
    1. Если говорить C a char, то это наименьшее доступное целочисленное значение.
    2. Говоря C и ASCII символьный литерал (например, 'A'), это просто другое представление значения int (здесь 65).
    3. Говоря о математике, есть и другие способы представить одно и то же значение, кроме десятичного (с основанием 10). Одним из распространенных является использование основания 16, шестнадцатеричный способ.

    Суммируя вышеизложенное, получается, что:

    int i = 'A';
    char c = i; 
    

    такой же как:

    int i = 65; 
    char c = i; 
    

    и то же, что:

    int i = 0x41; 
    char c = i; 
    

    и то же, что:

    char c = 'A';
    

    и то же, что:

    char c = 65;
    

    и то же, что:

    char c = 0x41;
    

    So

    char a[5] = "ABCDE";
    

    на самом деле это уже целочисленный массив из пяти (маленьких) целых чисел.

    Если напечатать с использованием правильного спецификатора преобразования и модификатора длины, вы увидите, что вам нужно.

    for (size_t i = 0; i < 5; ++i)
    {
      printf("%hhx ", a[i]);
    }
    

    Выход:

    41 42 43 44 45
    

    Чтобы показать читателю, что это должно быть шестнадцатеричным значением, можно было бы префикс значения, используя общепринятую нотацию 0x.

      printf("0x%hhx ", a[i]);
    

    что дало тебе

    0x41 0x42 0x43 0x44 0x45
    

    Если бы вы показали это ребятам из Паскаля, вы, возможно, использовали бы

      printf("$%hhx ", a[i]);
    

    что дало тебе

    $41 $42 $43 $44 $45
    

    Чтобы увидеть самих персонажей только нам:

      printf("%c ", a[i]);
    

    и получить

    A B C D E
    

    Чтобы увидеть десятичные значения, используйте

      printf("%d ", a[i]);
    

    и получить

    65 66 67 68 69
    

    Вывод таков, что все дело в том, как вы представляете ("печатаете") одинаковые значения (содержимое элементов a) . «Преобразование» происходит при создании представления одного и того же значения (путем печати и передачи правильных «инструкций»), то есть только во время вывода.


    Поскольку вы ссылаетесь только на ASCII, это означает, что все значения равны ‹128, поэтому вы можете просто скопировать значения массива, используя цикл

    char src[5] = "ABCDE";
    uint8_t dst[5];
    
    for (size_t i = 0 i < 5; ++i)
    {
      dst[i] = src[i];
    }
    

    или сразу скопировав соответствующий блок памяти

    memcpy(dst, src, 5);
    
    01.08.2018

    3

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

    void hexCon(char str[],char result[][5]){
        int i,check,rem = 0;
        char res[20],res2[20];        
        int len = 0;    
        char temp;          
    
        for(i=0; i < strlen(str) ; i++){
            len=0;
            check = str[i];
            while(check > 0){
            rem = check%16;
            switch(rem){
                case 10:temp='A';break;
                case 11:temp='B';break;
                case 12:temp='C';break;
                case 13:temp='D';break;
                case 14:temp='E';break;
                case 15:temp='F';break;
                default:temp=rem + '0';
            }
            res[len] = temp;       
            check = check /16;
            len++;    
        }
    
        reverse(res,len,res2);  //reversing the digits
        res2[len] = '\0';       //adding null character at the end of string
        strcpy(result[i],res2); //copying all data to result array
        }
    }
    

    где обратная функция:

    void reverse(char str[], int size, char rev[]) 
    {       
        int i=0,j=0;
        for(i=size-1 , j=0 ; i >= 0; i-- , j++ ){
            rev[j] = str[i];
        }    
    }
    

    вы можете назвать это так:

    void main(){    
        char str[]="ABCDE";
        char result[strlen(str)][5];
        int i;
        hexCon(str,result);
        for(i =0 ;i < strlen(str); i++){
            printf("%s\n",result[i]);
        }
    }
    

    используемый алгоритм объясняется здесь: - https://www.permadi.com/tutorial/numDecToHex/< /а>

    Надеюсь это поможет :)

    01.08.2018
  • Как это отвечает на вопрос в целом? 06.08.2018
  • Новые материалы

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

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..