Dev - C++ - Ayuda con Lista Enlazada | Nodo

   
Vista:

Ayuda con Lista Enlazada | Nodo

Publicado por Erick (1 intervención) el 26/03/2018 22:51:29
Saludos compañeros, tengo una consulta que hacerles respecto a un proyecto que tengo que realizar.

Básicamente quiero guardar en un archivo de texto una serie de nodos, para que posteriormente sean leídos y reconocidos por la aplicación. Realicé el código base en CMD y me aseguré de que funcionara, pero como la aplicación es en WinApi a la hora de adaptarla me surgen problemas.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <iostream>
#include <conio.h>
#include <fstream>
 
using namespace std;
char Ruta[_MAX_PATH] = "Usuarios//PRUEBA.txt";
struct USU
{
	int ID;
	char Nombre[20];
	char Nick[20];
	char Contra[12];
	//char Foto[20];
	USU *Sig;
	USU *Ant;
}; USU *Head = 0;
 
void Escribir();
void Leer();
void A_N(USU * Nodo, int dif);
 
void main() {
 
	Leer();
	short opc = 0;
	do {
		system("cls");
		cout << " - | QUE ES LO QUE QUIERE HACER? | -" << endl;
		cout << "" << endl;
		cout << " - | 1.- Agregar | -" << endl;
		cout << " - | 2.- Buscar | -" << endl;
		cout << " - | 3.- Mostrar | -" << endl;
		cout << " - | 4.- Borrar primer usuario | -" << endl;
		cout << " - | 5.- Salir | -" << endl;
		cout << endl << "Introduce el numero correspondiente:\n\n";
		cin >> opc;
		switch (opc) {
		case 1: {
			system("cls");
			USU * Nuevo = 0;
			Nuevo = new USU;
			cout << "Escribe el Nick: " << endl;
			cin >> Nuevo->Nick;
			cout << "Escribe tu nombre (sin espacios): " << endl;
			cin >> Nuevo->Nombre;
			Nuevo->Sig = 0; //inicializar sig y ant
			Nuevo->Ant = 0;
			Nuevo->ID = 0;
			A_N(Nuevo, 0);
			printf("El usuario se ha agregado satisfactoriamente.");
			_getch();
			break;
		}
 
                [..] // Aquí omití el resto del código que es necesario mostrar en este momento.
 
		}
		case 5: {
			break;
		}
		}
	} while (opc < 5);
	Escribir();
}
 
void Escribir() {
	ofstream Archivo;
	Archivo.open(Ruta, ios::trunc); //text
	if (Archivo.is_open())
	{
		USU * Aux = Head;
		while (Aux != 0)
		{
			Archivo.write((char*)Aux, sizeof(USU)); Archivo << endl;
			Aux = Aux->Sig;
		}
		Archivo.close();
	}
	else
		cout << "No se pudo encontrar el archivo a escribir";
	_getch();
}
void Leer() {
	ifstream Archivo;
	Archivo.open(Ruta);
	if (Archivo.is_open())
	{
		USU * Nuevo = new USU;
		Archivo.read((char*)Nuevo, sizeof(USU));
		while (!Archivo.eof())
		{
			Nuevo->Sig = 0;
			Nuevo->Ant = 0;
			A_N(Nuevo, 1);
			Nuevo = new USU;
			Archivo.read((char*)Nuevo, sizeof(USU)); // castear, cambiar a char (char*)
		}
		Archivo.close();
	}
	else
		cout << "No se pudo encontrar el archivo a leer";
	_getch();
}
void A_N(USU * Nodo, int Dif) {
	if (Head == 0) {
		if (Dif == 0)
			Nodo->ID = 1;
		Head = Nodo;
	}
	else
	{
		USU * Ultimo = Head;
		while (Ultimo->Sig != 0) {
			Ultimo = Ultimo->Sig;
		}
		if (Dif == 0)
			Nodo->ID = Ultimo->ID + 1;
		Ultimo->Sig = Nodo;
		Nodo->Ant = Ultimo;
	}
}

Ese codigo me funciona. Guarda los nodos en el archivo, guarda y lee el archivo correctamente. En el me basé, pero no sé que estoy haciendo mal en WinApi, ya que el primero y segundo nodo lo guarda correcto, pero a la hora de registrar un tercer usuario el ID me da un valor muy alto (a veces negativo) y random (ej. 1148675, cuando debería seguir 3). Les adjunto el código adaptado a WinApi en el que estoy trabajando:

Colocaré sólo las partes en las que trabaja el código.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
BOOL CALLBACK Registro(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_INITDIALOG:
		GetCurrentDirectory(MAX_PATH, raiz);
		char Nombre[30], Nick[15], Contra[12], Contra2[12], Img[_MAX_PATH];
		char UsAux[30];
		LeerArchivo();
 
		AsignarImgPerfil(hDlg, IDC_REG_ImgPerfil, gfotoP, 0, 0);
 
		strcpy(IMG_Logo, raiz); strcat(IMG_Logo, "\\Img\\Programa\\"); strcat(IMG_Logo, "Logo1.bmp");
		LogoPrin = (HBITMAP)LoadImage(NULL, IMG_Logo, IMAGE_BITMAP, 240, 90, LR_LOADFROMFILE);
		SendDlgItemMessage(hDlg, IDC_LogoPrin, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)LogoPrin);
		strcpy(IMG_Reg, raiz); strcat(IMG_Reg, "\\Img\\Programa\\"); strcat(IMG_Reg, "Registrarse.bmp");
		ImgReg = (HBITMAP)LoadImage(NULL, IMG_Reg, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
		SendDlgItemMessage(hDlg, IDC_REG_Regis, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)ImgReg);
		return true;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDC_REG_Regresar:
			EndDialog(hDlg, 0);
			return true;
		case IDC_REG_ImgBuscar:
			AbrirImgPerfil(hDlg, IDC_REG_ImgB, 1);
			GetWindowText(GetDlgItem(hDlg, IDC_REG_ImgB), gfotoP, MAX_PATH); //Para obtener la foto en gfotoP
			AsignarImgPerfil(hDlg, IDC_REG_ImgPerfil, gfotoP, 100, 100);
			strcpy(IMG_Perfil, gfotoP);
			return true;
		case IDC_REG_Regis:
			USU * Nuevo = 0;
			Nuevo = new USU;
			GetDlgItemText(hDlg, IDC_REG_NombreB, Nuevo->Nombre, 30); //strcpy(Nombre, Nuevo->Nombre);
			GetDlgItemText(hDlg, IDC_REG_NickB, Nuevo->Nick, 15);	 //strcpy(Nick, Nuevo->Nick);
			GetDlgItemText(hDlg, IDC_REG_PassB, Nuevo->Pass, 12);	strcpy(Contra, Nuevo->Pass);
			GetDlgItemText(hDlg, IDC_REG_PassB2, Nuevo->Pass2, 12); strcpy(Contra2, Nuevo->Pass2);
			GetDlgItemText(hDlg, IDC_REG_ImgB, Nuevo->Img, _MAX_PATH); //strcpy(Img, Nuevo->Img);
			//SetDlgItemText(hDlg, IDC_Reg_ImagenBox, Contra2);    // Utilizo esto para verificar que obtengo el dato de Pass2
 
			/* VALIDACION EN EL REGISTRO */
			if (strcmp("", Nuevo->Nick) != 0) { // Pregunta si esta vacío el campo Nick
				if (!CompararUs(UsAux, Nuevo->Nick)) {
					if (strcmp("", Nuevo->Nombre) != 0) { // Pregunta si esta vacío el campo nombre
						if (strcmp("", Nuevo->Pass) != 0) {  // Pregunta si está vacío el campo contraseña
							if (CompararPass(Contra, Nuevo->Pass2)) {  // Compara si las contraseñas son las mismas
								if (strcmp("", Nuevo->Img) != 0) { // pregunta si está vacío el campo imagen
									//Nuevo = C_N(Nick, Nombre, Contra, Contra2, Img);
									Nuevo->Sig = 0;
									Nuevo->Ant = 0;
									Nuevo->ID = 0;
									A_N(Nuevo, 0);
									EscribirArchivo(); //Lista, Us, Contra, IMG_Perfil
									MessageBox(ghDlg, "REGISTRO COMPLETADO", "¡ATENCION!", MB_OK + MB_ICONWARNING);
									EndDialog(hDlg, 0);
								}
								else { MessageBox(ghDlg, "ELIJA UNA IMAGEN DE PERFIL", "¡ATENCION!", MB_OK + MB_ICONWARNING); }
							}
							else { MessageBox(ghDlg, "LAS CONTRASEÑAS NO COINCIDEN", "¡ATENCION!", MB_OK + MB_ICONWARNING); }
						}
						else { MessageBox(ghDlg, "CAMPO DE CONTRASEÑA VACÍO", "¡ATENCION!", MB_OK + MB_ICONWARNING); }
					}
					else { MessageBox(ghDlg, "CAMPO DE NOMBRE VACÍO", "¡ATENCION!", MB_OK + MB_ICONWARNING); }
				}
				else { MessageBox(ghDlg, "NICK EN USO", "¡ATENCION!", MB_OK + MB_ICONWARNING); }
			}
			else { MessageBox(ghDlg, "CAMPO DE NICK VACÍO", "¡ATENCION!", MB_OK + MB_ICONWARNING); }
			/* TERMINA VALIDACION EN EL REGISTRO */
			return true;
		}
		return true;
	case WM_CLOSE:
		return true;
	case WM_DESTROY:
		return true;
	}
	return false;
}
 
void EscribirArchivo() //USU* ultimo, char Us[15], char Contra[15], char ImgP[_MAX_PATH]
{
	strcpy(rutaUsu, raiz); strcat(rutaUsu, "\\Users\\usuarios.txt");
 
	ofstream Archivo;
	Archivo.open(rutaUsu, ios::trunc);
	if (Archivo.is_open())
	{
		USU * Aux = Lista;
		while (Aux != 0)
		{
			Archivo.write((char*)Aux, sizeof(USU)); Archivo << " -TERMINA NODO-" << endl;
			Aux = Aux->Sig;
		}
		/*USU*nuevo = new USU, *ultimo;
		nuevo->Nombre;
		nuevo->Sig = NULL;

		Archivo << Us << endl;
		Archivo << Contra << endl;
		Archivo << ImgP << endl;

		if (Lista == NULL)
		{
			Lista = nuevo;
		}
		else
		{
			ultimo = Lista;
			while (ultimo->Sig != NULL)
			{
				ultimo = ultimo->Sig;
			}
			ultimo->Sig = nuevo;
		}*/
		Archivo.close();
	}
}
 
void A_N(USU * Nodo, int Id) {   // Agregar Nodo
	if (Lista == NULL) {
		if (Id == 0) { //Si el primer nodo es igual 0 se le asigna el ID=1;
			Nodo->ID = 1;
		}
		Lista = Nodo;
	}
	else
	{
		USU * Ultimo = Lista;
		while (Ultimo->Sig != 0) {
			Ultimo = Ultimo->Sig;
		}
		if (Id == 0) {
			Nodo->ID = Ultimo->ID + 1;
		}
		Ultimo->Sig = Nodo;
		Nodo->Ant = Ultimo;
	}
}
 
//Esta parte la estaba utilizando pero me di cuenta que era redundante, ya que era lo mismo que hice en el callback.
USU*C_N(char Nick[30], char Nombre[15], char Ps[15], char Ps2[15], char Img[_MAX_PATH]) { //Crear Nodo
	USU * Aux = new USU;
	strcpy(Aux->Nick, Nick);
	strcpy(Aux->Nombre, Nombre);
	strcpy(Aux->Pass, Ps);
	strcpy(Aux->Pass2, Ps);
	strcpy(Aux->Img, Img);
 
	return Aux;
}

Más que nada ese es mi problema, que el registro me lo hace de forma incorrecta en la parte del "ID", guarda todos los datos bien en el .txt exceptuando el ID.
Cualquier consejo y ayuda, me vendría muy bien.
Probablemente vuelva a acudir a ustedes si es que tengo problemas a la hora de leer el archivo.

Desde ya, ¡muchas gracias!
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder