2012-05-31 13 views
11

Ho una stringa che ha ints e sto cercando di ottenere tutti gli ints in un altro array. Quando sscanf non riesce a trovare un int, voglio che il ciclo si fermi. Così, ho fatto quanto segue:sscanf non si muove, esegue la scansione dello stesso intero ogni volta! C

int i; 
int getout=0; 
for(i=0; i<bsize && !getout;i++){ 
    if(!sscanf(startbuffer, "%d", &startarray[i])){ 
    getout=1; 
    } 
} 
//startbuffer is a string, startarray is an int array. 

Ciò si traduce nell'avere tutti gli elementi di startarray di essere il primo carattere in startbuffer. sscanf funziona bene ma non si sposta sul successivo int ma rimane nella prima posizione.

Qualche idea di cosa c'è che non va? Grazie.

+0

possibile duplicato del [Ottiene il numero di caratteri letti da sscanf?] (Http://stackoverflow.com/questions/13503135/get-number-of-characters-read-by-sscanf) – sashoalm

risposta

12

Lo stesso puntatore a stringa viene passato ogni volta che si chiama sscanf. Se dovesse "spostare" l'input, dovrebbe spostare tutti i byte della stringa ogni volta che sarebbe lento per le stringhe lunghe. Inoltre, sposterebbe i byte che non sono stati scansionati.

Invece, è necessario implementare questo da soli interrogandoli per il numero di byte consumati e il numero di valori letti. Usa queste informazioni per regolare da solo i puntatori.

int nums_now, bytes_now; 
int bytes_consumed = 0, nums_read = 0; 

while ((nums_now = 
     sscanf(string + bytes_consumed, "%d%n", arr + nums_read, & bytes_now) 
     ) > 0) { 
    bytes_consumed += bytes_now; 
    nums_read += nums_now; 
} 
+0

Sto ottenendo valori falsi per 'nums_now' quando' bytes_consumed == strlen (string) '(sul ultima chiamata che dovrebbe interrompere il ciclo). Anche questo è previsto? –

+0

@mangledorf Secondo [specifica] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html), "Se l'input termina prima della prima conversione (se presente) completata e senza dopo che si è verificato un errore, EOF deve essere restituito. " Questo suona come zero viene essenzialmente rimappato in uno negativo. – Potatoswatter

+0

ahah! Quindi è molto importante che num_rows sia un intero _signed_. È piuttosto sottile. –

4

Questo è il comportamento corretto di sscanf. sscanf funziona su un const char*, non un flusso di input da un file, quindi non memorizzerà alcuna informazione su ciò che ha consumato.

Per quanto riguarda la soluzione, è possibile utilizzare %n nella stringa di formato per ottenere il numero di caratteri che ha consumato fino ad ora (definito in C89 standard).

ad es. sscanf("This is a string", "%10s%10s%n", tok1, tok2, &numChar);numChar conterrà il numero di caratteri consumati fino a quel momento. È possibile utilizzare questo come offset per continuare la scansione della stringa.

Se la stringa contiene solo numeri interi che non superano il valore massimo del tipo lungo (o del tipo lungo lungo), utilizzare strtol o strtoll. Fai attenzione che il tipo long può essere a 32 o 64 bit, a seconda del sistema.

4

Si è corretto: sscanf infatti non "sposta", perché non c'è nulla da spostare. Se hai bisogno di scansionare un po 'di intes, puoi usare strtol - ti dice quanto legge, in modo da poter alimentare il prossimo puntatore alla funzione alla successiva iterazione.

char str[] = "10 21 32 43 54"; 
char *p = str; 
int i; 
for (i = 0 ; i != 5 ; i++) { 
    int n = strtol(p, &p, 10); 
    printf("%d\n", n); 
} 
Problemi correlati