1

El problema es simple, necesito insertar dos variables: nombre y altura. Sin embargo, cuando ingreso el nombre el programa se saltea el segundo scanf (el de altura).

char nombre[30];
int i;
float h;

printf("Enter names and surnames: ");
scanf("%c", &nombre);
printf("\nEnter height in meters: ");
scanf(" %f", &h);

gets(nombre);
printf("\nYour height is %f, and your initials are %c", h, nombre[0]);
for (i = 0; i < sizeof(nombre); i++)
{
    if(nombre[i] == ' ')
    {
        printf(", %c", nombre[i+1]);
    }
}

return 0;

El problema no ocurre cuando utilizo "%s" en vez de "%c", pero intento leer caracteres individualmente así que no sé si es una opción.

Dynaheart
  • 13
  • 3
  • 1
    Hola. Bienvenido a stackoverflow en español. Por favor, traduce tu pregunta a españo de lo contrario podrá terminar cerradal. Hi, welcome to stackoverflow in spanish, please, translate your question to spanish otherwise it could be closed. – Adrián Mar 17 '21 at 15:29
  • disculpe, pensé que estaba en la página en inglés, sinceramente no estaba enterado de que había una alternativa en español – Dynaheart Mar 17 '21 at 15:40
  • 1
    No te preocupes. Cuando indicas que el problema no sucede cuando lees con `scanf` la entrada reemplazando `%s` es porque `%s` denota un string que es lo que necesitas. En cambio con `%c` esperas un caracter y solamente uno, por lo que no lee toda la entrada que realmente necesitas. – Adrián Mar 17 '21 at 16:09
  • fijate la explicación en https://es.stackoverflow.com/a/214828/81450 – alo Malbarez Mar 17 '21 at 16:19

1 Answers1

1

Analicemos paso a paso el programa.

Cuando se ejecute esta línea:

printf("Enter names and surnames: ");
scanf("%c", &nombre);

El usuario solo puede ingresar un caracter. Por ejemplo, la letra A y este caracter se guardaría en la primera posición del array nombre (es decir, en nombre[0]).

Esto quiere decir, que si solo ingresas un caracter, el búfer del teclado quedaría con un salto de línea, esto no afectará al próximo scanf, ya que ignorará el salto de línea.

Si el usuario ingresara como altura: 12.3. El búfer sigue quedando con el \n.

printf("\nEnter height in meters: ");
scanf(" %f", &h);

Esto ocasiona que la función gets nunca se detenga para la espera de una cadena y esto se debe a que esta rutina deja de leer hasta encontrar un salto de línea.

gets(nombre);

Después se imprime los datos que ingresó el usuario:

printf("\nYour height is %f, and your initials are %c", h, nombre[0]);

Dándome como resultado:

Your height is 12.3, and your initials are

Por supuesto, no se está imprimiendo el contenido de la primera posición del array nombre y esto se debe que la función gets como no pudo leer nada, asignó el caracter nulo en nombre[0] y dicho caracter no se lo puede imprimir con %c (sino con %d).

Hasta ahí, podríamos comprender como podría funcionar tu código ingresando esos datos.

Veamos otro caso. Si en la primera llamada de scanf ingreso un Ramirez, solo tomará el primer caracter de la cadena (la letra R), el resto se quedará en el búfer: amirez.

scanf("%c", &nombre);

El próximo scanf pide un flotante y solo ignora saltos de líneas pero como en el búfer quedó con mas caracteres, esto provoca que la lectura falle y esa es la razón del porque se salta la opción.

El problema no ocurre cuando utilizo "%s" en vez de "%c", pero intento leer caracteres individualmente así que no sé si es una opción.

Si haces algo como esto:

printf("Enter names and surnames: ");
scanf("%s", &nombre);

La función scanf leerá los caracteres del búfer hasta encontrar un espacio o salto de línea. Esto es peligroso, aquí puedes desbordar el array nombre y esto provoca que scanf escriba en alguna dirección de memoria que no le corresponda al programa. En este hilo puedes encontrar mas información sobre eso: ¿Cómo evitar un desbordamiento de búfer cuando se pide una cadena con scanf? . De igual manera, en tu caso deberías de utilizar una función que si te permita leer cadenas con espacios.

Pero no, no debes usar la función gets. Es peligroso, también puedes desbordar el búfer. Para mas información, leer este hilo: Es recomendable usar la función gets?.

La función que conozco para leer cadenas con espacios y que sea seguro, es la función fgets.

Su uso es sencillo:

printf("Enter names and surnames: ");
fgets(nombre, sizeof nombre, stdin);
printf("\nEnter height in meters: ");
scanf("%f", &h);

De esta manera haces una lectura de forma segura. Un detalle importante es que la función fgets agregaría el salto de línea en el array. Eso se lo podría eliminar de esta forma:

nombre[strlen(nombre) - 1] = '\0';

Y eso es todo..

El último código no tengo ni idea del porque lo usaste. Si quieres imprimir la cadena, simplemente usa:

printf("name and surname: %s", nombre);
MrDave1999
  • 7,491
  • 1
  • 7
  • 22
  • Muchísimas gracias, ahora el código funciona perfectamente :D (aunque creo que debo aclarar que el último fragmento es para sacar las iniciales de los nombres, así que no puedo reemplazarlo) – Dynaheart Mar 17 '21 at 18:37