| Ver tema anterior :: Ver siguiente tema | | Autor | Mensaje |
|---|
K1LL3RDO6
Registrado: 03 Abr 2005 Mensajes: 3
| Publicado: 03/11/2007 8:13 pm | | | Título: fgets y estructura |
| Hola, soy nuevo en esto de la programación y tengo una duda.
Estoy tratando de usar la función fgets para recibir un string, mi problema es que al ejecutar el programa, se salta la lectura del string.
Esto solo me pasa si pongo las variables dentro de una estructura, pues si no lo hago no hay problemas.
Tengo que hacerlo asi por que nos estan enseñando eso ahora.
Esto lo estoy compilando en linux.
| Código: |
#include <stdio.h> #include <stdlib.h> #include <string.h> //#include <conio.h>
void menu(); void ingresar(); void imprimir(); void mayor18(); void buscar_nombre();
struct registro {
char nombre[20], apellido[20]; int edad; char domicilio[25];
};
struct registro reg; FILE *a; char ok;
int main() {
// clrscr(); // ingresar(); // imprimir(); // mayor18(); // buscar_nombre(); menu(); return 0; }
void menu() {
short opcion;
do {
system("clear"); printf("MENU\n\n"); printf("1. Ingresar datos\n"); printf("2. Imprimir registros\n"); printf("3. Mayores de 18\n"); printf("4. Buscar por nombre\n"); printf("0. Salir\n"); printf("Ingresa opcion: "); scanf("%d", &opcion);
switch (opcion) {
case 0: break;
case 1: ingresar(); break;
case 2: imprimir(); break;
case 3: mayor18(); break;
case 4: buscar_nombre(); break;
default: printf("Opcion no valida\n"); break;
}
} while ( opcion != 0); }
void ingresar() {
a = fopen("datos.dat", "w");
if (a == NULL) {
printf("No se puede crear\n"); // getch(); } else {
do {
// clrscr(); printf("\nIngreso datos\n"); printf("Nombre: "); scanf("%s", ®.nombre); printf("Apellido: "); scanf("%s", ®.apellido); printf("Edad: "); scanf("%d", ®.edad); printf("Domicilio: "); fgets(reg.domicilio, 25, a); //scanf("%s", ®.domicilio); //getline(reg.domicilio, 25); /* toma los espacios tb*/ fwrite(®, sizeof(reg), 1, a); printf("Registro grabado.. Ingresa otro s/n: "); scanf("%s", &ok);
} while (ok=='s'); } fclose(a); }
void imprimir() {
a = fopen("datos.dat", "r");
if (a == NULL) {
printf("\nError al abrir el archivo"); // getch(); } else {
do {
fread(®, sizeof(reg), 1, a); if (feof(a)) { printf("fin de lectura...\n\n"); // getch(); } else {
printf("\n\nNombre: %s\n", reg.nombre); printf("Apellido: %s\n", reg.apellido); printf("Edad: %d\n", reg.edad); printf("Domicilio: %s\n", reg.domicilio); } } while (!feof(a)); }
fclose(a); system("sleep 10"); /* realiza un sleep de 10 seg */
}
void mayor18() {
short cont = 0;
/* Abre el archivo */ // a = fopen("datos.dat", "r");
// if (a == NULL) {
if ( (a = fopen("datos.dat", "r") ) == NULL ) {
printf("Error a abrir archivo\n"); // getch(); } else {
do {
fread(®, sizeof(reg), 1, a);
if ( feof(a)) {
printf("fin de lectura\n"); } else {
if (reg.edad > 18) {
if (cont == 0)
printf("PERSONAS MAYORES de 18\n\n");
printf("Nombre: %s\n", reg.nombre); printf("Apellido: %s\n", reg.apellido); printf("Edad: %d\n", reg.edad); printf("Domicilio: %s\n\n", reg.domicilio); cont = 1; } } } while (!feof(a)); }
fclose(a); // getch(); }
void buscar_nombre() {
char nombre[20]; short aux = 0;
printf("BUSQUEDA PERSONA POR NOMBRE\n\n"); printf("Nombre: "); scanf("%s", &nombre);
if ( (a = fopen("datos.dat", "r") ) == NULL ) {
printf("Error a abrir archivo\n"); } else {
do {
fread(®, sizeof(reg), 1, a);
if ( feof(a))
printf("fin de lectura\n");
else { if ( strcmp(nombre, reg.nombre) == 0) {
if ( aux == 0)
printf("Se encontro a:\n\n");
printf("Nombre: %s %s\n", reg.nombre, reg.apellido); printf("Edad: %d\n", reg.edad); printf("Domicilio: %s\n", reg.domicilio); aux = 1; } }
} while (!feof(a)); }
fclose(a); }
|
Al ejecutarse se ve asi
| Código: | MENU
1. Ingresar datos 2. Imprimir registros 3. Mayores de 18 4. Buscar por nombre 0. Salir Ingresa opcion: 1
Ingreso datos Nombre: juan Apellido: perez Edad: 30 Domicilio: Registro grabado.. Ingresa otro s/n:
|
Como se puede ver, después de "Domicilio" me dice inmediatamente que el registro está grabado, y no me permite ingresar el domicilio de la persona.
Agradeceria si alguien me puede ayudar, darme alguna pista de por qué está mal por favor. |
| | Volver arriba | |  | rir3760

Registrado: 01 Oct 2004 Mensajes: 3676 Ubicación: Mexico
| Publicado: 04/11/2007 6:26 am | | | Título: |
| El error es uno muy comun causado por el uso intercalado de la funcion scanf con otras funciones como gets/fgets/etc.
En esta parte de tu programa:
| Código: | printf("Edad: "); scanf("%d", ®.edad);
printf("Domicilio: "); fgets(reg.domicilio, 25, a); |
La funcion scanf lee el numero de la entrada estandar pero no procesa el espacio blanco despues de este (incluyendo el avance de linea o '\n').
Supongamos que al presentarse la peticion de la edad se teclea "123" seguido de {ENTER}, en este caso el bufer de la entrada estandar contiene: 1, 2, 3, {ENTER} Los tres primeros caracteres son procesados por scanf para formar el numero 123 pero (este es el gran problema) el avance de linea se queda en el bufer.
La siguiente funcion (fgets) trata de leer una linea y se encuentra con el remanente de scanf: {ENTER} Ese avance de linea fgets lo toma como una linea en blanco y es la causa de que el programa no te permita introducir el domicilio.
Para evitar todo esto basta con eliminar los caracteres restantes de la linea despues de la llamada a scanf:
| Código: | printf("Edad: "); scanf("%d", ®.edad); /* eliminar resto de la linea*/ { int ch;
while ((ch = getchar()) != EOF && ch != '\n') ; }
printf("Domicilio: "); fgets(reg.domicilio, 25, a); |
Un saludo _________________ The capacity to learn is a gift; The ability to learn is a skill; The willingness to learn is a choice. -- Rebec of Ginaz |
| | Volver arriba | |  | K1LL3RDO6
Registrado: 03 Abr 2005 Mensajes: 3
| Publicado: 04/11/2007 5:13 pm | | | Título: |
| | rir3760 escribió: | El error es uno muy comun causado por el uso intercalado de la funcion scanf con otras funciones como gets/fgets/etc.
En esta parte de tu programa:
| Código: | printf("Edad: "); scanf("%d", ®.edad);
printf("Domicilio: "); fgets(reg.domicilio, 25, a); |
La funcion scanf lee el numero de la entrada estandar pero no procesa el espacio blanco despues de este (incluyendo el avance de linea o '\n').
Supongamos que al presentarse la peticion de la edad se teclea "123" seguido de {ENTER}, en este caso el bufer de la entrada estandar contiene: 1, 2, 3, {ENTER} Los tres primeros caracteres son procesados por scanf para formar el numero 123 pero (este es el gran problema) el avance de linea se queda en el bufer.
La siguiente funcion (fgets) trata de leer una linea y se encuentra con el remanente de scanf: {ENTER} Ese avance de linea fgets lo toma como una linea en blanco y es la causa de que el programa no te permita introducir el domicilio.
Para evitar todo esto basta con eliminar los caracteres restantes de la linea despues de la llamada a scanf:
| Código: | printf("Edad: "); scanf("%d", ®.edad); /* eliminar resto de la linea*/ { int ch;
while ((ch = getchar()) != EOF && ch != '\n') ; }
printf("Domicilio: "); fgets(reg.domicilio, 25, a); |
Un saludo |
Hola, escribi lo que pusiste, pero tampoco me permite poder ingresar la dirección, compilo, ejecuto y se salta tambien poder ingresar el domicilio.
saludos |
| | Volver arriba | |  | | daltomi
Registrado: 28 Abr 2007 Mensajes: 117 Ubicación: Argentina
| Publicado: 04/11/2007 6:40 pm | | | Título: |
| Hola. En la función ingresar existe un error: Creas un archivo de sólo escritura y luego utilizas la función fgets para leer el archivo, es decir, debes reemplazar fgets por scanf,o mejor dicho, comenta fgets y quita el formato de comentario al scanf que ya existe.
Saludos. |
| | Volver arriba | |  | Diabliyo
Registrado: 14 Abr 2004 Mensajes: 316 Ubicación: En la Luna
| Publicado: 04/11/2007 7:38 pm | | | Título: |
| Limpia el buffer...
| Código: | //para windows. fflush(stdin);
//para linux while( getch()!='\n' ); |
_________________
|
| | Volver arriba | |  | mamntc02
Registrado: 30 Abr 2007 Mensajes: 248
| Publicado: 05/11/2007 4:38 am | | | Título: |
| Hola,
Volvemos a un error recurrente. no tiene por qué funcionar (ni en Linux, ni en Windows ni en ninguna plataforma). No hay ninguna función en el standard q vacie los buffer de entrada, fflush sólo funciona (o sólo es obligatorio q funcione) para buffers de salida. Puede q el compilador igualmente implemente la función para los buffers de entrada, pero nadie le obliga y lo más probable es q no te funcione. La solución es la q comenta rir3760
Saludos. |
| | Volver arriba | |  | | K1LL3RDO6
Registrado: 03 Abr 2005 Mensajes: 3
| Publicado: 05/11/2007 9:11 am | | | Título: |
| Hice lo que me dijeron, estoy probando en windows y no me resulta, aca le saque un screenshot al turbo c, ejecutando el programita.
No me funciona en windows o linux, no se si falto algo =\
| Código: | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h>
void menu(); void ingresar(); void imprimir(); void mayor18(); void buscar_nombre();
struct registro {
char nombre[20], apellido[20]; int edad; char domicilio[25];
};
struct registro reg; FILE *a; char ok;
int main() {
menu(); return 0; }
void menu() {
short opcion;
do {
clrscr(); printf("MENU\n\n"); printf("1. Ingresar datos\n"); printf("2. Imprimir registros\n"); printf("3. Mayores de 18\n"); printf("4. Buscar por nombre\n"); printf("0. Salir\n\n"); printf("Ingresa opcion: "); scanf("%d", &opcion);
switch (opcion) {
case 0: break;
case 1: ingresar(); break;
case 2: imprimir(); break;
case 3: mayor18(); break;
case 4: buscar_nombre(); break;
default: printf("Opcion no valida\n"); break;
}
} while ( opcion != 0); }
void ingresar() {
a = fopen("datos.dat", "w");
if (a == NULL) {
printf("No se puede crear\n"); } else {
do {
printf("\nIngreso datos\n"); printf("Nombre: "); scanf("%s", ®.nombre); printf("Apellido: "); scanf("%s", ®.apellido); printf("Edad: "); scanf("%d", ®.edad); /* eliminar resto de la linea */ {
int ch;
while ((ch = getchar()) != EOF && ch != '\n') ;
} printf("Domicilio: "); fgets(reg.domicilio, 25, a); //scanf("%s", ®.domicilio); //cin.getline(reg.domicilio, 25); /* toma los espacios tb*/ fwrite(®, sizeof(reg), 1, a); printf("Registro grabado.. Ingresa otro s/n: "); scanf("%s", &ok);
} while (ok=='s'); } fclose(a); getch(); }
void imprimir() {
a = fopen("datos.dat", "r");
if (a == NULL) {
printf("\nError al abrir el archivo");
} else {
do {
fread(®, sizeof(reg), 1, a); if (feof(a)) { printf("fin de lectura...\n\n");
} else {
printf("\n\nNombre: %s\n", reg.nombre); printf("Apellido: %s\n", reg.apellido); printf("Edad: %d\n", reg.edad); printf("Domicilio: %s\n", reg.domicilio);
} } while (!feof(a)); }
fclose(a); // system("sleep 10"); /* realiza un sleep de 10 seg */ getch();
}
void mayor18() {
short cont = 0;
if ( (a = fopen("datos.dat", "r") ) == NULL ) {
printf("Error a abrir archivo\n");
} else {
do {
fread(®, sizeof(reg), 1, a);
if ( feof(a)) {
printf("fin de lectura\n"); } else {
if (reg.edad > 18) {
if (cont == 0)
printf("PERSONAS MAYORES de 18\n\n");
printf("Nombre: %s\n", reg.nombre); printf("Apellido: %s\n", reg.apellido); printf("Edad: %d\n", reg.edad); printf("Domicilio: %s\n\n", reg.domicilio); cont = 1; } } } while (!feof(a)); }
fclose(a); getch(); }
void buscar_nombre() {
char nombre[20]; short aux = 0;
printf("BUSQUEDA PERSONA POR NOMBRE\n\n"); printf("Nombre: "); scanf("%s", &nombre);
if ( (a = fopen("datos.dat", "r") ) == NULL ) {
printf("Error a abrir archivo\n"); } else {
do {
fread(®, sizeof(reg), 1, a);
if ( feof(a))
printf("fin de lectura\n");
else { if ( strcmp(nombre, reg.nombre) == 0) {
if ( aux == 0)
printf("Se encontro a:\n\n");
printf("Nombre: %s %s\n", reg.nombre, reg.apellido); printf("Edad: %d\n", reg.edad); printf("Domicilio: %s\n", reg.domicilio); aux = 1; } }
} while (!feof(a)); }
fclose(a); getch(); }
|
La idea es que me pueda tomar un domicilio el cual puede llevar un espacio en blanco (Ejemplo "juan claro"), pues hay calles que llevan espacios en blanco. Poniendo cin.getline para almacenar el domicilio con espacio blanco, con su #include <iostream> respectivo, funciona lo que quiero realizar, pero entiendo que esa función es de c++ y me gustaría que sólo fuera con c.
muchas gracias por las respuestas. |
| | Volver arriba | |  | | |
| No puede crear mensajes No puede responder temas No puede editar sus mensajes No puede borrar sus mensajes No puede votar en encuestas
|
|
| |