resueltos - ¿Cómo leo una cadena ingresada por el usuario en C?
funciones de cadenas de caracteres en c++ (6)
Quiero leer el nombre ingresado por mi usuario usando C programas.
Para esto escribí:
char name[20];
printf("Enter name: ");
gets(name);
Pero usar gets
no es bueno, entonces, ¿cuál es la mejor manera?
Creo que la mejor y más segura forma de leer cadenas ingresadas por el usuario es usando 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;
}
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);
La line
no tiene terminación nula y contiene /n
(o lo que sea que use su plataforma) al final. Se vuelve inválido después de la siguiente operación de E / S en la transmisión. Puede modificar el buffer de line
devuelto.
En un sistema POSIX, probablemente deba usar getline
si está disponible.
También puede usar la función de los ggets
dominio público de Chuck Falconer, que proporciona la sintaxis más cercana pero sin los problemas. (El sitio web de Chuck Falconer ya no está disponible, aunque archive.org tiene una copia , y yo hice mi propia página para los ggets ).
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;
}
está basado en fgets pero libre de ''/ n'' y caracteres adicionales stdin (para reemplazar fflush (stdin) que no funciona en todos los SO, útil si tienes que adquirir cadenas después de esto).
Nunca debe usar gets
(o scanf
con un tamaño de cadena ilimitada) ya que eso lo abre a desbordamientos de búfer. Usa los fgets
con un controlador stdin
ya que te permite limitar los datos que se colocarán en tu búfer.
Aquí hay un pequeño fragmento que uso para la entrada de línea del usuario:
#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;
}
Esto me permite establecer el tamaño máximo, detectará si se ingresan demasiados datos en la línea y también vaciará el resto de la línea para que no afecte la siguiente operación de entrada.
Puedes probarlo con algo como:
// 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;
}
Puede usar la función scanf para leer una cadena
scanf("%[^/n]",name);
no sé sobre otras mejores opciones para recibir cadenas,