Newsgroup: it.comp.lang.c
Titolo: Stringa to "hex"

Ciao,
    ho un dubbio.
Esiste in C una funzione standard per convertire una stringa in un altra
stringa che ne rappresenti il valore esadecimale. Ad esempio:
char str[] = "ciao";
char strHex[8] = {0};
strHex = func(str);  /* ?? */
dove la variabile strHex sarà :  "6369616F"
Grazie, ciao!

 dove la variabile strHex sar? :  "6369616F"
Non e` difficile: str[x] e` un char, il cui valore (interpretato come
intero) e` la sua codifica nel charset in uso (di solito ASCII). Puoi
quindi usare sprintf per scrivere la stringa hex corrispondente a questo
intero. Lo specificatore di conversione e` %x (o %X, in base ai gusti).
Luca
-- 
Home: 
http://kronoz.cjb.net
Windows NT crashed.
I'm the Blue Screen of Death.
No one hears your screams.

 intero. Lo specificatore di conversione e` %x (o %X, in base ai gusti).
Ho provato ma.....
<CODE>
int main() {
  char str[] = "ciao";
  char strHex[9] = {0};
  int *pi;
  pi = (int *)str;
  sprintf(strHex, "%x", *pi);
  printf("Valore di strHex: %s \n", strHex);
  return 0;
}
<CODE>
...il valore della variabile strHex e' l'inverso di quello che voglio
ottenere e contiene lettere minuscole. Cioe':  "6f616963" (al posto di
"6369616F").
Suggerimenti?
Ciao! (e grazie!)

 ha scritto:

Il risultato che ottieni e` casuale, e si basa sul fatto che sulla tua
piattaforma sizeof(int) == 4 (LE) e contemporaneamente la stringa e`
lunga 4 caratteri. La conversione devi farla carattere per carattere:
#include <stdio.h>
char *str2hex(char *dst, int size, char const *src) {
	int i;
	char *tmp = dst;
 
	if (!dst)
		return NULL;
	for (i = 0; *src && i + 2 <= size - 1; src++, tmp += 2, i += 2)
		sprintf(tmp, "%02X", *src);
	*tmp = '\0';
	return dst;
}
int main() {
	char str[] = "ciao";
	char strHex[9] = {0};
	printf("Valore di strHex: %s \n", str2hex(strHex, sizeof(strHex), str));
	return 0;
}
 
La questione maiuscolo/minuscolo dipende dallo specificatore di
conversione (%X oppure %x, rispettivamente) e avresti potuto scoprirlo
con un minimo di sforzo...
Luca
-- 
Home: 
http://kronoz.cjb.net
"In linea di principio sarei indifferente al natale, se solo il natale
 ricambiasse la cortesia e mi lasciasse in pace." -- Marco d'Itri

 con un minimo di sforzo...
Grazie.
E' vero avrei potuto sforzarmi di piu' ma tieni presente che le prove le ho
fatte alle 2 di mattina (che puoi vedere dal post)... quindi qualche rotella
era gia' in letargo ?!?! :-P
Grazie ancora, ciao!

 esadecimale.
Che _io_ sappia, le librerie standard non forniscono nulla di gia` fatto
per risolvere questo problema (ovviamente il  fatto che io non lo sappia
non implica necessariamente che allora non esista) :)
Ho  visto   che  ti  hanno   gia`  risposto;  la  soluzione   di  Kronos
_sicuramente_ funziona. Io te ne proporrei un'altra che ti svincolerebbe
dall'uso di  s[n]?print (e,  _personalmente_, lo  ritengo un  bene), poi
decidi tu cosa ti conviene utilizzare :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENC(x,y)  \
  ((x & 15) > 9 ? (x & 15) + (y ? 'A' : 'a') - 10 : (x & 15) + '0')
 
#define DEC(x)    \
  ((x >= 'a') ? x - 'a' + 10 : ((x >= 'A') ? x - 'A' + 10 : x - '0'))
#ifndef NITEMS
# define NITEMS 4
#endif
enum enc_case
{
  USE_LOWERCASE,
  USE_UPPERCASE
};
typedef enum enc_case case_t;
static __inline__ char *__my_encode(char *str, case_t c)
{
  char *scan = NULL, *encoded = NULL;
 
  if (!str || !(encoded = malloc((strlen(str) << 1) + 1)))
    return NULL;
  for (scan = encoded; *str != '\0'; str++, scan += 2)
  {
    *scan = ENC((unsigned int)*str >> 4, c);
    *(scan + 1) = ENC((unsigned int)*str, c);
  }
 
  *scan = '\0';
  return(encoded);
}
static __inline__ char *__my_decode(char *str)
{
  char *scan = NULL, *decoded = NULL;
  size_t size;
 
  if (!str)
    return NULL;
 
  if ((size = strlen(str)) & 1 || !(decoded = malloc((size >> 1) + 1)))
    return NULL;
 
  for(scan = decoded; *str != '\0'; str += 2, scan++)
  {
    *scan = DEC((unsigned int)*str) << 4;
    *scan += DEC((unsigned int)*(str + 1));
  }
 
  *scan = '\0';
  return(decoded);
}
int main(int x, char *y[])
{
  char *z[NITEMS] = {NULL, NULL, NULL, NULL};
  int i;
 
  /* encoda/decoda stringa */
  for (i = 0; i < NITEMS; i += 2)
  {
        z[i] = __my_encode((x < 2 ? NULL : y[1]), i);
    z[i + 1] = __my_decode(z[i]);
  }
 
  /* stampa gli elementi */
  (void)fprintf(stdout, "From `%s':\n", x > 1 ? y[1] : "NULL");
 
  for (i = 0; i < NITEMS; i++)
    (void)fprintf(stdout, "\t`%s'\n", z[i] ? z[i] : "NULL");
 
  /* libera memoria */
  for (i = 0; i < NITEMS; i++)
    free(z[i]);
 
  return 0;
}
La funzione __my_encode  puo` "encodare" in lower|upper  case, a seconda
della flag specificata durante il passaggio dei parametri; se prevedessi
di encodare  sempre, ad  esempio, in  upper case,  puoi o  modificare il
codice o scriverti una macro  che ti eviterebbe "l'onere" di specificare
sempre tale flag; ad esempio:
#define _my_encode(x) __my_encode(x, USE_UPPERCASE)
__my_decode, invece,  non ha bisogno di  alcuna specificazione; "decoda"
quello che  gli dai  in pasto  (a patto che  la lunghezza  della stringa
passata sia un numero pari).
Ciao.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 static __inline__ char *__my_encode(char *str, case_t c)
Il C99 prevede inline (non __inline__), inoltre gli identificativi che
iniziano per underscore o che contengono il doppio underscore sono
riservati per uso interno della libreria C.
Sarebbe meglio questo prototipo:
static inline char *my_encode_(char *str, case_t c)
#define my_encode_upper(x) my_encode_(x, USE_UPPERCASE)
Luca
-- 
Home: 
http://kronoz.cjb.net
"It is more complicated than you think"
                -- The Eighth Networking Truth from RFC 1925

 [snip]
Piu` in  generale funzioni  che rispettano quel  template nel  nome sono
simboli  non esportati  (kernel|user space). Trattandosi  di convenzioni
non mi pare il caso di discutere.


        __inline__ and __typeof__ instead. `-ansi' implies `-fno-asm'.
ANSI != C99. Nel C99 inline e` una keyword riservata e non puo` essere
riciclata come identificatore (asm e typeof sono estensioni del gcc,
invece). Tra l'altro la tua documentazione e` vecchia:
    In C99 mode (`-std=c99' or `-std=gnu99'), this switch only affects
    the `asm' and `typeof' keywords, since `inline' is a standard
    keyword in ISO C99.
(gcc-3.3)
Luca
-- 
Home: 
http://kronoz.cjb.net
"Ci sono le balle, le megaballe e le statistiche".
 Mark Twain

 Tra l'altro la tua documentazione e` vecchia:
La documentazione che  ho postato *non* e` vecchia;  e` semplicemente il
manuale  di  riferimento  del  gcc  2.95.3; le  differenze  tra  il  tuo
compilatore ed  il mio,  come ben  saprai, non si  riducono certo  ad un
fattore di anzianita`.
