Hola, tengo un problema con fgets, estoy intentando separar un numero de 4 digitos, e introducir cada uno de ellos en una posicion del array :silbar:
Para eso lo guardo en un array de caracteres y asi ya me guarda en cada posicion un numero, pero tal y como esta el codigo ahora solo guarda tres (lo he mirado con el debugger), cuando en teoria deberia guardar 4 (MAX)
Debería hacer esto:
Numero: 4578
Pos_1 Pos_2 Pos_3 Pos_4
4 5 7 8
Pero hace esto:
Numero: 4578
Pos_1 Pos_2 Pos_3 Pos_4
4 5 7 -48
Es decir, la ultima posicion del array la toma como 0, y al restar 48 (es lo mismo usar la funcion atoi), se queda en -48 :o
#include <stdio.h>
#define MAX 4
#define TONUM 48
int main()
{
char Cadena[MAX];
int Numero[MAX];
printf("Introduce un numero de 4 digitos: ");
fgets(Cadena, MAX, stdin);
getchar();
// Ahora convertimos la cadena a numerico
for(int i=0;i<MAX;i++)
{
Numero[i] = Cadena[i] - TONUM;
printf("%d", Numero[i]);
}
return 0;
}
No se donde puedes estar el error, porque seguro que es muy tonto :rolleyes: :rolleyes:
Saludos
(El código es un recorte del grande, pero esa es la parte que falla, asi que quizas no va bien porque me he dejado algo ;D )
Hola MeCraniDOS mira esto:
Citarchar * fgets ( char * str, int num, FILE * stream );
Get string from stream
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
Fuente http://www.cplusplus.com/reference/cstdio/fgets/
Es decir que fgets por definición lee carácteres del stream y los almacena en str hasta un número de (num-1) carácteres, así que para arreglar tu codigo, o igualas MAX a 5 o pones MAX+1 en fgets como te he puesto en tu código:
#include <stdio.h>
#define MAX 4
#define TONUM 48
int main()
{
char Cadena[MAX];
int Numero[MAX];
printf("Introduce un numero de 4 digitos: ");
fgets(Cadena, MAX+1, stdin);
getchar();
// Ahora convertimos la cadena a numerico
for(int i=0;i<MAX;i++)
{
Numero[i] = Cadena[i] - TONUM;
printf("%d", Numero[i]);
}
return 0;
}
¡Un saludo!
Cita de: avesudra en 19 Enero 2014, 15:30 PM
Hola MeCraniDOS mira esto:Es decir que fgets por definición lee carácteres del stream y los almacena en str hasta un número de (num-1) carácteres
Eso es lo que habia hecho, poner (MAX + 1), pero no sabia el porque con 5 cogia 4, con 4 cogia 3, etc
Vale, pues muchas gracias ;-)
Saludos
Cita de: MeCraniDOS en 19 Enero 2014, 15:41 PMEso es lo que habia hecho, poner (MAX + 1), pero no sabia el porque con 5 cogia 4, con 4 cogia 3, etc
Pues esa no era la solución xD.
El código original funciona perfectamente, lo que pasa esque el último elemento es el caracter nulo. Por eso te sale -48.
Si pones en el fgets un (MAX+1), lo que pasará esque pondrá el caracter nulo FUERA de la cadena, modificar memoria que no te toca no es nada bueno nunca. Te funciona porque la cadena es la última variable que habías reservado de modo que solo estás modificando espacio vacio, si no fuera así estarías modificando el contenido de otra variable xD. Y si haces eso con memoria dinámica tu progama directamente abortará.
La solución es poner MAX = 5, también cambiara el for por:
for(int i=0;Cadena[i] != '\0';i++)
{
Numero[i] = Cadena[i] - TONUM;
printf("%d", Numero[i]);
}
De esa forma leerá hasta que encuentre el caracter nulo, lo que te permitirá meter cadenas de 1,2,3,4 caracteres. Tú código actual solo permite cadenas de 4 caracteres (si le metes 3, te saldrán un dato "extraño".
Cita de: amchacon en 19 Enero 2014, 15:52 PM
Pues esa no era la solución xD.
El código original funciona perfectamente, lo que pasa esque el último elemento es el caracter nulo. Por eso te sale -48.
En un principio habia pensado lo del caracter nulo, pero al pasarlo por el debugger tampoco me ponia el '\0', asi que lo he descartado :-[
De todas formas ya he modificado un par de cosas y funciona bien :laugh:
Gracias ;-)
Cita de: MeCraniDOS en 19 Enero 2014, 16:53 PMEn un principio habia pensado lo del caracter nulo, pero al pasarlo por el debugger tampoco me ponia el '\0', asi que lo he descartado
'\0' es solo un simbolo para ti, el compilador lo traduce como un 0:
for(int i=0;Cadena[i] != 0;i++)
Cita de: amchacon en 19 Enero 2014, 15:52 PM
La solución es poner MAX = 5, también cambiara el for por:
for(int i=0;Cadena[i] != '\0';i++)
{
Numero[i] = Cadena[i] - TONUM;
printf("%d", Numero[i]);
}
De esa forma leerá hasta que encuentre el caracter nulo, lo que te permitirá meter cadenas de 1,2,3,4 caracteres. Tú código actual solo permite cadenas de 4 caracteres (si le metes 3, te saldrán un dato "extraño".
La solución que aporta amchacon tiene un "pero", el caracter de fin de línea que introduce fgets al final de la cadena que podría tener efectos indeseables en el resto del código.
He aquí una salida con "repetición" para ver el efecto indeseado de ese caracter:
#include <stdio.h>
#define MAX 5
#define TONUM 48
int main()
{
char Cadena[MAX]={""},come_buffer[100];
int i,ch,Numero[MAX-1];
while (1)
{
printf("\nIntroduce un numero de 4 digitos: \n");
fgets(Cadena, MAX, stdin);
// Ahora convertimos la cadena a numerico
for(i=0;Cadena[i];i++)
{
Numero[i] = Cadena[i] - TONUM;
printf("%d", Numero[i]);
}//while((ch = getchar()) != '\n');
}
return 0;
}
Citar
Introduce un numero de 4 digitos:
1234
1234
Introduce un numero de 4 digitos:<==de forma automática "salta" la introducción a mano
-38
Introduce un numero de 4 digitos:
12345
1234
Introduce un numero de 4 digitos:<==de forma automática "salta" la introducción a mano y devuelve lo que quedaba en el buffer, el 5, acompañado además
5-38
Introduce un numero de 4 digitos:<==si es menor que 4 devuelve el número "acompañado"
12
12-38
Introduce un numero de 4 digitos:
5432
5432
Introduce un numero de 4 digitos:<==de forma automática "salta" la introducción a mano
-38
Introduce un numero de 4 digitos:<==si es menor que 4 devuelve el número "acompañado"
321
321-38
Introduce un numero de 4 digitos:
123456
1234
Introduce un numero de 4 digitos:<==salto automático y
56-38<==lo que queda en el buffer "acompañado"
Una forma de evitar ambas cosas, el caracter extraño y tener que limpiar el buffer, es sobredimensionar de entrada el array Cadena y ya luego nos ocupamos de darle el tamaño que queramos, 5 en este caso.
Con esta idea, ésta es la salida:Citar
Introduce un numero de 4 digitos:
123
Numero=123 Cadena=123
Introduce un numero de 4 digitos:
1234567
Numero=1234 Cadena=1234
Introduce un numero de 4 digitos:
32
Numero=32 Cadena=32
Introduce un numero de 4 digitos:
32564
Numero=3256 Cadena=3256
Introduce un numero de 4 digitos:
3214
Numero=3214 Cadena=3214
Introduce un numero de 4 digitos:
1
Numero=1 Cadena=1
#include <stdio.h>
#define MAX 10
#define N 5
#define TONUM 48
int main()
{
char Cadena[MAX]={""},come_buffer[100];
int i,ch,Numero[N];
while (1)
{
printf("\nIntroduce un numero de 4 digitos: \n");
fgets(Cadena, MAX, stdin);
if (strlen(Cadena)<MAX)
Cadena[strlen(Cadena)-1] = '\0';
Cadena[N-1] = '\0';
// Ahora convertimos la cadena a numerico
printf("Numero=");
fflush(stdout);
for(i=0;Cadena[i];i++)
{
Numero[i] = Cadena[i] - TONUM;
printf("%d", Numero[i]);
}
printf("\tCadena=%s", Cadena);
}
return 0;
}
Es sólo una idea, ¡¡¡Ehhhh!!!. Admito con gusto otras sugerencias más cualificadas que la mía. ;) ;) ;)¡¡¡¡ Saluditos! ..... !!!!
(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)
Vaya pues no había caído en eso :-X. Muy buen ojo Leo.
Tú solución no funciona adecuadamente si le metes 9 caracteres o más. El buffer de escritura es una fulana de cuidado.
La solución que se me ocurre es leerlo caracter a caracter:
#include <stdio.h>
#define MAX 5
#define TONUM 48
int main()
{
char Cadena[MAX+1]= {""};
int i,Numero;
char ch;
while (1)
{
printf("\nIntroduce un numero de 4 digitos: \n");
i = 0;
//ch = getchar();
while ((ch = getchar()) != '\n')
{
if (i < MAX)
Cadena[i++] = ch;
}
Cadena[i] = 0;
printf("Cadena = %s \t Numero = ",Cadena);
// Ahora convertimos la cadena a numerico
for(i=0; Cadena[i]; i++)
{
Numero = Cadena[i] - TONUM;
printf("%d", Numero);
}
printf("\n");
}
return 0;
}
Cita de: amchacon en 19 Enero 2014, 23:15 PM
Vaya pues no había caído en eso :-X. Muy buen ojo Leo.
Tú solución no funciona adecuadamente si le metes 9 caracteres o más. El buffer de escritura es una fulana de cuidado.
La solución que se me ocurre es leerlo caracter a caracter:
Excelente opción. ;-) ;-) ;-
Y lo de los nueve caracteres es por el tamaño que le dí a MAX, Si lo pongo mayor más "traga". Pero no es plan, claro.¡¡¡¡ Saluditos! ..... !!!!
(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)
Cita de: leosansan en 20 Enero 2014, 11:17 AMY lo de los nueve caracteres es por el tamaño que le dí a MAX, Si lo pongo mayor más "traga". Pero no es plan, claro.
No es eso, sino que se salta un caso. Y si le pongo aún más se salta más casos.
Cita de: amchacon en 20 Enero 2014, 11:44 AM
No es eso, sino que se salta un caso. Y si le pongo aún más se salta más casos.
Es lo que te comenté. Al poner MAX=10 al noveno caracter se queda "fuera" de la cadena, es decir en el buffer. No he entendido lo de que se salta un caso. :rolleyes:
Una forma simple de evitarlo es la ya indicada de sobredimensionar MAX a 100, por poner un número. Se supone que si al usuario se le piden cuatro caracteres tampoco va a ser tan bruto de ingresar tropecientos.
Claro que como siempre hay brutitos dispuestos a reventar un código a la fuerza, otra opción es comprobar si la cadena es mayor o menor de cuatro dígitos y si no pedir nueva introducción de datos, siem`re que no se "pase" de 100 y si no más tamaño a Cadena. :rolleyes: :rolleyes: :rolleyes:
Lo cierto es que ahora funciona y sólo admite cuatro dígitos, ni más ni menos. Ya me comentarán que tal.
Y una muestra:Citar
Introduce un numero de 4 digitos:
123
Introduce un numero de 4 digitos:
3215
Numero=3215 Cadena=3215
Introduce un numero de 4 digitos:
123456789456321
Introduce un numero de 4 digitos:
6541
Numero=6541 Cadena=6541
Introduce un numero de 4 digitos:
123
Introduce un numero de 4 digitos:
12
Introduce un numero de 4 digitos:
2589
Numero=2589 Cadena=2589
Introduce un numero de 4 digitos:
321654987654321654987
Introduce un numero de 4 digitos:
2561
Numero=2561 Cadena=2561
#include <stdio.h>
#include <string.h>
#define TONUM 48
#define MAX 100
#define N 5
int main()
{
char Cadena[MAX]={""};
int i,ch,Numero[N];
while (1)
{
do{
printf("\nIntroduce un numero de 4 digitos: \n");
fgets(Cadena, MAX, stdin);
}while (strlen(Cadena)!=N);
Cadena[N-1] = '\0';
// Ahora convertimos la cadena a numerico
printf("Numero=");
fflush(stdout);
for(i=0;Cadena[i];i++)
{
Numero[i] = Cadena[i] - TONUM;
printf("%d", Numero[i]);
}
printf("\tCadena=%s", Cadena);
}
return 0;
}
Por otro lado una pequeña observación:Cita de: amchacon en 19 Enero 2014, 23:15 PM
.....................................................
int main()
{
char Cadena[MAX+1]= {""};
int i,Numero;
char ch;
while (1)
{
printf("\nIntroduce un numero de 4 digitos: \n");
i = 0;
//ch = getchar();
while ((ch = getchar()) != '\n')
......................................................
la función getchar (http://www.cplusplus.com/reference/cstdio/getchar/?kw=getchar)es de tipo int y por ello ch ha de ser int, no char. ;) ;) ;)
¡¡¡¡ Saluditos! ..... !!!!
(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)
P.D: Se me olvidaba, el código como lo tienes, además de admitir menos de cuatro caracteres, admite hasta cinco.
Creo que es aquí donde está el error:Cita de: amchacon en 19 Enero 2014, 23:15 PM
while (1)
{
printf("\nIntroduce un numero de 4 digitos: \n");
i = 0;
//ch = getchar();
while ((ch = getchar()) != '\n')
{
if (i < MAX) <== aquí va MAX-1
Cadena[i++] = ch;
}
Tomo nota del getchar(), no sé porqué siempre pienso que devuelve un char (ese nombre puñetero :¬¬).
Lo del MAX está perfecto, fijate que:
char Cadena[MAX+1]= {""};
La razón de ese cambio es que me parece más intuitivo y menos propenso a errores usar como unidad de longitud MAX que MAX - 1.
Tal como tienes en el post esta es la salida:Citar
Introduce un numero de 4 digitos:
12345
Cadena = 12345 Numero = 12345<==AQUI admite 5 caracteres
Introduce un numero de 4 digitos:
1234
Cadena = 1234 Numero = 1234
Con la corrección que te indico del -1 esta es la salida:Citar
Introduce un numero de 4 digitos:
12345
Cadena = 1234 Numero = 1234<==AQUI está O.K
Introduce un numero de 4 digitos:
1234
Cadena = 1234 Numero = 1234
Introduce un numero de 4 digitos:
123
Cadena = 123 Numero = 123
¡¡¡¡ Saluditos! ..... !!!!
(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)
P.D: Pero conste que la gracia era solucionar lo del fgets, nada de scanf ni getchar.
Ah leñe, lo que tengo que hacer ahí es cambiar este printf:
printf("\nIntroduce un numero de 4 digitos: \n");
Por este más genérico:
printf("\nIntroduce un numero de %d digitos: \n",MAX);
Ala, problema resuelto ;D
Cita de: amchacon en 20 Enero 2014, 17:20 PM
Ah leñe, lo que tengo que hacer ahí es cambiar este printf:
printf("\nIntroduce un numero de 4 digitos: \n");
Por este más genérico:
printf("\nIntroduce un numero de %d digitos: \n",MAX);
Ala, problema resuelto ;D
¿Queeeeeeeeeeeeeeeeeeé?. ¿Qué es eso de problema resuelto?. Se trata de ingresar cuatro dígitos, no cinco pequeño saltamontes. :laugh:
Es coña, la hora será.
Eh aquí tu solución adaptada a cuatro dígitos y sólo cuatro:Citar
Introduce un numero de 4 digitos:
123
Numero menor cifras.
Introduce un numero de 4 digitos:
3265
Cadena = 3265 Numero = 3265
Introduce un numero de 4 digitos:
12
Numero menor cifras.
Introduce un numero de 4 digitos:
123456
Numero mayor cifras.
Introduce un numero de 4 digitos:
2541
Cadena = 2541 Numero = 2541
Introduce un numero de 4 digitos:
1
Numero menor cifras.
[/size]
#include <stdio.h>
#define MAX 5
#define TONUM 48
int main()
{
char Cadena[MAX+1]= {""};
int i,Numero;
int ch;
while (1){
printf("\nIntroduce un numero de 4 digitos: \n");
i = 0;
while ((ch = getchar()) != '\n') {
if (i<=MAX-1)
Cadena[i++] = ch;
}
if (i==MAX-1){
Cadena[i] = 0;
printf("Cadena = %s \t Numero = ",Cadena);
// Ahora convertimos la cadena a numerico
for(i=0; Cadena[i]; i++) {
Numero = Cadena[i] - TONUM;
printf("%d", Numero);
}
printf("\n");
}
else if (i>MAX-1)
puts ("Numero mayor cifras. ");
else
puts ("Numero menor cifras. ");
}
return 0;
}
¡¡¡¡ Saluditos! ..... !!!!
(http://st.forocoches.com/foro/images/smilies/simba2.gif)
REEDITADO Y MEJORADO.
Yo lo he interpetrado como n caraceteres :-X
Por cierto:
while ((ch = getchar()) != '\n') {
Cadena[i++] = ch;
//printf("\ni=%d\n",i);
}
¡Peligro de desbordamiento! Si le meto más caracteres de la cuenta (5) estaré desbordando el array.
Cita de: amchacon en 20 Enero 2014, 21:56 PM
Yo lo he interpetrado como n caraceteres :-X
Por cierto:
while ((ch = getchar()) != '\n') {
Cadena[i++] = ch;
//printf("\ni=%d\n",i);
}
¡Peligro de desbordamiento! Si le meto más caracteres de la cuenta (5) estaré desbordando el array.
Se me paso un if en el código anterior que ya he arreglado:
.............................
while ((ch = getchar()) != '\n') {
if (i<=MAX-1)
Cadena[i++] = ch;
.....................................
¡¡¡¡ Saluditos! ..... !!!!
(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)
P.D: Sigo pensando que esto se aparta del objetivo del fgets, que me ratifico en lo que propuse, salvo nueva aportación, cosa que espero.
Hola, bueno no me leí todo el hilo pero diría que se trata de problemas con el salto de línea y fgets(). Dejo aquí mi pequeño granito de arena:
#include <stdio.h>
#include <string.h>
#define MAX 5
int main()
{
char buffer[MAX]={'\0'};
int ch;
char *p=NULL;
fgets(buffer, MAX, stdin);
if (p=strchr(buffer, '\n')) // si se encuentra el '\n' se cambia por null
*p='\0';
else // si no se encuentra es que hay que vaciar el buffer de entrada
while ((ch=getchar())!='\n' && ch!=EOF);
printf("Introdujiste: %s\n", buffer);
return 0;
}
Si no tiene nada que ver con el hilo pido disculpas, pero es que con tanto post la verdad que da un poco de pereza encontrar el problema.
Saludos.
Cita de: xiruko en 21 Enero 2014, 00:15 AM
Hola, bueno no me leí todo el hilo pero diría que se trata de problemas con el salto de línea y fgets(). Dejo aquí mi pequeño granito de arena:
........................................
Si no tiene nada que ver con el hilo pido disculpas, pero es que con tanto post la verdad que da un poco de pereza encontrar el problema.
Buena aportación xiruko, da una nueva perspectiva.
Ahora sólo falta que diga que se rechaza por menor o mayor número de cifras. ;)¡¡¡¡ Saluditos! ..... !!!!
(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)
Cita de: leosansan en 21 Enero 2014, 02:53 AM
Ahora sólo falta que diga que se rechaza por menor o mayor número de cifras. ;)
Aquí lo dejo ;D
#include <stdio.h>
#include <string.h>
#define MAX 5
int main()
{
char buffer[MAX]={'\0'};
int ch;
char *p=NULL;
int basura=0;
printf("Introduce %d caracteres: ", MAX-1);
fgets(buffer, MAX, stdin);
if (p=strchr(buffer, '\n'))
printf("ERROR: Faltan %ld caracteres.\n", MAX-1-(p-buffer));
else
{
basura=1;
while ((ch=getchar())!='\n' && ch!=EOF) basura++;
if (basura > 1)
printf("ERROR: Sobran %d caracteres.\n", basura-1);
else
printf("BIEN! Introdujiste solo %d caracteres.\n", MAX-1);
}
return 0;
}
Saludos.