2016-11-11 6 views
6

Ich versuche, eine Zeichenfolge einzulesen, die Leerzeichen enthalten kann oder nicht. "Hallo Welt". Indem Sie die folgenden Schritte mit einem Zahlenauswahlmenü ausführen, das vom Benutzer eingegeben wird. Dies ist nur eine kleine Replik von dem, was ich versuche zu tun.Lesen einer Zeichenfolge mit Leerzeichen in C

#include <stdio.h> 
#include <string.h> 

int main(void){ 
    char line[3][80]; 

    strcpy(line[0],"default line 1\n"); 
    strcpy(line[1],"default line 2\n"); 
    strcpy(line[2],"default line 3\n"); 

    for(int i = 0; i < 3; i++){ 
    printf("%s", line[i]); 
    } 

    int option = 0; 
    printf("would you like to replace line 1? (1 for yes)\n"); 
    scanf("%d",&option); 
    if(option==1){ 
    printf("what would you like to replace the line with?\n"); 
    fgets(line[0],strlen(line[0]),stdin); 
    } 

    for(int i = 0; i < 3; i++){ 
    printf("%s", line[i]); 
    } 
} 

Warum ist es, dass ich nach 1 geben Sie die Zeile zu ändern, ist es die Anweisung druckt zu fragen, was ich mit ihm ersetzt werden soll und wird automatisch nichts und geben Sie die Saiten mit dem ersten Druck als leer?

Ich habe auch schon versucht, die Zeile mit sscanf("%[^\n\t]s", line[0]); ohne Glück zu lesen. Irgendwelche Ideen?

+0

Ich würde vermuten, dass 'fgets' ein EOF (Ende der Datei) gelesen als erstes Zeichen des Streams. –

+0

Ich bin ziemlich sicher, dass es etwas mit dem 'scanf ("% d ", & Option)' zu tun hat, wenn gefragt wird, ob der Benutzer die Zeile ersetzen möchte, aber ich bin nicht sicher, ob es eine Möglichkeit gibt, das zu beheben. – TheBoxOkay

+2

Nicht direkt mit Ihrem Problem verbunden, aber 'strlen (line [0])' sollte durch '80' ersetzt werden. Die Größe des Puffers ist nicht die Länge der Zeichenkette, die er enthält, sondern die Gesamtlänge des Puffers, der hier "80" ist. –

Antwort

10

Es ist, weil

scanf("%d",&option); 

die \n Zeichen in stdin verlässt und durch den ersten Aufruf zu fgets() verbraucht. Deshalb ist es am besten, scanf() in C vollständig zu vermeiden.

Sie können das Problem beheben mit:

scanf("%d",&option); 
    getchar(); /* consume the newline */ 

Aber ich würde mit fgets() vorschlagen option auch lesen und dann können Sie strtol() verwenden Sie es in eine ganze Zahl zu konvertieren.

Beachten Sie, dass diese Aussage wahrscheinlich nicht das ist, was Sie beabsichtigten (was das begrenzt, was Sie in line[0] lesen können).

fgets(line[0],sizeof line[0],stdin); 

, so dass Sie bis zu der tatsächlichen Größe der line[0] lesen:

fgets(line[0],strlen(line[0]),stdin); 

Sie wahrscheinlich verwenden sollten.

Bitte lesen Sie den C FAQ-Eintrag auch: http://c-faq.com/stdio/scanfprobs.html

+3

Ich bestätige, 'scanf' ist schrecklich und diese Art von Problemen sind üblich. Google _scanf ist evil_ (kein Witz) für weitere Informationen. –

+0

Vielen Dank, das hat perfekt funktioniert! – TheBoxOkay

2

Ihr Problem ist, dass die '\n' char in stdin gelassen werden und durch fgets verbraucht.

Ich würde vorschlagen, dass Sie immer fgets Eingänge für Lese verwenden, so

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int main(void) 
{ 
    char line[3][80]; 
    char temp[3]; 

    strcpy(line[0],"default line 1\n"); 
    strcpy(line[1],"default line 2\n"); 
    strcpy(line[2],"default line 3\n"); 

    for(int i = 0; i < 3; i++){ 
     printf("%s", line[i]); 
    } 

    int option = 0; 
    printf("would you like to replace line 1? (1 for yes)\n"); 
    fgets(temp,sizeof(temp),stdin); 
    option = atoi(temp); 

    if(option==1){ 
     printf("what would you like to replace the line with?\n"); 
     fgets(line[0],sizeof(line[0]),stdin); 
    } 

    for(int i = 0; i < 3; i++){ 
    printf("%s", line[i]); 
    } 
} 
3

Mit fgets() scheint im Allgemeinen weniger fehleranfällig als bei scanf() verheddern, aber wenn der Benutzer gibt eine Zeichenfolge, die so lang wie oder länger als die maximale Anzahl der angegebenen Zeichen, alle zusätzlichen Zeichen bis einschließlich des Zeilenumbruchs verbleiben im Eingabestream. Aus diesem Grund schreibe ich normalerweise meine eigene Version von gets(), um Eingabezeichenfolgen vom Benutzer zu erhalten, und wenn ich eine numerische Eingabe möchte, verwende ich strtol(). Hier ist ein Beispiel für eine solche Funktion:

char * s_gets(char *st, int n) 
{ 
    char *ret; 
    int ch; 

    ret = fgets(st, n, stdin); 
    if (ret) { 
     while (*st != '\n' && *st != '\0') 
      ++st; 
     if (*st) 
      *st = '\0'; 
     else { 
      while ((ch = getchar()) != '\n' && ch != EOF) 
       continue;   // discard extra characters 
     } 
    } 
    return ret; 
} 

zum OPs Problem angewandt, könnte ich so etwas tun:

#include <stdlib.h>    // for strtol() 

... 

char buf[80]; 
int option = 0; 

printf("would you like to replace line 1? (1 for yes)\n"); 
s_gets(buf, sizeof(buf)); 
option = strtol(buf, NULL, 10); 

if(option==1){ 
    printf("what would you like to replace the line with?\n"); 
    s_gets(line[0],sizeof(line[0])); 
} 
Verwandte Themen