2016-10-08 6 views
5

J'ai testé cette structure et je reçois un avertissement concernant l'utilisation de gets. Quelqu'un a mentionné utiliser fgets à la place et remplacer la fin par '\0'. Toute recommandation comment je peux changer mon code pour le faire?Remplacement de gets() avec 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); 
    } 
} 

Répondre

0

Vous pouvez écrire une fonction d'utilité mygets() qui prend 2 arguments: un pointeur vers le tableau de destination et sa taille:

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

Notez que vous pouvez factoriser plus de code avec une fonction prompt() qui sort la question et lit la réponse:

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

Notez également que cette fonction devrait prendre la taille de la reg tableau pour cesser de demander plus d'entrée lorsqu'il est plein. Comme actuellement spécifié, il a le même défaut que gets(), une entrée inattendue entraînera un comportement indéfini.

+0

@Alex: cela vous dérange-t-il de voter la réponse que vous avez acceptée? – chqrlie

0

Il suffit de faire par exemple

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

Je pense que cela va le faire juste pour le modèle, si j'ai multiplier int et char, y at-il une fonction qui peut parcourir tous et remplacer le \ n? – xxFlashxx

+0

@Alex: 'fgets()' (ainsi que 'get() ') lit uniquement les" chaînes ". Pour lire l '"année", vous utilisez 'gets (tmp)', qui peut être remplacé comme indiqué. – alk

+0

alors j'insère l'instruction if juste après fgets (model)? – xxFlashxx

1

Il est un peu Tricker qu'il n'y paraît. Il ne sert à rien de remplacer get avec fgets(), si vous traitez ensuite une ligne tronquée sur une entrée trop longue et que vous la gérez comme valide. Vous avez simplement remplacé un comportement indéfini par un comportement incorrect.

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

Il n'est pas nécessaire d'éliminer les longues lignes ... et les longues lignes se produisent assez fréquemment dans les fichiers texte écrits par des programmes informatiques. 'fgets()' peut les lire ... il faut juste plus d'appels, et de la logique pour gérer ça. – Peter

+0

Si les lignes valides sont illimitées, fgets() n'est pas votre fonction d'entrée de choix. Mais bien sûr, ce que signifie une ligne trop longue est déterminée par la situation, et parfois la rejeter est fausse. Tromper silencieusement et laisser le reste indissociable d'une ligne complète n'est cependant jamais un comportement correct. –