2009-06-09 8 views
6

So che questa può essere una domanda totalmente nuova (non ho ancora toccato C da molto tempo), ma qualcuno può dirmi perché questo non funziona?strcmp non funziona

printf("Enter command: "); 
bzero(buffer,256); 
fgets(buffer,255,stdin); 

if (strcmp(buffer, "exit") == 0) 
    return 0; 

Se entro "uscita" che non entra il caso, ha a che fare con la lunghezza di "buffer"?

Qualche suggerimento?

risposta

18

si vuole fare questo:

strcmp(buffer, "exit\n")

Cioè, quando si immette la stringa e premere "Invio", il ritorno a capo diventa una parte di buffer.

In alternativa, utilizzare strncmp(), che confronta soltanto n caratteri della stringa

+4

Questo va bene a meno che l'utente non digiti uno spazio prima o dopo, esci.E non dimenticare la storia (probabilmente apocrifa) del sistema che ha smesso di funzionare quando è stato aggiunto l'Ecuador - la gente ha dovuto digitare Quito per il nome della capitale, e il programma è uscito (esci) perché solo le prime 4 lettere sono state confrontate con 'smettere'. Abbastanza cattivo –

+3

@Jonathan verità! il mio suggerimento è di garantire che l'utente non sia mai autorizzato a inserire qualcosa nel tuo programma. – poundifdef

9

fgets() restituisce la stringa "exit \ n" - a differenza di gets(), mantiene le newline.

+0

... e "ottiene" richiede solo un parametro (buffer in questo esempio). Grazie! – juan

+8

(Per favore non usare gets() in pubblico.) – Dave

+0

@Dave perché è così? –

5

Come altri hanno già detto, confrontando con "exit" non riesce a causa fgets() incluso il newline nel buffer. Una delle sue garanzie è che il buffer terminerà con una nuova riga, a meno che la riga immessa non sia troppo lunga per il buffer, nel qual caso non termina con una nuova riga. fgets() garantisce inoltre che il buffer non sia terminato, quindi non è necessario azzerare 256 byte ma solo lasciare che fgets() utilizzi 255 per ottenere tale garanzia.

La semplice risposta del confronto a esattamente "exit\n" richiedeva che l'utente non aggiungesse accidentalmente spazi bianchi prima o dopo la parola. Ciò potrebbe non avere importanza se si desidera forzare l'utente a fare attenzione con il comando di uscita, ma in generale potrebbe essere una fonte di disturbo dell'utente.

L'utilizzo di strncmp() utilizza potenzialmente "exited", "exit42" e altro per corrispondere a dove potresti non volere. Potrebbe funzionare contro di te, specialmente se alcuni comandi validi sono stringhe di prefisso di altri comandi validi.

Nel caso generale, è spesso una buona idea separare I/O, tokenizzazione, analisi e azione nelle proprie fasi.

+0

Usa: fgets (buffer, sizeof (buffer), fp); e non sottrarre uno (o usare 255) perché fgets() si comporta in modo sano - gli hai detto quanto spazio c'è, e assicura che non usi più, ponendo il terminatore null nell'ultimo carattere disponibile nell'array. –

+0

Esattamente quello che stavo cercando di dire ... ma meglio detto. ;-) – RBerteig

0

Si consiglia di rimuovere \ n dalla fine della stringa, in questo modo.

 
char buf[256]; 
int len; 
/* get the string, being sure to leave room for a null byte */ 
if (fgets(buf,sizeof(buf) - 1) == EOF) 
{ 
    printf("error\n"); 
    exit(1); 
} 
/* absolutely always null-terminate, the easy way */ 
buf[sizeof(buf) - 1] = '\0'; 
/* compute the length, and truncate the \n if any */ 
len = strlen(buf); 
while (len > 0 && buf[len - 1] == '\n') 
{ 
    buf[len - 1] = '\0'; 
    --len; 
} 

In questo modo, se si deve confrontare la stringa immessa nei confronti di diverse costanti, non sei dover aggiungere il \ n a tutti loro.

+0

Perché il downvote? È una soluzione valida sebbene non sia spiegata. –

Problemi correlati