2016-10-08 5 views
5

Ich habe diese Struktur getestet und ich werde gewarnt, gets zu verwenden. Jemand erwähnte, stattdessen fgets zu verwenden und das Ende durch '\0' zu ersetzen. Irgendwelche Empfehlungen, wie ich meinen Code ändern kann, um das zu tun?Ersetzen von gets() mit fgets()

void regCars(Car reg[], int *pNrOfCars) { 
    char again[WORDLENGTH] = "yes", model[WORDLENGTH], tmp[WORDLENGTH]; 
    int year, milage; 

    while (strcmp(again, "yes") == 0) { 
     printf("Enter model:"); 
     gets(model); 
     printf("Enter Year:"); 
     gets(tmp); 
     year = atoi(tmp); 
     printf("Enter milage:"); 
     gets(tmp); 
     milage = atoi(tmp); 
     reg[*pNrOfCars] = createCar(model, year, milage); 
     (*pNrOfCars)++; 
     printf("Continue? (yes/no)"); 
     gets(again); 
    } 
} 

Antwort

0

Sie können eine Nutzenfunktion mygets() schreiben, die zwei Argumente nimmt: einen Zeiger auf das Zielfeld und seine Größe:

char *mygets(char *dest, size_t size) { 
    /* read a line from standard input and strip the linefeed if any */ 
    if (fgets(dest, size, stdin)) { 
     dest[strcspn(dest, "\n")] = '\0'); 
     return dest; 
    } 
    return NULL; 
} 

void regCars(Car reg[], int *pNrOfCars) { 
    char model[WORDLENGTH], tmp[WORDLENGTH]; 
    int year, milage; 

    for (;;) { 
     printf("Enter model:"); 
     if (!mygets(model, sizeof mode)) 
      break; 
     printf("Enter year:"); 
     if (!mygets(tmp, sizeof tmp)) 
      break; 
     year = atoi(tmp); 
     printf("Enter milage:"); 
     if (!mygets(tmp, sizeof tmp)) 
      break; 
     milage = atoi(tmp); 
     reg[*pNrOfCars] = createCar(model, year, milage); 
     (*pNrOfCars)++; 
     printf("Continue? (yes/no)"); 
     if (!mygets(tmp, sizeof(tmp)) 
      break; 
     if (strcmp(again, "yes") != 0) 
      break; 
    } 
} 

Beachten Sie, dass Sie mehr Code mit einer prompt() Funktion, die die Ausgänge faktorisieren kann und Frage lautet die Antwort:

char *prompt(const char *message, char *dest, size_t size) { 
    printf("%s ", message); 
    fflush(stdout); 
    /* read a line from standard input and strip the linefeed if any */ 
    if (fgets(dest, size, stdin)) { 
     dest[strcspn(dest, "\n")] = '\0'); 
     return dest; 
    } 
    return NULL; 
} 

void regCars(Car reg[], int *pNrOfCars) { 
    char model[WORDLENGTH], tmp[WORDLENGTH]; 
    int year, milage; 

    for (;;) { 
     if (!prompt("Enter model:", model, sizeof mode)) 
      break; 
     if (!prompt("Enter year:", tmp, sizeof tmp)) 
      break; 
     year = atoi(tmp); 
     if (!prompt("Enter milage:", tmp, sizeof tmp)) 
      break; 
     milage = atoi(tmp); 
     reg[*pNrOfCars] = createCar(model, year, milage); 
     (*pNrOfCars)++; 
     if (!prompt("Continue? (yes/no)", tmp, sizeof(tmp)) 
      break; 
     if (strcmp(again, "yes") != 0) 
      break; 
    } 
} 

beachten Sie auch, dass diese Funktion die Größe desnehmen sollteArray, um die Eingabeaufforderung zu beenden, wenn sie voll ist. Wie derzeit angegeben, weist es den gleichen Nachteil auf wie gets(), unerwartete Eingaben führen zu undefiniertem Verhalten.

+0

@Alex: Stimmst du die Antwort, die du angenommen hast, hoch? – chqrlie

0

Just do zum Beispiel

if (NULL != fgets(model, WORDLENGTH, stdin)) /* Read the string. */ 
{ 
    model[strcspn(model, "\r\n")] = '\0'; /* Cut off \n and/or \r, if any. */ 
} 
+0

Ich denke, das ist es nur für das Modell tun, wenn ich multiplizieren int und char, gibt es eine Funktion, die durch alle von ihnen schauen und ersetzen die \ n? – xxFlashxx

+0

@Alex: 'fgets()' (sowie 'get() ') liest nur" strings ". Um das "Jahr" zu lesen, verwenden Sie 'gets (tmp)', das wie gezeigt ersetzt werden kann. – alk

+0

Also füge ich die if-Anweisung direkt nach fgets (Modell) ein? – xxFlashxx

1

Es ist ein bisschen tricker als es aussieht. Es hat nicht viel Sinn, nur gets mit fgets() zu ersetzen, wenn Sie dann eine abgeschnittene Zeile bei überlangen Eingaben verarbeiten und als gültig behandeln. Sie haben lediglich undefiniertes Verhalten durch falsches Verhalten ersetzt.

if(fgets(line, sizeof(line), fp)) 
{ 
    if(!strchr(line, '\n')) 
    { 
     /* line is too long, what you do is up to you, but normally 
     we will discard it */ 
     int ch; 

     while((ch = fgetc(fp)) != EOF) 
     if(ch == '\n') 
      break; 

    } 
    else 
    { 
     /* line is a normal line with a trailing '\n' (gets trims the '\n')   */ 
    } 
} 
+0

Es ist nicht notwendig, nur lange Zeilen zu verwerfen ... und lange Zeilen treten ziemlich häufig in Textdateien auf, die von Computerprogrammen geschrieben werden. 'fgets()' kann sie lesen ... es braucht nur mehr Aufrufe und Logik, um damit umzugehen. – Peter

+0

Wenn gültige Zeilen unbeschränkt sind, ist fgets() nicht die Eingabefunktion Ihrer Wahl. Aber was eine überlange Linie bedeutet, wird natürlich von der Situation bestimmt, und manchmal ist es falsch, sie zu verwerfen. Das stillschweigende Abschneiden und das Nicht-Unterscheiden des Rests von einer vollen Zeile ist jedoch fast nie korrekt. –