Перейти к содержанию
    

Парсинг хекс строки

Здравствуйте !

Столкнулся с тем что в компиляторе не работает функция sscanf и sprintf(компилятор не популярный)

Мне нужно форматировать хекс строку с разными байтными с полубайтными  хекс символами и в uchar hex переменные

Подскажите пожалуйста как можно это сделать так чтобы не городить большой огород 

Спасибо !

 

 

 

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую. Для начала, все-таки, постарайтесь внятнее сформулировать вопрос. А то какая-то каша.

Вам что, нужна функция перевода hex-to-int?

/*
ch - ASCII-символ '0'...'9', 'a'('A')...'f'('F')
*/
static inline s32 hexToInt1(u32 ch) {
  if((ch -= '0') > 9) {
    ch &= ~0x20;
    if((ch -= 17) > 5)
      return -1;
    else ch += 10;
  }
  return ch;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за поддержку!

У меня есть следующая строка принимаемая по юарту "#ААВСС\r"

Где АА, хекс значение от 0 до FF

B, хекс значение от 0 до F

CC, хекс значение от 0 до FF

Мне нужно эти три значения параметров парсировать и положить в 3 переменные типа  unsigned char

Сами строки я кладу по указателю для которого выделили маалоком соответствующий размер 

Также после /r я вставляю доп символ конца строки /0

И после этого применяю sscanf или sprintf

Все данные принимаемые строк через указатель просматриваются 

Но после sscanf и sprintf ,в выходных  переменных отформатированные значения получаются нулевыми

И sscanf возвращает FF, а sprintf не нулевое, меньшее FF

Выделяемую память пока нигде не удаляю

Изменено пользователем addi II

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пишиите на английском. Переводчик на русский очень плохо работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вместо 10-15 строк в эпистолярном жанре Вы могли бы привести 3-4 сторки кода (даже одну), который "не идет" или работает не так, как Вы ожидали.

В частности, соблюдаете ли Вы формат sscanf(" <указатель на входную строку для разбора>, <сторка/указатель на строку формата>", . . . "приемные" указатели . . . . ) - то что есть в документации на "базовый" С.  (ошипку исправил)

Quote

И после этого применяю sscanf или sprintf

совсем "одно и тоже". Это касаемо Вашего "или".

Хотя-бы приведите строку формата, которую Вы используете в sscanf. Лучше полный код.

Кроме того, в "недокомипляторах" может быть (сильно)урезанная версия работы с форматами в (s)printf, и уж тем более - в (s)scanf.

Если есть возможность - отработайте Ваш код на нормальной платформе (Visual C любой самой древнй версии, Console32), добейтесь правильной работы, затем переносите на Ваш компилятор.

ps чтобы sscanf правильно распарсил входную строку, в строке формата должен быть правильно закодирован терминирующий символ (\r)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 часа назад, addi II сказал:

У меня есть следующая строка принимаемая по юарту "#ААВСС/r"

Где АА, хекс значение от 0 до FF

B, хекс значение от 0 до F

CC, хекс значение от 0 до FF

Мне нужно эти три значения параметров позвать и положить в 3 переменные  unsigned char

И зачем тут вообще sscanf и sprintf? Бред какой-то.... :wacko2:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Строка: A5

Из первого символа 'A' вычитаем 0x30. Если результат от 0 до 9, то так и используем.

Если больше 9, то вычитаем 0x41. Если меньше 15, значит используем и в строке была большая буква А.

Если больше 15, то вычитаем 0x61. Если результат меньше 15, то используем как есть и в строке была маленькая буква 'a'.

Если больше 15, то введен неверный символ.

Результат - это четыре бита. Куда их разместить, уже зависит от обрабатываемого символа.

В нашем случае результат обработки символа "А" нужно сдвинуть на четыре бита влево, а результат обработки символа "5" сложить с предыдущим результатом посредством операции "ИЛИ".

И так со всеми символами.

 

Изменено пользователем DX168B

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 hours ago, x893 said:

Пишиите на английском. Переводчик на русский очень плохо работает.

прошу прощения писал с телефона, исправил

13 hours ago, k155la3 said:

Вместо 10-15 строк в эпистолярном жанре Вы могли бы привести 3-4 сторки кода (даже одну), который "не идет" или работает не так, как Вы ожидали.

В частности, соблюдаете ли Вы формат sscanf(" <указатель на входную строку для разбора>, <сторка/указатель на строку формата>", . . . "приемные" указатели . . . . ) - то что есть в документации на "базовый" С.  (ошипку исправил)

совсем "одно и тоже". Это касаемо Вашего "или".

Хотя-бы приведите строку формата, которую Вы используете в sscanf. Лучше полный код.

Кроме того, в "недокомипляторах" может быть (сильно)урезанная версия работы с форматами в (s)printf, и уж тем более - в (s)scanf.

Если есть возможность - отработайте Ваш код на нормальной платформе (Visual C любой самой древнй версии, Console32), добейтесь правильной работы, затем переносите на Ваш компилятор.

ps чтобы sscanf правильно распарсил входную строку, в строке формата должен быть правильно закодирован терминирующий символ (\r)

Спасибо большое, может быть в этом проблема, символ '\r' кодирую как 0x0D

10 hours ago, jcxz said:

И зачем тут вообще sscanf и sprintf? Бред какой-то.... :wacko2:

На мой взгляд не достаточно очевидно, как иначе, а с помощью sscanf/sprintf делать этого удобно

Строку я сохраняю в память по указателю типа char, как по вашему они будут располагаться и как потом склеивать байтное значение и разделять полубайтное?

8 hours ago, DX168B said:

Строка: A5

Из первого символа 'A' вычитаем 0x30. Если результат от 0 до 9, то так и используем.

Если больше 9, то вычитаем 0x41. Если меньше 15, значит используем и в строке была большая буква А.

Если больше 15, то вычитаем 0x61. Если результат меньше 15, то используем как есть и в строке была маленькая буква 'a'.

Если больше 15, то введен неверный символ.

Результат - это четыре бита. Куда их разместить, уже зависит от обрабатываемого символа.

В нашем случае результат обработки символа "А" нужно сдвинуть на четыре бита влево, а результат обработки символа "5" сложить с предыдущим результатом посредством операции "ИЛИ".

И так со всеми символами.

Спасибо, поробую!

 

 

Изменено пользователем addi II

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 hours ago, k155la3 said:

Вместо 10-15 строк в эпистолярном жанре Вы могли бы привести 3-4 сторки кода (даже одну), который "не идет" или работает не так, как Вы ожидали.

В частности, соблюдаете ли Вы формат sscanf(" <указатель на входную строку для разбора>, <сторка/указатель на строку формата>", . . . "приемные" указатели . . . . ) - то что есть в документации на "базовый" С.  (ошипку исправил)

совсем "одно и тоже". Это касаемо Вашего "или".

Хотя-бы приведите строку формата, которую Вы используете в sscanf. Лучше полный код.

Кроме того, в "недокомипляторах" может быть (сильно)урезанная версия работы с форматами в (s)printf, и уж тем более - в (s)scanf.

Если есть возможность - отработайте Ваш код на нормальной платформе (Visual C любой самой древнй версии, Console32), добейтесь правильной работы, затем переносите на Ваш компилятор.

ps чтобы sscanf правильно распарсил входную строку, в строке формата должен быть правильно закодирован терминирующий символ (\r)

Вот код:

#include "uart.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

volatile unsigned char temp=0;
extern unsigned char ByteReceived;
extern unsigned char status_uart ;
volatile unsigned char sts=0;
volatile unsigned char cntb=0;
volatile unsigned char cmd=0;
volatile unsigned char tr_s=0;
volatile unsigned char i=0;

volatile char* data1;
volatile char* data2;

volatile char cmd1[] = "!01-SPU-1000\r";
volatile char cmd2[] = "!02-SPU-1000\r";
volatile char reccmd1[] = "$01M\r";
volatile char error[] = "error\0";
volatile char reccmd2[] = "$02M\r";
volatile char toend[] = ">AA\r\0";
volatile unsigned char pref, aa,b,dd,n,d;
volatile unsigned char debug=0;
volatile unsigned char temp3;

void main()
{
	data1 = (char*)malloc(6 * sizeof(char));
	data2 = (char*)malloc(17 * sizeof(char));
	data3 = (char*)malloc(8 * sizeof(char));
	ini();
 
while(1)
{
 if(temp == 1) // when byte received
   {
// парсинг этой строки работает   
		if((ByteReceived == 0x24) && (sts ==0))
		{

                       // debug = 1;
                        sts = 1;
                        *(data1+ cntb) = ByteReceived;          
                        cntb++ ;                 
                        ByteReceived = 0x00;
                        temp = 0;

                }
                else
                {
                        if((sts==1) && (ByteReceived == 0x0D))
                        {
                                *(data1 + cntb) = ByteReceived;//'\r';
                                *(data1 + cntb + 1) = '\0';                                                           
                                ByteReceived = 0x00;
                                temp = 0;
                                if(strcmp((const char *)data1,(const char *) reccmd1) == 0 )
                                {
                                   

                                        adr = 0xC004;
                                        *(volatile short*)(adr) = 0xFF;
                                        IOPORT2 &= ~0x80;
                                        tr_s = sizeof(cmd1) - 1;
                                        i = 0;
                                        do
                                        {

                                                SBUF_TX0 = cmd1[i];
                                                do{status_uart = SP_STAT0;}
                                                while(!(status_uart & 0x08));
                                                tr_s --;
                                                i++;

                                        }
                                        while(tr_s);
                                        sts = 0;
                                        cntb = 0;
                                        IOPORT2 |= 0x80;

                                }
                                else
                                {
                                        if(strcmp((const char *)data1,(const char *) reccmd2) == 0 )
                                        {
											IOPORT2 &= ~0x80;
											 adr = 0xC004;
											*(volatile short*)(adr) = 0x55;
											 tr_s = sizeof(cmd2) - 1;
											i = 0;
											do
											{                                           
													SBUF_TX0 = cmd2[i];//ByteReceived;//0x01;
													do{status_uart = SP_STAT0;}
													while(!(status_uart & 0x08));
													tr_s --;
													i++;
											}
											while(tr_s);
											sts = 0;
											cntb = 0;                                      
                                        }
                                        else
                                        { 
											tr_s = sizeof(error) - 1;
											i = 0;
											do
											{
													SBUF_TX0 = error[i];
													do{status_uart = SP_STAT0;}
													while(!(status_uart & 0x08));
													tr_s --;
													i++;
											}
											while(tr_s);
											sts = 0;
											cntb =0;
											IOPORT2 |= 0x80;
                                        }
                                }

                        }
                        else
                        {
                              if((sts==1) && (ByteReceived != 0x0D))
                              {
                                *(data1+ cntb) = ByteReceived;
                                cntb++ ;
                                temp = 0;
                              }
                        }

                }
// прием строчки описанной в ветке, 0x230x300x310x310x310x320x0D
                if((ByteReceived == 0x23) && (sts == 0))               
                {
                       cntb = 0;
                       sts = 2;
                       *(data2+ cntb) = ByteReceived;
                       cntb++ ;
                       ByteReceived = 0x00;
                       temp = 0;
                }
                else
                {
                        if((sts==2) && (ByteReceived == 0x0D))
                        {
                               *(data2 + cntb) =  ByteReceived ;
                               *(data2 + cntb+1) = '\0';

                                 ByteReceived = 0x00;
                                 temp = 0;
                                 temp3 = 0;
								 // sscanf( (char*) data2, "%1u%2u%1u%2u",&pref, &aa, &b, &dd );
                                 //temp3 = sscanf( (const char*) data2, "%1x%2x%1x%2x",&pref, &aa, &b, &dd );
                                 temp3 = sprintf ( (char*) data2, "%1x%2x%1x%2x",(unsigned char)&pref, (unsigned char)&aa, (unsigned char)&b, (unsigned char)&dd );
                                //sscanf( (char*)  data2, "#%2X%1X%2X", &aa, &b, &dd );

                                // sprintf (data2, "#%2X%1X%2X",&pref, &aa, &b, &dd );
                                ///sprintf (data2, "#%2X%1X%2X", &aa, &b, &dd );
                                //if(((data2[1]==0x30) && (data2[2]==0x31)) || ((data2[1]==0x30) && (data2[2]==0x32)))
                                //   if((aa== 0x00))// || (aa == 0x32))
                               //if((pref == 0x00) && (data2[0]==0x23) && (temp3 != 0x00))
                                //if((pref == 0x23) && (data2[0]==0x23)) //&& (temp3 != 0x00))
                               // if((aa== 0x31) || (aa == 0x32))
                               if((temp3 != 0x00) && (pref == 0x00))
                                {

                                   debug = 1;


                                }
                                 cntb = 0;
                                 temp = 0;
                                 sts = 0;

                        }

                        else
                        {
                               if((sts==2) && (ByteReceived != 0x0D))
                               {
                                *(data2+ cntb) = ByteReceived;
                                cntb++ ;
                                temp = 0;
                               }
                        }


                }

   }
	else
	{
		
		  IOPORT2 |= 0x80;
	}
	
	
	 if( ((debug==1) && (sts == 0)) )//|| ((debug==1) && (sts == 2)) )
     {
            debug = 0;
            if(sts)
            sts =0;
			IOPORT2 &= ~0x80;
			SBUF_TX0 = pref+0x30;//ByteReceived;//0x01;
			do{status_uart = SP_STAT0;}
			while(!(status_uart & 0x08));
			SBUF_TX0 = aa+0x30;//ByteReceived;//0x01;
			do{status_uart = SP_STAT0;}
			while(!(status_uart & 0x08));
			SBUF_TX0 = b+0x30;//ByteReceived;//0x01;
			do{status_uart = SP_STAT0;}
			while(!(status_uart & 0x08));
			SBUF_TX0 = dd+0x30;//ByteReceived;//0x01;
			do{status_uart = SP_STAT0;}
			while(!(status_uart & 0x08));
			SBUF_TX0 = temp3 + 0x30;//ByteReceived;//0x01;
			do{status_uart = SP_STAT0;}
			while(!(status_uart & 0x08));
			SBUF_TX0 = 0x24;//ByteReceived;//0x01;
			do{status_uart = SP_STAT0;}
			while(!(status_uart & 0x08));
			SBUF_TX0 = 0x23;//ByteReceived;//0x01;
			do{status_uart = SP_STAT0;}
			while(!(status_uart & 0x08));
			if(temp3 < 20)
			{
				SBUF_TX0 = 0x23;//ByteReceived;//0x01;
				do{status_uart = SP_STAT0;}
				while(!(status_uart & 0x08));

			}
			
      }

	
	
}

}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может поможет: [url=https://github.com/eddyem/stm32samples/blob/master/F1:F103/MLX90640/strfunct.c#L187]ввод числа[/url].

Какой-то глюк с формой ответа: не могу url вставить нормально…

В приведенном коде анализируется строка и преобразуется из десятичной, восьмеричной, двоичной или шестнадцатеричной записи.

Изменено пользователем Eddy_Em

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 hours ago, addi II said:

Вот код: . . . 

Да, с типом char в sscanf() есть некоторая неясность. А именно при "разборе" по формату "X"/HEX переменные (адреса) с типом 
(unsigned char) не воспринимаются корректно. Хотя n = sscanf() дает правильное кол-во принятых значений. И по указанным адресам что-то пишется. 
---
Меняем для sscanf/HEX рабочий тип переменных на unsigned (short) int. Если надо char переприсваиваем.

// Win MS VStudio Console32
	static unsigned int vcA, vcB, vcC, vcD;
    vcA = 0x11, vcB = 0x22, vcC = 0x33, vcD = 0x44;
    n = sscanf( ":AABCC-", ":%2x%1x%2x-",  &vcA, &vcB, &vcC );
    printf("\nn=%.2d", n);
    printf("\nA=%.02X", (unsigned int) vcA);
    printf("\nB=%.02X", (unsigned int) vcB);
    printf("\nC=%.02X", (unsigned int) vcC);
    printf("\n");

Очевидно, в sscanf() для "разбора" X/HEX формата есть ограничения (реализована только разрядность int и выше).
Можно проверить, покурив документацию, а лучще - почитав исходник для sscanf().

ps
Использовать sscanf() удобно там, где надо "разбирать" различную инф с различными форматами (возможно задаваемыми)
динамически или через ini файл-данные.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, k155la3 сказал:

Да, с типом char в sscanf() есть некоторая неясность.

Во-первых, никакой неясности нет. char предназначен для хранения символов. Для чисел предназанчены (un)signed char

Во-вторых, вы форматной строкой просите заносить результат в переменную типа unsigned int. Почему же вас удивляет, что компилятор делает именно то, что вы попросили? Для размещения в переменные другой размерности в форматной строке предусмотрены модификаторы l, h и ll, hh (начиная с C99).

И напоследок: зачем вы в printf() делаете явное приведение к unsigned int переменной, которая и так имеет тип unsigned int? К тому же, при вызове функций с переменным числом аргументов используются integer promotion rules и все переменные, меньшие int, неявно приводятся к (un)signed int.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Сергей Борщ said:

Во-первых, никакой неясности нет.

Это само-собой. "Неясность" есть у меня. Но смысла разбираться мне с этим (модификаторами) сейчас нет. Это если у ТС будет непреодолимое желание "покурить взатяг".

Попробовал модификатор hhx - не помогло. Смысла это вылавливать на компиляторе MSVS2008 нет, у ТС явно другое.

Явное приведение для int в printf лишнее, согласен. Было явное приведение для char, не стал убирать, просто переправил для int. Явное для char нужно чтобы в printf не заморачиваться с модификаторами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 5/26/2022 at 2:51 PM, addi II said:

Спасибо за поддержку!

У меня есть следующая строка принимаемая по юарту "#ААВСС\r"

Где АА, хекс значение от 0 до FF

B, хекс значение от 0 до F

CC, хекс значение от 0 до FF

Мне нужно эти три значения параметров парсировать и положить в 3 переменные типа  unsigned char

 

я бы сделал так

uint32_t HexStrToInt(char *hex)
{
    uint32_t val = 0;
    while (*hex)
    {
        // get current character then increment
        uint8_t l_byte = *hex++;
        // transform hex character to the 4bit equivalent number, using the ascii table indexes
        if (l_byte >= '0' && l_byte <= '9') l_byte = l_byte - '0';
        else if (l_byte >= 'a' && l_byte <='f') l_byte = l_byte - 'a' + 10;
        else if (l_byte >= 'A' && l_byte <='F') l_byte = l_byte - 'A' + 10;
        // shift 4 to make space for new digit, and add the 4 bits of the new digit
        val = (val << 4) | (l_byte & 0xF);
    }
    return val;
}

void Convert(char * str)
{
  char tmp[3] = {0};
  
  strncpy(tmp, &str[1], 2);
  unsigned char aa = HexStrToInt(tmp);
  
  strncpy(tmp, &str[3], 1);
  unsigned char bb = HexStrToInt(tmp);
  
  strncpy(tmp, &str[4], 2);
  unsigned char cc = HexStrToInt(tmp); 
  
}

 

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...