2017-04-02 2 views
2

Je l'habitude d'utiliser obtient mais j'ai entendu dire qu'il a été retiré de c11 et que c'est globalement très dangereux. J'ai donc fait quelques recherches et j'ai découvert que vous pouvez utiliser fgets() pour faire la même chose. Le problème est que lorsque j'utilise fgets(), il semble également copier la fin de la ligne, ce qui finit par créer une ligne supplémentaire non désirée.Alternative à obtenir?

Pour vous montrer ce que je veux dire:

//if I have 
char key[30]; 
fgets(key, sizeof(key), stdin); 

//now if ender for instance: Doggo and do: 
printf("The key is:%s|hozaah!\n", key); 

//I expect it to print: 
The key is:Doggo|hozaah! 

//Instead it prints: 
The key is:Doggo 
|hozaah! 

est-il un moyen de contourner ce problème? Ou y a-t-il une autre fonction que je peux utiliser à la place?

+1

trouvé que la clé [strcspn (key, "\ n")] = 0; fonctionne comme un charme, merci! – Mathue24

+0

@Kerrek Chill mec, il essayait juste d'aider, pas besoin d'être si arrogant lol – Mathue24

+0

@ Mathue24: Oui, des excuses, assez juste.Je suis un peu trop sensible aux mauvaises cargaisons autour des chaînes de caractères C, car la plupart des vulnérabilités logicielles proviennent d'une mauvaise compréhension des chaînes de caractères et des chaînes de caractères. C'est quelque chose que je veux que les gens pensent avec soin. –

Répondre

4

Il n'y a pas de norme remplacement direct pour gets(), mais il y a plusieurs façons facile de se débarrasser de la nouvelle ligne si elle est présente:

  • Le plus simple en utilisant strcspn (déclarée <string.h>):

    if (fgets(buf, sizeof buf, fp)) { 
        buf[strcspn(buf, "\n")] = '\0'; 
    } 
    
  • Le classique en utilisant strlen:

    if (fgets(buf, sizeof buf, fp)) { 
        size_t len = strlen(buf); 
        if (len > 0 && buf[len - 1] == '\n') 
         buf[--len] = '\0'; 
    } 
    
  • Un autre classique avec strchr:

    if (fgets(buf, sizeof buf, fp)) { 
        char *p = strchr(buf, '\n'); 
        if (p != NULL) 
         *p = '\0'; 
    } 
    

Une alternative est la fonction POSIX getline() qui pourrait être disponible sur votre système:

#include <stdio.h> 
ssize_t getline(char **lineptr, size_t *n, FILE *stream); 

Le tampon est affecté ou réaffecté avec malloc() et son la taille est mise à jour en *n. Les valeurs initiales doivent être lineptr = NULL et n = 0.

1

La réponse réside dans le fait que fgets lit autant de caractères que forme dans la mémoire tampon, y compris une terminaison nulle, mais seulement jusqu'à la fin du fichier ou une nouvelle ligne, et il sera magasin la nouvelle ligne dans la chaîne, aussi:

Ainsi, si vous entrez une entrée sur le terminal, la nouvelle ligne est également transmise à l'entrée standard et lue par fgets. Ceci est différent de l'ancien gets, qui remplace le saut de ligne par un octet nul. Par conséquent, si vous lisez des lignes et que vous ne voulez pas le retour à la ligne potentiel, effacez-le. Malheureusement, fgets ne vous dit pas combien de caractères ont été lus, donc vous devez analyser la chaîne à nouveau travailler dehors:

char* p = fgets(key, sizeof(key), stdin); 

if (!p) { /* error */ } 

size_t n = strlen(key); 

if (n > 0 && key[n - 1] == '\n') { 
    key[n - 1] = '\0'; 
} else { 
    /* buffer too short or EOF reached without newline */ 
} 

printf("The line was: '%s'\n", key); 

Il peut être utile de considérer des alternatives: Si vous avez seulement besoin d'une entrée, ne pas entrer la nouvelle ligne en premier lieu. Si vous avez besoin de beaucoup de lignes, utilisez fread dans un tampon de taille fixe et analysez vous-même les retours à la ligne.

+0

[Démo] (https://wandbox.org/permlink/AwlDxatyy7fnSuXF), essayez-le avec et sans retour d'entrée. –