2009-06-09 7 views
6

Ich weiß, dass dies eine völlig neue Frage sein kann (ich habe C schon lange nicht mehr berührt), aber kann mir jemand sagen, warum das nicht funktioniert?strcmp funktioniert nicht

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

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

Wenn ich geben Sie „exit“ es nicht in die wenn, muss es mit der Länge der „Puffer“ zu tun?

Irgendwelche Vorschläge?

Antwort

18

Sie wollen, dies zu tun:

strcmp(buffer, "exit\n")

Das heißt, wenn Sie die Zeichenfolge ein und drücken Sie "Enter" eingeben, das Newline ein Teil von buffer wird.

Alternativ verwenden strncmp(), die nur n Zeichen der Zeichenfolge

+4

Das ist gut, es sei denn, der Benutzer gibt ein Leerzeichen vor oder nach dem Beenden ein.Und vergessen Sie nicht die (wahrscheinlich apokryphe) Geschichte des Systems, das nicht mehr funktionierte, als Ecuador hinzugefügt wurde - die Leute mussten Quito für den Namen der Hauptstadt eingeben, und das Programm wurde beendet, weil nur die ersten 4 Buchstaben verglichen wurden 'Verlassen'. Ziemlich böse! –

+3

@ Jonathan Wahrheiten! Mein eigener Vorschlag besteht darin, sicherzustellen, dass der Benutzer niemals etwas in sein Programm eingeben darf. – poundifdef

9

fgets() gibt die Zeichenfolge "exit \ n" zurück - im Gegensatz zu gets() behält sie Zeilenumbrüche bei.

+0

... und "gets" nimmt nur einen Parameter (Puffer in diesem Beispiel). Vielen Dank! – juan

+8

(Bitte verwenden Sie nicht gets() in der Öffentlichkeit.) – Dave

+0

@Dave warum ist das? –

5

Wie bereits gesagt wurde, mit "exit" Vergleich fehlschlägt, weil fgets() die Neue-Zeile in dem Puffer enthalten. Eine der Garantien ist, dass der Puffer mit einem Newline endet, es sei denn, die eingegebene Zeile ist zu lang für den Puffer, in diesem Fall endet es nicht mit einem Newline. fgets() auch garantieren, dass der Puffer null terminiert ist, so müssen Sie nicht 256 Bytes Null, sondern nur fgets() 255 verwenden, um diese Garantie zu erhalten.

Die einfache Antwort des Vergleichens mit genau "exit\n" erforderte, dass der Benutzer vor oder nach dem Wort nicht zufällig Whitespace hinzugefügt. Das kann nicht von Bedeutung sein, wenn Sie den Benutzer zwingen möchten, mit dem Befehl exit vorsichtig zu sein, aber im Allgemeinen eine Quelle der Benutzerbelästigung sein könnte.

Die Verwendung von strncmp() ermöglicht möglicherweise "exited", "exit42" und mehr, um zu entsprechen, wo Sie sie möglicherweise nicht möchten. Das kann gegen Sie arbeiten, besonders wenn einige gültige Befehle Präfix-Strings anderer gültiger Befehle sind.

Im allgemeinen Fall ist es oft eine gute Idee, I/O, Tokenization, Parsing und Aktion in ihre eigenen Phasen zu trennen.

+0

Verwenden Sie: fgets (Puffer, sizeof (Puffer), fp); und subtrahieren Sie nicht eins (oder verwenden Sie 255), da sich fgets() normal verhält - Sie haben ihm gesagt, wie viel Platz es gibt, und es stellt sicher, dass es keinen mehr verwendet und den Null-Terminator in das letzte verfügbare Zeichen im Array platziert. –

+0

Genau das, was ich sagen wollte ... aber besser gesagt. ;-) – RBerteig

0

Ich würde empfehlen, dass Sie das \ n vom Ende der Zeichenfolge entfernen, so.

 
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; 
} 

diese Weise, wenn Sie die eingegebene Zeichenkette gegen mehrere Konstanten vergleichen haben, sind mit Ihnen nicht die \ n für alle von ihnen hinzuzufügen.

+0

Warum der Downvote? Es ist eine gültige Lösung, obwohl es nicht erklärt wird. –

Verwandte Themen