leer dev caracteres cadenas c memory-management malloc printf scanf

dev - ¿Cómo permite que se ingresen espacios usando scanf?



scanf dev c++ (11)

Usando el siguiente código:

char *name = malloc(sizeof(char) + 256); printf("What is your name? "); scanf("%s", name); printf("Hello %s. Nice to meet you./n", name);

Un usuario puede ingresar su nombre, pero cuando ingresa un nombre con un espacio como Lucas Aardvark , scanf() simplemente corta todo después de Lucas . ¿Cómo hago que scanf() permita espacios?


Este ejemplo usa un escaner invertido, por lo que scanf sigue tomando valores hasta que encuentra una ''/ n'' - línea nueva, por lo que los espacios se guardan también

#include <stdio.h> int main (int argc, char const *argv[]) { char name[20]; scanf("%[^/n]s",name); printf("%s/n", name); return 0; }


Las personas (y especialmente los principiantes) nunca deben usar scanf("%s") o gets() o cualquier otra función que no tenga protección de desbordamiento de búfer, a menos que sepa con certeza que la entrada siempre tendrá un formato específico (y tal vez ni siquiera entonces).

Recuerde que scanf significa "escaneo formateado" y hay muy poco menos formato que los datos ingresados ​​por el usuario. Es ideal si tiene un control total del formato de datos de entrada, pero generalmente no es adecuado para la entrada del usuario.

Utilice fgets() (que tiene protección de desbordamiento de búfer) para obtener su entrada en una cadena y sscanf() para evaluarla. Como solo quiere lo que el usuario ingresó sin analizar, realmente no necesita sscanf() en este caso de todos modos:

#include <stdio.h> #include <stdlib.h> #include <string.h> /* Maximum name size + 1. */ #define MAX_NAME_SZ 256 int main(int argC, char *argV[]) { /* Allocate memory and check if okay. */ char *name = malloc(MAX_NAME_SZ); if (name == NULL) { printf("No memory/n"); return 1; } /* Ask user for name. */ printf("What is your name? "); /* Get the name, with size limit. */ fgets(name, MAX_NAME_SZ, stdin); /* Remove trailing newline, if there. */ if ((strlen(name) > 0) && (name[strlen (name) - 1] == ''/n'')) name[strlen (name) - 1] = ''/0''; /* Say hello. */ printf("Hello %s. Nice to meet you./n", name); /* Free memory and exit. */ free (name); return 0; }


No use scanf() para leer cadenas sin especificar un ancho de campo. También debe verificar los valores de retorno para los errores:

#include <stdio.h> #define NAME_MAX 80 #define NAME_MAX_S "80" int main(void) { static char name[NAME_MAX + 1]; // + 1 because of null if(scanf("%" NAME_MAX_S "[^/n]", name) != 1) { fputs("io error or premature end of line/n", stderr); return 1; } printf("Hello %s. Nice to meet you./n", name); }

Alternativamente, use fgets() :

#include <stdio.h> #define NAME_MAX 80 int main(void) { static char name[NAME_MAX + 2]; // + 2 because of newline and null if(!fgets(name, sizeof(name), stdin)) { fputs("io error/n", stderr); return 1; } // don''t print newline printf("Hello %.*s. Nice to meet you./n", strlen(name) - 1, name); }


Puede usar scanf para este propósito con un pequeño truco. En realidad, debe permitir la entrada del usuario hasta que el usuario presione Enter ( /n ). Esto tendrá en cuenta todos los personajes, incluido el espacio . Aquí hay un ejemplo:

int main() { char string[100], c; int i; printf("Enter the string: "); scanf("%s", string); i = strlen(string); // length of user input till first space do { scanf("%c", &c); string[i++] = c; // reading characters after first space (including it) } while (c != ''/n''); // until user hits Enter string[i - 1] = 0; // string terminating return 0; }

¿Cómo funciona esto? Cuando el usuario ingresa caracteres desde la entrada estándar, se almacenarán en una variable de cadena hasta el primer espacio en blanco. Después de eso, el resto de la entrada permanecerá en el flujo de entrada y esperará el próximo scanf. A continuación, tenemos un bucle for que toma char por char desde el flujo de entrada (hasta /n ) y los coloca al final de la variable de cadena , formando así una cadena completa igual a la entrada del usuario desde el teclado.

¡Espero que esto ayude a alguien!


Puede usar la fgets() para leer una cadena o usar scanf("%[^/n]s",name); así que la lectura de cadena terminará al encontrar un carácter de nueva línea.


Puedes usar esto

char name[20]; scanf("%20[^/n]", name);

O esto

void getText(char *message, char *variable, int size){ printf("/n %s: ", message); fgets(variable, sizeof(char) * size, stdin); sscanf(variable, "%[^/n]", variable); } char name[20]; getText("Your name", name, 20);

DEMO


Si alguien sigue buscando, esto es lo que funcionó para mí: leer una longitud de cadena arbitraria, incluidos los espacios.

Gracias a muchos carteles en la web para compartir esta solución simple y elegante. Si funciona, el crédito recae sobre ellos, pero cualquier error es mío.

char *name; scanf ("%m[^/n]s",&name); printf ("%s/n",name);


Si bien no debería usar scanf() para este tipo de cosas, porque hay llamadas mucho mejores, como gets() o getline() , se puede hacer:

#include <stdio.h> char* scan_line(char* buffer, int buffer_size); char* scan_line(char* buffer, int buffer_size) { char* p = buffer; int count = 0; do { char c; scanf("%c", &c); // scan a single character // break on end of line, string terminating NUL, or end of file if (c == ''/r'' || c == ''/n'' || c == 0 || c == EOF) { *p = 0; break; } *p++ = c; // add the valid character into the buffer } while (count < buffer_size - 1); // don''t overrun the buffer // ensure the string is null terminated buffer[buffer_size - 1] = 0; return buffer; } #define MAX_SCAN_LENGTH 1024 int main() { char s[MAX_SCAN_LENGTH]; printf("Enter a string: "); scan_line(s, MAX_SCAN_LENGTH); printf("got: /"%s/"/n/n", s); return 0; }


Tratar

char str[11]; scanf("%10[0-9a-zA-Z ]", str);

Espero que ayude.


Use el siguiente código para leer una cadena con espacios:
scanf("[%s/n]",str_ptr);


getline()

Ahora parte de POSIX, nada menos.

También se ocupa del problema de asignación de búfer sobre el que se le preguntó antes, aunque debe tener cuidado de free la memoria.