2017-07-30 4 views
-3

J'essaie de convertir les valeurs hexadécimales en une seule chaîne et je l'ai déjà lu question mais je ne sais pas comment le convertir de manière dynamique, comme si ma fonction obtenait une série hexadécimale de 8 ou 9 ou plus. Comment puis-je optimiser cet extrait avec une boucle qui itère sur les valeurs hexadécimales données et convertit chaque valeur hexadécimale (sauf la première) suivie d'un .?Convertir un hexagone en une corde dans une boucle

/* 
Input: char[] ="2b06010201010300" 
Output: char[]="1.3.6.1.2.1.1.3.0" 
*/ 
void test(char * hex_arr) 
{ 
    char string[sizeof(hex_arr)*2+1]; 
    string[0] = '1'; 
    string[1] = '.'; 
    string[2] = '3'; 
    string[3] = '.'; 
    sprintf(&string[4], "%x", hex_arr[1]); 
    string[5] = '.'; 
    sprintf(&string[6], "%x", hex_arr[2]); 
    // ... 
    printf("Output: %s\n", string); 
} 

L'entrée char[] représentent un SNMP OBJECT IDENTIFIER.

+3

est l'entrée d'une chaîne, comme 'entrée char [] = "2b 06 01 02 01 01 03 00"'? La sortie est-elle une chaîne? Et, comment est-ce que '1.3' vient de' 2b'? –

+0

@DavidBowling La chaîne d'entrée est comme 'unsigned char [] =" 2b06010201010300 "', la sortie est une chaîne. '2b' est spécifié comme' 1.3'. – Sam

+1

Pouvez-vous donner plus d'exemples d'entrée et de sortie? Et décrivez votre conversion plus en détail! Btw, 2b = 43, donc je ne pense pas que quiconque ici comprenne comment vous arrivez à 1.3 ... –

Répondre

1

Notez que dans le code affiché dans la question, string[] est déclaré dans la fonction test() en utilisant sizeof(hex_arr). Mais hex_arr est un pointeur vers char, pas un tableau, donc cela ne donnera pas la bonne taille pour string[]. Aussi, ici string est une variable automatique dont la durée de vie est limitée à la fonction test(); C'est bien si le seul but est d'imprimer les résultats, mais une autre solution doit être trouvée si les résultats doivent être utilisés ailleurs dans le code. Une manière d'approcher ceci est de faire passer une matrice de sortie avec un tableau d'entrée dans une fonction de conversion. La fonction peut retourner -1 si le format d'entrée n'est pas acceptable, sinon retourner 0, et le tableau de sortie peut contenir la chaîne d'identification résultant de la chaîne d'entrée du nombre hexadécimal. Chaque paire de chiffres dans l'entrée représente un nombre en hexadécimal, qui peut être un nombre décimal à trois chiffres, et chaque nombre décimal à trois chiffres (sauf le dernier, qui est suivi d'un terminateur nul) a un délimiteur ajouté ajouté après lui; Chaque paire de chiffres d'entrée est donc convertie en quatre caractères maximum. Cela signifie que l'allocation de output[] à deux fois la taille de input sera suffisante pour stocker tout résultat, y compris l'espace pour la terminaison nulle. Ceci fournit en fait un peu d'espace supplémentaire, qui sera nécessaire.

La méthode utilisée ici par la fonction id_from_hexstring() pour effectuer la conversion consiste à utiliser sscanf() dans une boucle pour lire une paire de caractères sous forme de chaîne à partir de l'entrée dans la mémoire tampon temporaire val_str[]. Le spécificateur de conversion %n est utilisé pour garder trace de l'emplacement atteint après chaque conversion réussie, en stockant le nombre de correspondances réussies en offset et en utilisant cette valeur pour incrémenter un pointeur dans input[] en préparation de la prochaine conversion.

La fonction strtoul() est utilisée pour convertir les chaînes hexadécimales à deux chiffres stockées en val_str[] en valeurs unsigned long. Lorsque la première paire de caractères dans input[] est convertie, si la valeur convertie ne correspond pas IN_PREFIX, la fonction renvoie avec un code d'erreur. Sinon, OUT_PREFIX est imprimé au début de output[] au lieu de la valeur convertie. Après cette première paire, les valeurs de conversion restantes sont imprimées à la fin de la chaîne output[].

Après la boucle se termine de conversion, un séparateur . arrière est laissé à la fin de output[], et la dernière tâche est de supprimer ce avant de retourner 0 pour indiquer le succès. En doublant la taille (au lieu de la longueur de la chaîne) du tableau input[] pour déterminer la taille du tableau output[], il est garanti que output[] peut contenir le délimiteur supplémentaire ..

Ce code pourrait faire plus pour valider l'entrée.Comme c'est le cas maintenant, la fonction id_from_hexstring() s'attend à ce que l'entrée soit composée de caractères hexadécimaux valides. Voici le programme complet et sa sortie:

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

#define IN_PREFIX  0x2b 
#define OUT_PREFIX  "1.3." 
#define ID_PREFIX_ERR -1 
#define ID_PREFIX_OK 0 

int id_from_hexstring(char *out, char *in); 

int main(void) 
{ 
    char input[] = "2b06010201010300"; 
    char output[sizeof input * 2] = ""; 

    if (id_from_hexstring(output, input) == -1) { 
     fprintf(stderr, "Error in input format\n"); 
    } else { 
     printf("Input: %s\n", input); 
     printf("Output: %s\n", output); 
    } 

    return 0; 
} 

/* Expects that out points to a suitably sized array containing an empty 
* string, and in points to a string containing only unsigned hex digits */ 
int id_from_hexstring(char *out, char *in) 
{ 
    int ret_val = ID_PREFIX_OK; 
    int offset; 
    char *ptr = in; 
    char val_str[3]; 

    while (sscanf(ptr, "%2s%n", val_str, &offset) == 1) { 

     unsigned long dec_val = strtoul(val_str, NULL, 16); 

     /* Handle prefix; return error code if invalid */ 
     if (ptr == in) { 
      if (dec_val != IN_PREFIX) { 
      ret_val = ID_PREFIX_ERR; 
      break; 
      } else { 
       sprintf(out, OUT_PREFIX); 
       ptr += offset; 
       continue; 
      } 
     } 

     /* Print next value to identifier string */ 
     size_t end = strlen(out); 
     sprintf(out + end, "%lu.", dec_val); 
     ptr += offset; 
    } 

    /* Replace trailing point */ 
    size_t out_len = strlen(out); 
    if (out_len > 0) { 
     out[out_len - 1] = '\0'; 
    } 

    return ret_val; 
} 
Input: 2b06010201010300 
Output: 1.3.6.1.2.1.1.3.0 
+0

Merci pour votre réponse. Si l'entrée est un pointeur sur un tableau, cela ne fonctionne pas. 'printf ("% 02x \ n ", ptr [0]);' fonctionne pour le pointeur mais je ne peux pas convertir le pointeur avec 'id_from_hexstring' – Sam

+0

@ Sam-- La réponse a été écrite à la spécification fournie dans la question, où l'entrée est un tableau. Si par "pointeur vers un tableau" vous voulez dire quelque chose comme "char * input =" 2b06010201010300 ";', vous pouvez utiliser 'strlen()' au lieu de l'opérateur 'sizeof', quelque chose comme:' char output [(strlen (input) + 1) * 2]; Cela nécessite que votre compilateur supporte les VLA (requis en C99, mais facultatif en C11). Le code original de la réponse n'utilisait pas de VLA, et compilait même sous C89 si quelques déclarations étaient déplacées. –

+0

@ David-- Merci, j'ai utilisé 'char input [ * 2]; sprintf (& input [i * 2], "% 02x", ptr [i]); 'pour représenter hex décimal comme une chaîne. – Sam