Jump to content
    

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

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

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

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

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

Спасибо !

 

 

 

 

 

 

 

Share this post


Link to post
Share on other sites

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

Вам что, нужна функция перевода 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;
}

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

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

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

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

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

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

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

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

Edited by addi II

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

Quote

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

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

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

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

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

Share this post


Link to post
Share on other sites

Строка: A5

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

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

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

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

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

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

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

 

Edited by DX168B

Share this post


Link to post
Share on other sites

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" сложить с предыдущим результатом посредством операции "ИЛИ".

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

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

 

 

Edited by addi II

Share this post


Link to post
Share on other sites

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));

			}
			
      }

	
	
}

}

 

Share this post


Link to post
Share on other sites

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

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

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

Edited by Eddy_Em

Share this post


Link to post
Share on other sites

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 файл-данные.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

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

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

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

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

Share this post


Link to post
Share on other sites

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); 
  
}

 

Edited by jenya7

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...