LusoRobótica - Robótica em Português

Software => C/C++ => Tópico iniciado por: Addax em 16 de Junho de 2015, 15:45

Título: Duvida Strings
Enviado por: Addax em 16 de Junho de 2015, 15:45
Boa tarde,
Estou com um problema ao fazer um printf de um valor hexadecimal.
A minha duvida é a seguinte: se eu declarar uma variável, inicializa-la e fizer o printf funciona na perfeição. Abaixo está o código que estou a falar.
Código: [Seleccione]
int main()
{
char ch[33]={0x1D,0x56,0x01};
while(1)
{
printf("%s",ch);
}
}
Depois algures no código eu recebo por rs232 a seguinte string: "0x80,0x25,0x35", ou seja,
ch[0]=0
ch[1]=x
ch[2]=8
ch[3]=0
.....

Agora a minha duvida é a seguinte, como posso separar os diferentes hexadecimais de forma a ficar igual ao apresentado no printf acima?

(Não sei se estou a conseguir transmitir a minha duvida)

obrigado desde já
Cumprimentos
Título: Re: Duvida Strings
Enviado por: senso em 16 de Junho de 2015, 15:55
Falta um \0 para terminar a string.
Porque é que não usas '0', 'a' para escrever um caracter em vez de andar com numeros, nem toda a gente decora a tabela ASCII.
Porque é que usas um array com 33 posições para usar 3?

Se queres imprimir um numero em formato hex usas %x
Título: Re: Duvida Strings
Enviado por: Addax em 16 de Junho de 2015, 16:10
Eu depois de receber aquela string por rs232 volto a enviar para outro rs232.
No primeiro exemplo quem recebe a string interpreta e reage.
No segundo mesmo com o '\0' não reage. já tentei de várias formas e só no primeiro caso é que funciona

O 33 em vez do 3 foi um erro mas como isto é só um exemplo não faz diferença.
Título: Re: Duvida Strings
Enviado por: KammutierSpule em 16 de Junho de 2015, 16:11
Desculpa nao entendi as duvidas (tambem so li uma vez) mas reparo que ha uma mistura de problemas ai, vou tentar fazer um pequeno sumario talvez possa ajudar.

Código: [Seleccione]
printf("%s", "imprime uma string de caracteres que termina com o caracter zero" ); // Nota: "" termina automaticamente a string com um \0. Este zero final nao é impresso (mas ocupa memoria), apenas significa que deve terminar o envio da string.
printf("%c", 0x20); // Imprime o caracter com o valor hexadecimal 0x20 , que corresponde na tabela ascii ao caracter espaço.
printf("%c", '!'); // Mesma coisa mas imprime o caracter ! que corresponde ao valor hexadecimal 0x21
printf("%d", '!'); // Imprime o valor do caracter !, que é 33, ou seja, os caracteres 3 duas vezes "33"
printf("%X, '!'); // Imprime o valor hexadecimal do caracter !, ou seja, 21, imprime o caracter '2' e o caracter '1' == "21"
printf("%X, 0x21); // Mesma coisa, imprime "21"
printf("%c", 0x21); // Imprime o caracter com o valor hexadecimal 0x21 que corresponde ao ! na tabel ascii.

Edit: mais exemplos:
Código: [Seleccione]
char c_array[4] = { 0x30, 0x31, 0x32, 0x33 };

printf("%s",  c_array); // Crash! Isto nao é correcto, nao existe uma terminacao no array conhecida com zero, logo nao sabe quando vai parar de escrever caracteres.

for( int i=0; i<4; i++) printf("%c", c_array[i] ); // Imprime "0123"
for( int i=0; i<4; i++) printf("%x", c_array[i] ); // Imprime "30313233"
for( int i=0; i<4; i++) printf("%d", c_array[i] ); // Imprime "48495051"
Título: Re: Duvida Strings
Enviado por: Addax em 17 de Junho de 2015, 12:58
Obrigado KammutierSpule e senso pela ajuda.
Problema e duvida resolvidos.

Isto é um exemplo.
Recebo por rs232 a seguinte string: "0x80,0x25,0x35", nas diferentes posições do vetor ch[]
ch[0]=0
ch[1]=x
ch[2]=8
ch[3]=0
ch[4]=,
ch[5]=0
.....

O que resolvi fazer foi:
Código: [Seleccione]
char recebe[100]=0;
char recebe_mod[100]=0;
char envia[3]=0;
int dec=0;
int k=0,j=0,q=0;

for(k=0;k<=strlen(recebe);k++)
{
   if(recebe[k]==0x30 && recebe[k+1]==0x78)
   {
     recebe_mod[q]=recebe[k+2];
     recebe_mod[q+1]=recebe[k+3];
     q=q+2;
   }
}

for(k=0;k<=strlen(recebe_mod);k++)
{
  switch(recebe_mod[k])
  {
    case '0':
      envia[j]=0;
      j++;
      break;
    case '1':
      envia[j]=1;
      j++;
      break;
    case '2':
      envia[j]=2;
      j++;
      break;
    ...
    default:
      j=0;
  }
  if(j==2)
  {
    dec=(int)envia[0]*16+(int)envia[1];
    printf("%c",(char)dec);
    j=0;
  }
}

Partilho aqui o que fiz porque pode dar jeito a alguém
Título: Re: Duvida Strings
Enviado por: Njay em 17 de Junho de 2015, 13:19
Ahh, tu queres é parsar uma string que tem números num formato hexadecimal.
É melhor escrever assim, é mais correcto porque o 0 não fica ambiguo:

ch[0]='0'
ch[1]='x'
ch[2]='8'
ch[3]='0'
ch[4]=','
ch[5]='0'

Eu em 1º lugar tentaria mudar o formato de envio para eliminar o "0x", que só dificulta, passando a receber "80,25,35".

Depois tens 2 funções que te ajudam nesse parsing: strtok (http://linux.die.net/man/3/strtok) (parte uma string por um separador) e strtol (http://linux.die.net/man/3/strtol) (converte uma string num número, no último argumento indicas a base numérica, que no teu caso seria 16 (hexadecimal)). Dá uma olhada nestas funções porque mesmo que não precises delas agora, quem sabe no futuro (e é um bom exercício re-escreveres o código usando-as).
Título: Re: Duvida Strings
Enviado por: Addax em 17 de Junho de 2015, 14:33
Njay, obrigado pela dica.
Eu só não optei por alterar a mensagem recebida porque isto é para integrar num projeto e assim não tenho que estar a alterar o que já está feito.
quanto às duas funções de parsing, vou ver e se não forem utilizadas agora, fico com o conhecimento para uma próxima
Título: Re: Duvida Strings
Enviado por: StarRider em 17 de Junho de 2015, 15:11
Boas,

Grande complicação para algo tão simples:

Código: [Seleccione]
char recebe[100] = "0x80,0x25,0x35";
uchar envia[3];
char *token;
int idx=0;

token = strtok(recebe, ",");
while (token != NULL)   {
    envia[idx++]=strtol(token, NULL, 16);
    token = strtok (NULL, ",");
}


PS: não te esqueças dos includes:
#include <string.h>
#include <stdlib.h>

Abraços,
PA
Título: Re: Duvida Strings
Enviado por: Njay em 17 de Junho de 2015, 15:26
Olha, boa, não tinha reparado que o strtol também aceitava hexs começados com o 0x :D

Então já agora e só para tornar isso mais à prova de crashes misteriosos:

const int cMaxEnvia = 3;
char recebe[100] = "0x80,0x25,0x35";
uchar envia[cMaxEnvia];
char *token;
int idx=0;

token = strtok(recebe, ",");
while ( (idx < cMaxEnvia) && (token != NULL) )   {
    envia[idx++]=strtol(token, NULL, 16);
    token = strtok (NULL, ",");
}

Título: Re: Duvida Strings
Enviado por: StarRider em 17 de Junho de 2015, 15:42
Olha, boa, não tinha reparado que o strtol também aceitava hexs começados com o 0x :D

Então já agora e só para tornar isso mais à prova de crashes misteriosos:

const int cMaxEnvia = 3;
char recebe[100] = "0x80,0x25,0x35";
uchar envia[cMaxEnvia];
char *token;
int idx=0;

token = strtok(recebe, ",");
while ( (idx < cMaxEnvia) && (token != NULL) )   {
    envia[idx++]=strtol(token, NULL, 16);
    token = strtok (NULL, ",");
}


Yap, mas a prova do "crash" era para ser ele a descobrir ;)

Abraços,
PA
Título: Re: Duvida Strings
Enviado por: Addax em 17 de Junho de 2015, 16:46
Obrigado StarRider e Njay.
O código que apresentaste é muito mais simples.
o único problema para este caso especifico é que no recebe pode estar algures 0x00. ao fazer o printf do envia ele faz como se fosse '\0', ou seja, é como se fosse o fim da string
Título: Re: Duvida Strings
Enviado por: Njay em 17 de Junho de 2015, 17:03
Qual é o problema? Agora já sabes quantos bytes são (idx), portanto...

Código: [Seleccione]
for (int i = 0; i < idx; i++)
{
    printf("%c", envia[i]);
}
Título: Re: Duvida Strings
Enviado por: Addax em 17 de Junho de 2015, 17:40
tens toda a razão. pensei mal
problema resolvido. com um código bem mais simples e reduzido que inicialmente o meu

obrigado a todos que participaram no tópico
Título: Re: Duvida Strings
Enviado por: StarRider em 17 de Junho de 2015, 18:01
Qual é o problema? Agora já sabes quantos bytes são (idx), portanto...

Código: [Seleccione]
for (int i = 0; i < idx; i++)
{
    printf("%c", envia[i]);
}

Ou ainda mais "compacto"  ;)

Código: [Seleccione]
while(idx--)
    printf("%c", envia[idx]);

Abraços,
PA
Título: Re: Duvida Strings
Enviado por: Njay em 17 de Junho de 2015, 18:02
É mais compacto mas o resultado não é o mesmo, ficas com os bytes impressos pela ordem inversa ;)
Título: Re: Duvida Strings
Enviado por: StarRider em 17 de Junho de 2015, 18:08
É mais compacto mas o resultado não é o mesmo, ficas com os bytes impressos pela ordem inversa ;)

touché ... estava a contar que a impressão fosse somente para fins de verificação.

Abraços,
PA
Título: Re: Duvida Strings
Enviado por: Njay em 17 de Junho de 2015, 19:55
Para fins de verificação podemos fazer

Código: [Seleccione]
for (int i = 0; i < idx; i++)
{
    printf("%s0x%02X", (i? "," : ""), envia[i]);
}
Título: Re: Duvida Strings
Enviado por: Addax em 17 de Junho de 2015, 23:40
obrigado a todos
problema resolvido e aprendi duas novas funções que não conhecia