¿Cómo puedo leer una cadena de entrada de longitud desconocida?

Si no sé cuánto dura la palabra, no puedo escribir char m[6]; ,
La longitud de la palabra es tal vez diez o veinte de largo. ¿Cómo puedo usar scanf para obtener entrada desde el teclado?

 #include  int main(void) { char m[6]; printf("please input a string with length=5\n"); scanf("%s",&m); printf("this is the string: %s\n", m); return 0; } 

por favor ingrese una cadena con longitud = 5
Hola
esta es la cadena: hola

Ingrese mientras asegura un área dinámicamente

P.EJ

 #include  #include  char *inputString(FILE* fp, size_t size){ //The size is extended by the input with the value of the provisional char *str; int ch; size_t len = 0; str = realloc(NULL, sizeof(char)*size);//size is start size if(!str)return str; while(EOF!=(ch=fgetc(fp)) && ch != '\n'){ str[len++]=ch; if(len==size){ str = realloc(str, sizeof(char)*(size+=16)); if(!str)return str; } } str[len++]='\0'; return realloc(str, sizeof(char)*len); } int main(void){ char *m; printf("input string : "); m = inputString(stdin, 10); printf("%s\n", m); free(m); return 0; } 

Con las computadoras de hoy en día, puede salirse con la asignación de cadenas de caracteres muy grandes (cientos de miles de caracteres) mientras que apenas hace mella en el uso de RAM de la computadora. Entonces no me preocuparía demasiado.

Sin embargo, en los viejos tiempos, cuando la memoria era escasa, la práctica común era leer cadenas en fragmentos. fgets lee hasta un número máximo de caracteres de la entrada, pero deja intacto el rest del búfer de entrada para que pueda leer el rest de la forma que desee.

en este ejemplo, leo en trozos de 200 caracteres, pero puede usar cualquier tamaño de porción que desee, por supuesto.

 #include  #include  #include  char* readinput() { #define CHUNK 200 char* input = NULL; char tempbuf[CHUNK]; size_t inputlen = 0, templen = 0; do { fgets(tempbuf, CHUNK, stdin); templen = strlen(tempbuf); inputlen += templen; input = realloc(input, inputlen+1); strcat(input, tempbuf); } while (templen==CHUNK-1 && tempbuf[CHUNK-2]!='\n'); return input; } int main() { char* result = readinput(); printf("And the result is [%s]\n", result); free(result); return 0; } 

Tenga en cuenta que este es un ejemplo simplificado sin comprobación de errores; en la vida real, tendrá que asegurarse de que la entrada sea correcta al verificar el valor de retorno de los fgets .

También tenga en cuenta que al final si la rutina readinput, no se desperdician bytes; la cadena tiene el tamaño exacto de memoria que necesita tener.

Solo he visto una forma simple de leer una cadena arbitrariamente larga, pero nunca la he usado. Creo que es así:

 char *m = NULL; printf("please input a string\n"); scanf("%ms",&m); if (m == NULL) fprintf(stderr, "That string was too long!\n"); else { printf("this is the string %s\n",m); /* ... any other use of m */ free(m); } 

El m entre % scanf() le dice a scanf() que mida la cadena y le asigne memoria y copie la cadena en esa, y que almacene la dirección de esa memoria asignada en el argumento correspondiente. Una vez que haya terminado con esto, tiene que free() .

Sin embargo, esto no es compatible con todas las implementaciones de scanf() .

Como han señalado otros, la solución más fácil es establecer un límite en la longitud de la entrada. Si aún desea usar scanf() , puede hacerlo de esta manera:

 char m[100]; scanf("%99s",&m); 

Tenga en cuenta que el tamaño de m[] debe ser al menos un byte mayor que el número entre % y s .

Si la cadena ingresada es más larga que 99, los caracteres restantes esperarán a ser leídos por otra llamada o por el rest de la cadena de formato pasada a scanf() .

En general, scanf() no se recomienda para manejar la entrada del usuario. Se aplica mejor a archivos de texto estructurados básicos que fueron creados por otra aplicación. Incluso entonces, debe tener en cuenta que es posible que la información no esté formateada como esperaba, ya que alguien podría haber interferido con ella para tratar de romper su progtwig.

Si puedo sugerir un enfoque más seguro:

Declara un buffer lo suficientemente grande como para contener la cadena:

char user_input[255];

Obtenga la entrada del usuario de una manera segura :

fgets(user_input, 255, stdin);

Una forma segura de obtener la entrada, el primer argumento es un puntero a un búfer donde se almacenará la entrada, el segundo la entrada máxima que la función debe leer y el tercero es un puntero a la entrada estándar, es decir, donde ingresa el usuario de.

La seguridad, en particular, proviene del segundo argumento que limita cuánto se leerá, lo que evita los desbordamientos del búfer. Además, fgets se ocupa de la terminación nula de la cadena procesada.

Más información sobre esa función aquí .

EDITAR: Si necesita formatear (por ejemplo, convertir una cadena en un número), puede usar atoi una vez que tenga la entrada.

Versión más segura y más rápida (capacidad de duplicación):

 char *readline(char *prompt) { size_t size = 80; char *str = malloc(sizeof(char) * size); int c; size_t len = 0; printf("%s", prompt); while (EOF != (c = getchar()) && c != '\r' && c != '\n') { str[len++] = c; if(len == size) str = realloc(str, sizeof(char) * (size *= 2)); } str[len++]='\0'; return realloc(str, sizeof(char) * len); } 

Tome un puntero de caracteres para almacenar la cadena requerida. Si tiene alguna idea sobre el posible tamaño de la cadena, utilice la función

 char *fgets (char *str, int size, FILE* file);` 

de lo contrario, puede asignar memoria en tiempo de ejecución también utilizando la función malloc () , que proporciona dinámicamente la memoria solicitada.

Sé que llegué después de 4 años y llegué demasiado tarde, pero creo que tengo otra forma que alguien puede usar. Yo había usado la función getchar() esta manera: –

 #include  #include  #include  //I had putten the main Function Bellow this function. //d for asking string,f is pointer to the string pointer void GetStr(char *d,char **f) { printf("%s",d); for(int i =0;1;i++) { if(i)//Ie if i!=0 *f = (char*)realloc((*f),i+1); else *f = (char*)malloc(i+1); (*f)[i]=getchar(); if((*f)[i] == '\n') { (*f)[i]= '\0'; break; } } } int main() { char *s =NULL; GetStr("Enter the String:- ",&s); printf("Your String:- %s \nAnd It's length:- %lu\n",s,(strlen(s))); free(s); } 

Aquí está la muestra de ejecución para este progtwig:

 Enter the String:- I am Using Linux Mint XFCE 18.2 , eclispe CDT and GCC7.2 compiler!! Your String:- I am Using Linux Mint XFCE 18.2 , eclispe CDT and GCC7.2 compiler!! And It's length:- 67 

Lea directamente en el espacio asignado con fgets() .

Se debe tener especial cuidado en distinguir una lectura exitosa, fin de archivo, error de entrada y falta de memoria. Se requiere una gestión de memoria adecuada en EOF.

Este método conserva una línea '\n' .

 #include  #include  #define FGETS_ALLOC_N 128 char* fgets_alloc(FILE *istream) { char* buf = NULL; size_t size = 0; size_t used = 0; do { size += FGETS_ALLOC_N; char *buf_new = realloc(buf, size); if (buf_new == NULL) { // Out-of-memory free(buf); return NULL; } buf = buf_new; if (fgets(&buf[used], (int) (size - used), istream) == NULL) { // feof or ferror if (used == 0 || ferror(istream)) { free(buf); buf = NULL; } return buf; } size_t length = strlen(&buf[used]); if (length + 1 != size - used) break; used += length; } while (buf[used - 1] != '\n'); return buf; } 

Uso de muestra

 int main(void) { FILE *istream = stdin; char *s; while ((s = fgets_alloc(istream)) != NULL) { printf("'%s'", s); free(s); fflush(stdout); } if (ferror(istream)) { puts("Input error"); } else if (feof(istream)) { puts("End of file"); } else { puts("Out of memory"); } return 0; } 

También tengo una solución con entradas y salidas estándar

 #include #include int main() { char *str,ch; int size=10,len=0; str=realloc(NULL,sizeof(char)*size); if(!str)return str; while(EOF!=scanf("%c",&ch) && ch!="\n") { str[len++]=ch; if(len==size) { str = realloc(str,sizeof(char)*(size+=10)); if(!str)return str; } } str[len++]='\0'; printf("%s\n",str); free(str); }