2010-11-09 11 views
6

Ho provatocome convertire la stringa esadecimale in unsigned a 64 bit (uint64_t) intero in modo rapido e sicuro?

sscanf(str, "%016llX", &int64); 

ma non sembra al sicuro. C'è un modo veloce e sicuro per eseguire il casting di tipo?

Grazie ~

+0

Cosa intendi con "non sicuro"? –

+1

Non lo so. Ho provato ad usarlo per eseguire il cast tra un gran numero di stringhe esadecimali e a volte segnalerei un errore di segmento –

+0

Potresti mostrare la dichiarazione e l'inizializzazione di 'str'? – Flinsch

risposta

7

Non preoccupatevi delle funzioni della famiglia scanf. Sono quasi impossibili da usare in modo robusto. Ecco un uso sicuro generale strtoull:

char *str, *end; 
unsigned long long result; 
errno = 0; 
result = strtoull(str, &end, 16); 
if (result == 0 && end == str) { 
    /* str was not a number */ 
} else if (result == ULLONG_MAX && errno) { 
    /* the value of str does not fit in unsigned long long */ 
} else if (*end) { 
    /* str began with a number but has junk left over at the end */ 
} 

noti che strtoull accetta un 0x prefisso opzionale sulla corda, così come opzionale spazio bianco iniziale e un carattere di segno (+ o -). Se si desidera rifiutare questi, è necessario eseguire un test prima di chiamare strtoull, per esempio:

if (!isxdigit(str[0]) || (str[1] && !isxdigit(str[1]))) 

Se anche voi volete disabilitare eccessivamente lunghe rappresentazioni di numeri (zeri), si potrebbe verificare la seguente condizione prima di chiamare strtoull:

if (str[0]=='0' && str[1]) 

una cosa da tenere a mente è che "i numeri negativi" non sono considerati al di fuori della gamma di conversione; invece, un prefisso di - viene trattato come l'operatore di negazione unario in C applicato a un valore senza segno, quindi ad esempio strtoull("-2", 0, 16) restituirà ULLONG_MAX-1 (senza impostare errno).

+0

In generale sono d'accordo con i tuoi sentimenti riguardo alla famiglia 'scanf()'. Essi * hanno senso in ambienti controllati, ad es. leggendo nei file che la tua applicazione ha scritto da sola – DevSolar

+0

@DevSolar: In effetti, il mio commento era inteso come una risposta alla domanda dell'OP sull'uso sicuro, non su un consiglio generale. La famiglia 'scanf' funziona bene per la lettura dei file di Linux'/proc', per esempio. –

+0

Non '' strtoull() 'restituisce un tipo 'unsigned long long', che non è necessariamente un tipo 'uint64_t'? – GreySage

2

Il titolo (attualmente) contraddice il codice che hai fornito. Se vuoi fare quello che era originariamente il tuo titolo (converti una stringa in un intero), allora puoi usare questa risposta.


È possibile utilizzare la funzione di strtoull, che a differenza sscanf è una funzione specificamente orientata verso la lettura di rappresentazioni testuali di numeri.

const char *test = "123456789abcdef0"; 

errno = 0; 
unsigned long long result = strtoull(test, NULL, 16); 

if (errno == EINVAL) 
{ 
    // not a valid number 
} 
else if (errno == ERANGE) 
{ 
    // does not fit in an unsigned long long 
} 
+1

A mio parere, vuole convertire da intero a stringa, non viceversa. ;) – Flinsch

+1

@Flinsch, il titolo è cambiato, ma il suo codice originale suggerisce di voler convertire da stringa a intero. Non sono sicuro che tu possa vedere la cronologia delle modifiche della domanda, ma in origine il titolo indicava che voleva convertire una stringa in un numero intero. – dreamlax

+0

In realtà, 'scanf()' et al. sono * definiti * in termini di 'strtol()'. Per l'input decente a metà, sono funzionalmente identici per quanto riguarda i numeri di analisi. Ammetto che 'strtol()' gestisce il fallimento in modo più garbato. – DevSolar

0

Al momento ho scritto questa risposta, il titolo ha suggerito che ci si vuole scrivere un int64_t in una stringa, mentre il codice ha fatto il contrario (la lettura di una stringa esadecimale in un int64_t). Ho risposto "entrambi i modi":

L'intestazione <inttypes.h> ha macro di conversione per gestire le ..._t tipi in modo sicuro:

#include <stdio.h> 
#include <inttypes.h> 

sprintf(str, "%016" PRIX64, int64); 

Oppure (se questo è davvero quello che stai cercando di fare), il contrario :

#include <stdio.h> 
#include <inttypes.h> 

sscanf(str, "%" SCNx64, &int64); 

Notare che non è possibile applicare le larghezze, ecc con la famiglia scanf() funzioni. Analizza ciò che ottiene, il che può produrre risultati indesiderati quando l'input non aderisce alla formattazione prevista. Oh, e la famiglia di funzioni scanf() conosce solo (in minuscolo) "x", non (maiuscolo) "X".

Problemi correlati