Ha encontrado el problema exacto con scanf() y% s: ¿qué sucede cuando no sabe cuánta información hay?
Si intenta ejecutar char mystring[0];
, su programa compilará muy bien. Pero siempre segfault. Está creando una matriz de tamaño 0, por lo que cuando intente colocar algo en esa matriz, saldrá inmediatamente de los límites de su cadena (ya que no se habrá asignado memoria), que es una segfault.
Por lo tanto, punto 1: siempre debe asignar un tamaño para su cadena. Puedo pensar en muy pocas circunstancias (de acuerdo, ninguna) en las que desee decir char mystring[0]
en lugar de char *mystring
.
A continuación, cuando utilice scanf, nunca querrá usar el especificador "% s", ya que esto no hará ninguna comprobación de límites en el tamaño de la cadena. por lo que incluso si usted tiene:
char mystring[512];
scanf("%s", mystring);
si el usuario introduce más de 511 caracteres (ya que el 512º es \ 0), has de salir de los límites de la matriz.La manera de remediar esto es:
scanf("%511s", mystring);
Todo esto es para decir que C no tiene una facilidad para cambiar automáticamente el tamaño de una cadena si hay más de entrada que usted está esperando. Este es el tipo de cosas que tienes que hacer manualmente.
Una forma de resolver esto es usando fgets().
Se podría decir:
while (fgets(mystring, 512, stdin))
{
/* process input */
}
A continuación, puede utilizar sscanf() para analizar mystring
Pruebe el código anterior, con una cadena de longitud 5. Después de 4 caracteres han sido leídos, ese código vuelve a repetir para recuperar el resto de la entrada. El "procesamiento" podría incluir código para reasignar una cadena para que tenga un tamaño mayor y luego agregar la última entrada de fgets().
El código anterior no es perfecto: haría que el programa repunte y procese cualquier longitud infinita de cadena, por lo que es posible que desee tener algún límite interno duro (p. Ej., Realice un bucle de hasta 10 veces).
t debe agregarse que% s lee palabras, no cadenas enteras. Porque la cadena de formato de scanf usa espacios y saltos como delimitadores.En este caso, use% c en su lugar (con un ancho de campo) o fgets como mencionó. En el caso de% c con un ancho de campo, recuerde inicializar toda la cadena de almacenamiento intermedio a cero. –
El programa no siempre segfault. De hecho, probablemente no la mayoría de las veces. Su programa probablemente se rompa silenciosamente. ¿No es C adorable? :-) –