web-dev-qa-db-fra.com

Comment lire une chaîne entrée par l'utilisateur en C?

Je veux lire le nom saisi par mon utilisateur à l'aide des programmes C.

Pour cela j'ai écrit:

char name[20];

printf("Enter name: ");
gets(name);

Mais utiliser gets n’est pas bon, alors quel est le meilleur moyen?

47
Peeyush

Vous devriez jamais utiliser gets (ou scanf avec une taille de chaîne non limitée) car cela vous ouvrirait la voie aux dépassements de mémoire tampon. Utilisez le fgets avec un stdin car il vous permet de limiter les données qui seront placées dans votre tampon.

Voici un petit extrait que j'utilise pour la saisie de ligne de l'utilisateur:

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

#define OK       0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
    int ch, extra;

    // Get line with buffer overrun protection.
    if (prmpt != NULL) {
        printf ("%s", prmpt);
        fflush (stdout);
    }
    if (fgets (buff, sz, stdin) == NULL)
        return NO_INPUT;

    // If it was too long, there'll be no newline. In that case, we flush
    // to end of line so that excess doesn't affect the next call.
    if (buff[strlen(buff)-1] != '\n') {
        extra = 0;
        while (((ch = getchar()) != '\n') && (ch != EOF))
            extra = 1;
        return (extra == 1) ? TOO_LONG : OK;
    }

    // Otherwise remove newline and give string back to caller.
    buff[strlen(buff)-1] = '\0';
    return OK;
}

Cela me permet de définir la taille maximale, détectera si trop de données sont entrées sur la ligne et videra le reste de la ligne de manière à ne pas affecter l’opération d’entrée suivante.

Vous pouvez le tester avec quelque chose comme:

// Test program for getLine().

int main (void) {
    int rc;
    char buff[10];

    rc = getLine ("Enter string> ", buff, sizeof(buff));
    if (rc == NO_INPUT) {
        // Extra NL since my system doesn't output that on EOF.
        printf ("\nNo input\n");
        return 1;
    }

    if (rc == TOO_LONG) {
        printf ("Input too long [%s]\n", buff);
        return 1;
    }

    printf ("OK [%s]\n", buff);

    return 0;
}
80
paxdiablo

Je pense que le moyen le plus sûr et le plus sûr de lire les chaînes entrées par l'utilisateur est d'utiliser getline()

Voici un exemple comment faire cela:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    char *buffer = NULL;
    int read;
    unsigned int len;
    read = getline(&buffer, &len, stdin);
    if (-1 != read)
        puts(buffer);
    else
        printf("No line read...\n");

    printf("Size read: %d\n Len: %d\n", read, len);
    free(buffer);
    return 0;
}
17
joaopauloribeiro

Sur un système POSIX, vous devriez probablement utiliser getline s'il est disponible.

Vous pouvez également utiliser la fonction ggets du domaine public de Chuck Falconer qui fournit une syntaxe plus proche de gets mais sans les problèmes. (Le site Web de Chuck Falconer n'est plus disponible, bien que archive.org en ait une copie , et j'ai déjà créé ma propre page pour les gadgets .)

6
jamesdlin

J'ai trouvé une solution simple et agréable:

char*string_acquire(char*s,int size,FILE*stream){
    int i;
    fgets(s,size,stream);
    i=strlen(s)-1;
    if(s[i]!='\n') while(getchar()!='\n');
    if(s[i]=='\n') s[i]='\0';
    return s;
}

il est basé sur fgets mais ne contient pas de caractères supplémentaires '\ n' et stdin (pour remplacer fflush (stdin) qui ne fonctionne pas sur tous les systèmes d'exploitation, utile si vous devez acquérir des chaînes après cela).

3
faber

Sur les systèmes BSD et Android, vous pouvez également utiliser fgetln:

#include <stdio.h>

char *
fgetln(FILE *stream, size_t *len);

Ainsi:

size_t line_len;
const char *line = fgetln(stdin, &line_len);

Le line n'est pas terminé et contient \n (ou ce que votre plate-forme utilise) à la fin. Il devient invalide après la prochaine opération d'E/S sur le flux. Vous êtes autorisé à modifier le tampon line renvoyé.

1
wonder.mice

Vous pouvez utiliser la fonction scanf pour lire une chaîne

scanf("%[^\n]",name);

je ne connais pas d'autres options plus efficaces pour recevoir des chaînes,

0
user1938455