manejo - Programación en C: imprime solo int de fgets
leer cadenas en c scanf (7)
Es una buena idea pensar siempre en el manejo de errores. ¿Qué ocurre si el usuario pulsa espacio y pestañas incorrectamente? Por lo tanto, primero quite los espacios y pestañas si existen:
char *c = string;
while ((*c == '' '') || (*c == ''/t''))
++c;
y luego usa atoi()
.
Ver este main
:
int main(void)
{
int i;
int ch;
char str[512];
fgets(str, sizeof str, stdin);
for (i = 0; i <= (strlen(str)); i++)
{
if (str[i] != ''/0'' && str[i] != ''/n'')
{
int num = atoi(&str[i]);
printf("%d/n", num);
}
}
return 0;
}
Quiero obtener una línea con los números del usuario y obtener todos los números sin spaces
ni tabs
.
Por ejemplo:
La entrada 1 2 3
. Pero en este caso esta es la salida:
1
2
2
3
3
Entonces, ¿por qué recibí 2
y 3
dos veces?
La solución con strtok
tampoco es tan difícil:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
char s[128];
fgets(s, sizeof s, stdin);
const char *delim = " /t/n";
char *p = strtok(s, delim);
while(p) {
int val = strtol(p, NULL, 10);
printf("%d/n", val);
p = strtok(NULL, delim);
}
return 0;
}
Sin embargo, tenga en cuenta que es un poco dudoso ya que utiliza un estado oculto (no es bueno para programas multiproceso) y, por supuesto, modifica la cadena de entrada, por lo que no puede ser una constante (pero ¿por qué haría eso?).
Porque también pasas la posición de la cuerda que comienza con espacios. consiguen que el primer número sea 2
y 3
respectivamente, dos veces. Eso es lo que se devuelve.
for (i = 0; i <= (strlen(str)); i++)
{
if (str[i] != ''/0'' && !isspace(str[i]) )
{
int num = atoi(&str[i]);
printf("%d/n", num);
}
}
Huellas dactilares:
1
2
3
Para el uso de tokensing puedes usar strtok
y convertirlo a strtol
numérico, etc. Estos proporcionan un mejor control sobre los casos de error que atol/atoi
do.
Puede usar la función isdigit
o isalpha()
(según su uso) disponible en ctype.h
. lo siguiente es fragmento de código usando la función isdigit
:
for (i = 0; i <= (strlen(str)); i++)
{
if (isdigit(str[i]))
{
int num = atoi(&str[i]);
if(i && str[i-1]==''-'') num *= -1;
printf("%d/n", num);
i += ( num==0 ) ? 1 : (int)log10(abs(num))+1;
}
}
Véalo trabajar aquí .
Compruebe aquí, por ejemplo, en las isdigit
e isalpha()
.
En cuanto a su pregunta que:
Entonces, ¿por qué recibí 2 y 3 dos veces?
Consulte la siguiente explicación disponible en cplusplus.com que explica la función atoi()
.
La función descarta primero tantos caracteres en blanco (como en isspace) como sea necesario hasta que se encuentre el primer carácter que no sea de espacio en blanco. Luego, a partir de este carácter, toma un signo más o menos inicial opcional seguido de tantos dígitos de base 10 como sea posible, y los interpreta como un valor numérico.
Así es como lo haría:
char line[256];
if (fgets(line, sizeof line, stdin) != NULL)
{
const char *ptr = line;
while (*ptr != ''/0'')
{
char *eptr = NULL;
const long value = strtol(ptr, &eptr, 10);
if (eptr != ptr)
printf("%ld/n", value);
else
break;
ptr = eptr;
}
}
Esto usa strtol()
para que también maneje números negativos; si esto es incorrecto, por supuesto puedes agregar cheques para filtrarlos. Creo que esto es mucho mejor que cualquier cosa usando strtok()
.
Cuando alcance el carácter de espacio en la entrada, llamará atoi()
con " 2 3"
(que da como resultado 2) y más tarde con " 3"
(lo que da como resultado 3), lo que crea los números inesperados.
De la referencia de atoi()
:
La función descarta primero tantos caracteres en blanco (como en isspace) como sea necesario hasta que se encuentre el primer carácter que no sea de espacio en blanco. [...]
Eso significa que si usted da como entrada a esa función "2", devolverá 2.
Cambia esto:
if (str[i] != ''/0'' && str[i] != ''/n'')
a esto:
if (str[i] != '' '' && str[i] != ''/0'' && str[i] != ''/n'')
y obtendrás:
1
2
3
Aquí hay un consejo sobre la depuración de este código: en su salida, obtuvo 2 y 3 dos veces, pero no 1.
En otras palabras, obtienes el número que estaba después de un espacio dos veces. 1 no tenía un espacio antes.
Esto debería hacerte pensar que hay algo escalofriante en los espacios que hay allí.
De hecho, ingresaría el cuerpo de la declaración if, ¡incluso si str[i]
fuera un espacio!
Al agregar una condición para verificar si el carácter actual no es un espacio, para ingresar el boby de la instrucción if, en realidad omite los espacios.