¿Cómo leo una cadena ingresada por el usuario en C?

4 minutos de lectura

avatar de usuario
Peeyush

Quiero leer el nombre ingresado por mi usuario usando programas C.

Para esto escribí:

char name[20];

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

pero usando gets no es bueno, entonces, ¿cuál es una mejor manera?

avatar de usuario
nicaragua

Encontré una solución fácil y agradable:

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

se basa en fgets pero no tiene caracteres adicionales ‘\n’ ni stdin (reemplazar fflush(stdin) no funciona en todos los sistemas operativos, útil si tiene que adquirir cadenas después de esto).

  • Esto debería usar fgetc en vez de getchar para que utilice el suministrado stream en vez de stdin.

    – jamesdlin

    7 febrero 2019 a las 23:42

  • Con la salvedad de que no funciona como se esperaba con archivos que terminan solo en CR. Esos no son tan raros como te puedes imaginar (dice, después de encontrar una carpeta llena de ellos). Es una oportunidad perdida que no permitieron que getdelim/getline tomara una lista de delimitadores en lugar de un solo int.

    – Maury Markowitz

    27 de febrero de 2018 a las 19:53

  • @MauryMarkowitz Funcionaría en un sistema que usa CR como su formato nativo de final de línea. Las secuencias en modo texto convertirán cualquier tipo de final de línea nativo a \n.

    – jamesdlin

    28 de febrero de 2018 a las 3:57

avatar de usuario
joaopauloribeiro

Creo que la forma mejor y más segura de leer las cadenas ingresadas por el usuario es usar getline()

Aquí hay un ejemplo de cómo hacer esto:

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

  • leer = getline(&buffer, &len, stdin); da advertencias de GCC, por ejemplo: gcc -Wall -c “getlineEx2.c” getlineEx2.c: En la función principal: getlineEx2.c:32:5: advertencia: pasar el argumento 2 de getline desde un tipo de puntero incompatible [enabled by default] leer = getline(&buffer, &len, stdin); ^ En el archivo incluido de /usr/include/stdio.h:29:0, de getlineEx2.c:24: /usr/include/sys/stdio.h:37:9: nota: tamaño esperado_t * pero el argumento es de tipo unsigned int * ssize_t _EXFUN(getline, (char **, size_t *, FILE *)); ^ Compilación finalizada con éxito.

    – rpd

    3 de marzo de 2014 a las 10:28


  • Solo actualizar ese getline ahora requiere que len sea size_t o long sin firmar

    – Wes

    9 de julio de 2014 a las 6:01

  • Desventaja: POSIX pero no ANSI C.

    – Ciro Santilli Путлер Капут 六四事

    27 de febrero de 2016 a las 14:25

En sistemas BSD y Android también puedes usar fgetln:

#include <stdio.h>

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

Al igual que:

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

Él line no termina en nulo y contiene \n (o lo que sea que esté usando su plataforma) al final. Se vuelve inválido después de la próxima operación de E/S en la transmisión. Se le permite modificar el devuelto line buffer.

  • leer = getline(&buffer, &len, stdin); da advertencias de GCC, por ejemplo: gcc -Wall -c “getlineEx2.c” getlineEx2.c: En la función principal: getlineEx2.c:32:5: advertencia: pasar el argumento 2 de getline desde un tipo de puntero incompatible [enabled by default] leer = getline(&buffer, &len, stdin); ^ En el archivo incluido de /usr/include/stdio.h:29:0, de getlineEx2.c:24: /usr/include/sys/stdio.h:37:9: nota: tamaño esperado_t * pero el argumento es de tipo unsigned int * ssize_t _EXFUN(getline, (char **, size_t *, FILE *)); ^ Compilación finalizada con éxito.

    – rpd

    3 de marzo de 2014 a las 10:28


  • Solo actualizar ese getline ahora requiere que len sea size_t o long sin firmar

    – Wes

    9 de julio de 2014 a las 6:01

  • Desventaja: POSIX pero no ANSI C.

    – Ciro Santilli Путлер Капут 六四事

    27 de febrero de 2016 a las 14:25

Puede usar la función scanf para leer cadenas

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

no conozco otras opciones mejores para recibir cadenas,

  • -1. Hacer no usar scanf; está notoriamente difícil de usar correctamente. Este uso es especialmente peligroso ya que no restringe la entrada y puede desbordar fácilmente el name buffer.

    – jamesdlin

    7 febrero 2019 a las 23:44

¿Ha sido útil esta solución?