Autor
|
Tema: Problemas con mostrar un registro (Leído 3,441 veces)
|
Sword9K
Desconectado
Mensajes: 10
|
Hola, es sobre un problema que estoy teniendo a la hora de mostrar unos datos con punteros, lo que pasa es que uno de los datos que ingreso se "cambia" por un carácter especial o algo así. Aquí esta parte del código, perdón si esta asi, lo copie rápido. #include <string.h> #include <iostream> #include <windows.h> #include <conio.h> using namespace std; void gt(int x, int y){ // -Posicion X y Y en el Programa HANDLE Manipulador; //Puntero COORD Coordenadas; //Coordenadas Manipulador = GetStdHandle(STD_OUTPUT_HANDLE); //Contenedor del Programa Coordenadas.X = x; //Posicion en X Coordenadas.Y = y; //Posicion en Y SetConsoleCursorPosition(Manipulador,Coordenadas); //Envia el Contenedor y variable para la posicion } void formu(){ system("cls"); gt(15,9); cout<<"Codigo: "; gt(15,11); cout<<"Nombres: "; gt(15,12); cout<<"Apellidos: "; gt(15,14); cout<<"Nota 1: "; gt(15,15); cout<<"Nota 2: "; gt(15,17); cout<<"Su Nota Definitiva es: "; } struct notas{ char nom[50]; char apel[50]; char cod[50]; float n1, n2; float defi; }alu, *pun=&alu; void capt(); void list(); void consul(); int ne; int main(){ char op; do{ system("cls"); gt(20,10); cout<<"MENU REGISTROS"; gt(22,12); cout<<"1. Capturar."; gt(22,13); cout<<"2. Consultar registros."; gt(22,14); cout<<"3. Salir."; gt(23,16); cout<<char(167)<<"Digite un numero: "; op = getch(); switch(op){ case '1': capt(); break; case '2': consul(); break; case '3': gt(6,18); cout<<"Saliendo..."; Sleep(200); gt(5,25); exit(1); break; default: gt(6,18); cout<<"Debe digitar un numero del 1 al 3..."; system("pause"); break; } } while(op != '3'); } void capt(){ system("cls"); gt(15,10); cout<<"Digite el Numero de Formularios a agregar: "; cin>>ne; const int ju = ne; for(int i=0;i<ju;i++){ formu(); fflush(stdin); gt(23,9); gets((pun+i)->cod); gt(24,11); gets((pun+i)->nom); gt(26,12); gets((pun+i)->apel); gt(23,14); cin>>(pun+i)->n1; gt(23,15); cin>>(pun+i)->n2; (pun+i)->defi=((pun+i)->n1+(pun+i)->n2)/2; gt(38,17); cout<<(pun+i)->defi; system("pause"); } ne = ju; } void consul(){ char op; do{ system("cls"); gt(20,10); cout<<"MENU - Consultas"; gt(22,12); cout<<"1. Listar."; gt(22,13); cout<<"2. Volver al menu anterior"; gt(22,14); cout<<"3. Salir"; gt(23,16); cout<<"Digite un numero: "; op = getch(); switch(op){ case '1': list(); break; case '2': gt(6,18); cout<<"Volviendo..."; Sleep(200); main(); break; case '3': gt(6,18); cout<<"Saliendo..."; Sleep(200); gt(5,25); exit(1); break; default: gt(6,18); cout<<"Digite un numero del 1 al 3..."; system("pause"); break; } } while(op != '4' || op == '2'); system("pause"); } void list(){ system("cls"); fflush(stdin); if((pun)->defi == 0){ gt(15, 10); cout<<"No se Encontraron Registros..."; } else{ gt(16,8); cout<<"--- REGISTROS ---"; gt(3,10); cout<<"No."; gt(7,10); cout<<"Codigo"; gt(17,10); cout<<"Nombre"; gt(33,10); cout<<"Apellido"; gt(47,10); cout<<"Nota 1"; gt(57,10); cout<<"Nota 2"; gt(67,10); cout<<"Definitiva"; for(int i=0;i<ne;i++){ gt(3,i+12); cout<<i+1; gt(7,i+12); cout<<(pun+i)->cod; gt(17,i+12); cout<<(pun+i)->nom; gt(32,i+12); cout<<(pun+i)->apel; gt(47,i+12); cout<<(pun+i)->n1; gt(57,i+12); cout<<(pun+i)->n2; gt(67,i+12); cout<<(pun+i)->defi; } system("pause"); } }
Y asi me queda cuando quiero mostrar los registros. --- REGISTROS --- No. Codigo Nombre Apellido Nota 1 Nota 2 Definitiva 1 32GRE ANDRES SUR 45 20 32.5 2 AH3H2 ♥ PEREZ 34 50 42 3 4H2BG ESTEBAN HONZ 45 35 40Presione una tecla para continuar . . .
|
|
|
En línea
|
|
|
|
ThunderCls
Desconectado
Mensajes: 455
Coder | Reverser | Gamer
|
Tu declaracion de "pun" es la siguiente: struct notas{ char nom[50]; char apel[50]; char cod[50]; float n1, n2; float defi; }alu, *pun=&alu;
Significa que "pun" es simplemente un puntero a una variable de tipo estructura "notas". Luego mas adelante haces algo como: (pun+i)->cod
Significa que estas accediendo a una posicion en memoria de la que no tienes control (intentas acceder mas alla de los limites de tu variable con pun+i). Cuando accedes a una zona de memoria no reservada, el contenido es incierto ya que tu aplicacion o cualquier otra puede usarla. Una posible solucion es declarar "pun" como un array de estructuras, o mejor aun, como un contenedor dinamico (vector, list). He modificado solamente la declaracion y uso de la variable "pun" para que tengas una idea: #include <string.h> #include <iostream> #include <windows.h> #include <conio.h> #include <vector> using namespace std; void gt(int x, int y) { // -Posicion X y Y en el Programa HANDLE Manipulador; //Puntero COORD Coordenadas; //Coordenadas Manipulador = GetStdHandle(STD_OUTPUT_HANDLE); //Contenedor del Programa Coordenadas.X = x; //Posicion en X Coordenadas.Y = y; //Posicion en Y SetConsoleCursorPosition(Manipulador, Coordenadas); //Envia el Contenedor y variable para la posicion } void formu() { system("cls"); gt(15, 9); cout << "Codigo: "; gt(15, 11); cout << "Nombres: "; gt(15, 12); cout << "Apellidos: "; gt(15, 14); cout << "Nota 1: "; gt(15, 15); cout << "Nota 2: "; gt(15, 17); cout << "Su Nota Definitiva es: "; } struct notas { char nom[50]; char apel[50]; char cod[50]; float n1, n2; float defi; }alu; vector<notas> pun; void capt(); void list(); void consul(); int ne; int main() { char op; do { system("cls"); gt(20, 10); cout << "MENU REGISTROS"; gt(22, 12); cout << "1. Capturar."; gt(22, 13); cout << "2. Consultar registros."; gt(22, 14); cout << "3. Salir."; gt(23, 16); cout << char(167) << "Digite un numero: "; op = _getch(); switch (op) { case '1': capt(); break; case '2': consul(); break; case '3': gt(6, 18); cout << "Saliendo..."; Sleep(200); gt(5, 25); exit(1); break; default: gt(6, 18); cout << "Debe digitar un numero del 1 al 3..."; system("pause"); break; } } while (op != '3'); } void capt() { system("cls"); gt(15, 10); cout << "Digite el Numero de Formularios a agregar: "; cin >> ne; const int ju = ne; for (int i = 0; i < ju; i++) { struct notas nota; formu(); fflush(stdin); gt(23, 9); cin >> nota.cod; gt(24, 11); cin >> nota.nom; gt(26, 12); cin >> nota.apel; gt(23, 14); cin >> nota.n1; gt(23, 15); cin >> nota.n2; nota.defi = (nota.n1 + nota.n2) / 2; gt(38, 17); cout << nota.defi; pun.push_back(nota); system("pause"); } ne = ju; } void consul() { char op; do { system("cls"); gt(20, 10); cout << "MENU - Consultas"; gt(22, 12); cout << "1. Listar."; gt(22, 13); cout << "2. Volver al menu anterior"; gt(22, 14); cout << "3. Salir"; gt(23, 16); cout << "Digite un numero: "; op = _getch(); switch (op) { case '1': list(); break; case '2': gt(6, 18); cout << "Volviendo..."; Sleep(200); main(); break; case '3': gt(6, 18); cout << "Saliendo..."; Sleep(200); gt(5, 25); exit(1); break; default: gt(6, 18); cout << "Digite un numero del 1 al 3..."; system("pause"); break; } } while (op != '4' || op == '2'); system("pause"); } void list() { system("cls"); fflush(stdin); if (pun.empty()) { gt(15, 10); cout << "No se Encontraron Registros..."; } else { gt(16, 8); cout << "--- REGISTROS ---"; gt(3, 10); cout << "No."; gt(7, 10); cout << "Codigo"; gt(17, 10); cout << "Nombre"; gt(33, 10); cout << "Apellido"; gt(47, 10); cout << "Nota 1"; gt(57, 10); cout << "Nota 2"; gt(67, 10); cout << "Definitiva"; for (int i = 0; i < ne; i++) { auto nota = pun.at(i); gt(3, i + 12); cout << i + 1; gt(7, i + 12); cout << nota.cod; gt(17, i + 12); cout << nota.nom; gt(32, i + 12); cout << nota.apel; gt(47, i + 12); cout << nota.n1; gt(57, i + 12); cout << nota.n2; gt(67, i + 12); cout << nota.defi; } system("pause"); } }
Saludos
|
|
|
En línea
|
|
|
|
Sword9K
Desconectado
Mensajes: 10
|
Gracias. Ya pude entender mejor donde estaba el problema de los punteros, voy a intentar hacerlo con un array de estructuras, no entiendo muy bien la libreria vector xD. Lo del problema es que, como el puntero accedia a un memoria que no tenia reservada, me cambiaba algunas variables, por ejemplo. void capt(){ system("cls"); gt(15,10); cout<<"Digite el Numero de Formularios a agregar: "; cin>>ne; const int ju = ne; for(int i=0;i<ju;i++){ formu(); fflush(stdin); gt(23,9); gets((pun+i)->cod); gt(24,11); gets((pun+i)->nom); gt(26,12); gets((pun+i)->apel); gt(23,14); cin>>(pun+i)->n1; gt(23,15); cin>>(pun+i)->n2; (pun+i)->defi=((pun+i)->n1+(pun+i)->n2)/2; gt(38,17); cout<<(pun+i)->defi; system("pause"); } ne = ju; }
Con ne, la variable para pedir el numero de formularios para el for, como que cambiaba su valor y no salia del for, por eso agregue una constante "const int ju", digamos para solucionarlo y que su valor no cambiara, pero aun asi tambien cambiaba los demas valores. Ya lo unico que me no entiendo es, si pongo un numero cualquiera en el for, ya me salen los datos bien. Como ejemplo, pongo que solo se hagan 3 formularios, y eso ya arregla el problema. void capt(){ system("cls"); for(int i=0;i<3;i++){ formu(); fflush(stdin); gt(23,9); gets((pun+i)->cod); gt(24,11); gets((pun+i)->nom); gt(26,12); gets((pun+i)->apel); gt(23,14); cin>>(pun+i)->n1; gt(23,15); cin>>(pun+i)->n2; (pun+i)->defi=((pun+i)->n1+(pun+i)->n2)/2; gt(38,17); cout<<(pun+i)->defi; system("pause"); } }
|
|
|
En línea
|
|
|
|
RayR
Desconectado
Mensajes: 243
|
Primero, algunas sugerencias/correciones. fflush(stdin) es incorrecto. La función fflush sólo se debe usar para flujos de salida, como stdout. Hacerlo con stdin es una violación a las reglas del propio lenguaje y aunque te pueda funcionar en Windows (en los otros sistemas operativos falla), no hay garantía de que siempre lo haga. En C++, una forma de limpiar el buffer es: #include <limits> ... cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
O al estilo C, con while y getchar. Son básicamente las únicas maneras correctas de hacerlo. A veces recomiendan una con fseek, pero es tan incorrecta como fflush(stdin). También deberías evitar gets. Es una función insegura y que desde hace años ya no es parte oficial de C o C++, y algunos compiladores incluso te darán error. En su lugar usa getline, cin.getline, o fgets. En cuanto a tu problema, como ya te comentaron, es un error acceder a memoria que no reservaste. pun+1, pun+2, etc. apuntan a direcciones de memoria que no deberías tocar. Lo que sucede cuando lo haces es que estás escribiendo a direcciones que podrían estar ocupadas por otras variables (o que otras variables van a ocupar más adelante en la ejecución de tu programa), e incluso puedes ocasionar que tu programa se cierre inesperadamente, al estar accediendo a memoria que el sistema operativo no reservó para tu programa. En tu caso, por lo que comentas, lo que debe estar pasando es que ptr+1 se refiere a la dirección de memoria ocupada por ne. Por lo tanto, cuando modificas ne, a la vez estás modificando un campo de ptr+1, y viceversa. Al usar la variable ju, evitas que tus gets modifiquen indirectamente a ne, pero al final de esa función, en la línea: ne = ju; al modificar ne, indirectamente estás modificando un campo de ptr+1, y de ahí los símbolos que mencionas. Por cierto, ju ni siquiera necesitaba ser const. Al ser variable local de capt, se encontrará en una posición de la memoria algo alejada de alu, que es variable global, por lo que no se superponen. Además, el calificador const sólo impide que en tu código manualmente modifiques la variable, pero todavía se puede modificar indirectamente si tienes un puntero a su dirección. De cualquier forma, el problema es que jamás debes acceder a memoria que no hayas reservado. Aunque algunas veces un programa que lo haga parezca funcionar correctamente, nunca es así. Internamente modifica algo que no debería y eventualmente causará problemas.
|
|
|
En línea
|
|
|
|
Sword9K
Desconectado
Mensajes: 10
|
gracias, ya he podido arreglar el programa. Sobre el problema, lo hice con el depurador y vi que, al poner un numero en el for, al menos el ciclo si terminaba, si utilizaba ne, después de usar pun+i, cambiaba el valor de ne y no terminaba, o cambiaba el valor de los string. En el programa deje solo un puntero en el struct. struct notas{ ... }*pun;
y luego en la funcion capt(), puse un arreglo dinamico. void capt(){ system("pause"); gt(15,10); cout<<"Digite el Numero de Formularios a agregar: "; cin>>ne; pun = new notas [ne]; for(int i=0;i<ne;i++){ ... }
Ademas, cambie el fflush() con el cin.ignore() y utilice el cin.getline() con los punteros.
|
|
« Última modificación: 11 Abril 2020, 04:32 am por Sword9K »
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
mostrar los valores de una key del registro de windows
Programación C/C++
|
andres_89a
|
3
|
3,256
|
1 Octubre 2012, 18:05 pm
por Eternal Idol
|
|
|
mostrar registro de tabla
PHP
|
basickdagger
|
5
|
2,760
|
26 Febrero 2013, 18:26 pm
por basickdagger
|
|
|
Mostrar registro de una acción
Java
|
siuxoes
|
1
|
1,591
|
1 Diciembre 2013, 19:48 pm
por Zoik
|
|
|
¿Cómo mostrar en la web un registro formateado de una BBDD?
Scripting
|
joanballester
|
1
|
2,084
|
17 Diciembre 2015, 12:40 pm
por ivancea96
|
|
|
Mostrar un registro asociado a otro??
Bases de Datos
|
Geg1
|
2
|
2,862
|
17 Marzo 2018, 19:45 pm
por srWhiteSkull
|
|