Archivos: condicional IF no compara dos strings.

Iniciado por FranAI, 28 Octubre 2020, 02:14 AM

0 Miembros y 1 Visitante están viendo este tema.

FranAI

Ya varias veces me viene pasando lo mismo con otros programas, el condicional if no me compara dos strings,  no entra, pasa de largo. He usado tanto el operador "==" como el metodo .compare, y realmente no se que puede estar mal.
CPP de carga:
Código (cpp) [Seleccionar]
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
using namespace std;
struct registro{
int numCuenta, saldoCuenta;
string apellido, nombre, codCuenta;
};registro r[6];
int main()
{
FILE *p = fopen("registros4.dat", "ab");
if(p == NULL)
{
cout << "Error al abrir el archivo.";
exit(1);
}
else
{
cout << "Seis clientes" << endl;
for(int i = 0; i < 6; i++)
{

cout << "CLIENTE " << i+1 << endl;
cout << "Ingrese numero de cuenta del cliente: ";
cin >> r[i].numCuenta;
cout << "Ingrese codigo de cuenta del cliente: ";
cin >> r[i].codCuenta;
cout << "Ingrese nombre del cliente: ";
cin >> r[i].nombre;
cout << "Ingrese apellido del cliente: ";
cin >> r[i].apellido;
cout << "Ingrese saldo de la cuenta del cliente: ";
cin >> r[i].saldoCuenta;
fwrite(&r[i], sizeof(registro), 1, p);
}
system("pause");
fclose(p);
}
}


CPP del proceso, donde está el problema:
Código (cpp) [Seleccionar]
#include <iostream>
#include <stdlib.h>
#include <string>
#include <stdio.h>
using namespace std;
struct registro{
int numCuenta, saldoCuenta;
string apellido, nombre, codCuenta;
};registro r[6];
int main()
{
FILE *p = fopen("registros4.dat", "rb");
if(p == NULL)
{
cout << "Error al abrir el archivo.";
exit(1);
}
else
{
int num = 0, importe = 0, a = 0, b = 0;
string A = "A", B = "B", C = "C", D = "D";
for(int i = 0; i < 6; i++)
{
fread(&r[i], sizeof(registro), 1, p);
if(r[i].codCuenta.compare(B) == 0)
{
cout << "Cuenta bloqueada" << endl;
cout << "Numero de cuenta: " << r[i].numCuenta << endl;
cout << "Nombre del cliente: " << r[i].nombre << endl;
cout << "Apellido del cliente: " << r[i].apellido << endl;
cout << "Saldo de cuenta: " << r[i].saldoCuenta << endl << endl;
}
if(r[i].codCuenta.compare(C) == 0)
{
num = i;
cout << "Cuenta en gestion judicial" << endl;
cout << "Numero de cuenta: " << r[i].numCuenta << endl;
cout << "Nombre del cliente: " << r[i].nombre << endl;
cout << "Apellido del cliente: " << r[i].apellido << endl;
cout << "Saldo de cuenta: " << r[i].saldoCuenta << endl << endl;
importe += r[num].saldoCuenta;
}
if(r[i].codCuenta.compare(A) == 0)
{
a++;
}
if(r[i].codCuenta.compare(D) == 0)
{
b++;
}
}

cout << "Cuentas normales: " << b << endl;
cout << "Cuentas cerradas: " << a << endl;
}
system("pause");
fclose(p);
return 0;
}

K-YreX

He probado y funciona correctamente.

El único error que se me ocurre es que al abrir el fichero para escribir lo haces con el argumento "ab" que indica que añade lo que escribas al final del fichero sin borrar lo que ya tenía (y la b de binario).
Si el fichero tiene otros registros anteriores estás trabajando con unos datos indeseados.

De no ser eso incluye algún mensaje en pantalla después de obtener los registros del fichero al array para ver que el contenido del array sea el esperado.

Suerte.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

Eternal Idol

#2
Para mi esta mal planteado de base, no podes escribir un std::string asi en un archivo, estas usando los datos de la representacion interna del objeto. Deberias usar la cadena devuelta por c_str. ¿Como sabes el tamaño de un std::string en primer lugar (sizeof(registro) lo asume implicitamente como fijo)? ¿Que pasa si la cadena no es trivial y el std::string usa memoria dinamica?

Ejemplo (VC++ 2017 x64):
Código (cpp) [Seleccionar]
std::string test = "creo que esta cadena es lo suficientemente larga como para que la clase std::string tenga que guardarla en memoria dinamica";

Ahora el viejo y querido WinDbg:
0:000> x
000000d5`ca5afe20 test = "creo que esta cadena es lo suficientemente larga como para que la clase std::string tenga que guardarla en memoria dinamica"

0:000> db 000000d5`ca5afe20
000000d5`ca5afe20  b0 c8 52 38 93 02 00 00-15 48 7c f8 f6 7f 00 00  ..R8.....H|.....
000000d5`ca5afe30  7b 00 00 00 00 00 00 00-7f 00 00 00 00 00 00 00  {...............
000000d5`ca5afe40  d8 4b 90 46 a8 84 00 00-88 7b 84 f8 f6 7f 00 00  .K.F.....{......
000000d5`ca5afe50  00 00 00 00 00 00 00 00-34 4d 7c f8 f6 7f 00 00  ........4M|.....
000000d5`ca5afe60  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5afe70  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5afe80  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5afe90  00 00 00 00 00 00 00 00-24 7c 59 ac fc 7f 00 00  ........$|Y.....
0:000> db
000000d5`ca5afea0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5afeb0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5afec0  00 00 00 00 00 00 00 00-a1 ce ea ac fc 7f 00 00  ................
000000d5`ca5afed0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5afee0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5afef0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5aff00  00 00 00 00 0b 0c d3 86-00 00 00 00 00 00 00 00  ................
000000d5`ca5aff10  00 00 00 00 00 00 00 00-90 0f 17 aa fc 7f 00 00  ................
0:000> db
000000d5`ca5aff20  c0 ee 5a ca d5 00 00 00-80 98 85 ff 0f 00 60 73  ..Z...........`s
000000d5`ca5aff30  9b 03 c4 2c fc 7f 00 00-c0 ee 5a ca d5 00 00 00  ...,......Z.....
000000d5`ca5aff40  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5aff50  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5aff60  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5aff70  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5aff80  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5aff90  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
0:000> db
000000d5`ca5affa0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5affb0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5affc0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5affd0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5affe0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5afff0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
000000d5`ca5b0000  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????
000000d5`ca5b0010  ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ??  ????????????????

Eso se escribiria usando la logica de estos programas, ahi no esta la cadena en cuestion sin un puntero a la misma y otros campos del std::string.

Como se puede ver aca esto funcionaria (dada la implementacion que estoy usando de la STL que puede cambiar sin que lo sepamos con cualquier actualizacion) de casualidad mientras la cadena tuviera pocos caracteres (15 o menos) y se usara _Buf en lugar de _Ptr.


0:000> dq 000000d5`ca5afe20
000000d5`ca5afe20  00000293`3852c8b0

0:000> da 00000293`3852c8b0
00000293`3852c8b0  "creo que esta cadena es lo sufic"
00000293`3852c8d0  "ientemente larga como para que l"
00000293`3852c8f0  "a clase std::string tenga que gu"
00000293`3852c910  "ardarla en memoria dinamica"

Deberias definir un formato POD para poder leer y escribir.

https://en.wikipedia.org/wiki/Passive_data_structure
https://en.wikipedia.org/wiki/Serialization

Tambien al llamar a fread estamos nuevamente escribiendo en donde no deberiamos, la estructura interna del std::string, en unos objetos que ya llamaron a su constructor. ¿Que pasa si le escribimos en _Ptr un puntero indefinido? A la larga nada bueno y esto es un std::string si llegamos a hacerlo con otros contenedores con representacion interna mas compleja pueden haber mas problemas.

En mi caso sucede esto al llamar al destructor, se intenta liberar un puntero erroneo y corrompe el monticulo:
0:000> g
(c814.e2f8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll!RtlpFreeHeapInternal+0x7d3:
00007ffc`ace807e3 41807d0f05      cmp     byte ptr [r13+0Fh],5 ds:00000232`9c5da59f=??
0:000> k
# Child-SP          RetAddr           Call Site
00 00000023`eb94fbf0 00007ffc`ace7fba1 ntdll!RtlpFreeHeapInternal+0x7d3
01 00000023`eb94fca0 00007ff7`548136dc ntdll!RtlFreeHeap+0x51
02 00000023`eb94fce0 00007ff7`547808f7 swrite!_free_base+0x1c [minkernel\crts\ucrt\src\appcrt\heap\free_base.cpp @ 105]
03 00000023`eb94fd10 00007ff7`5478b9a2 swrite!std::_Deallocate<16,0>+0x37 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\xmemory0 @ 208]
04 00000023`eb94fd40 00007ff7`54786217 swrite!std::allocator<char>::deallocate+0x22 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\xmemory0 @ 993]
05 00000023`eb94fd70 00007ff7`54783bb3 swrite!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy_deallocate+0x87 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\xstring @ 3995]
06 00000023`eb94fdc0 00007ff7`5478bd9d swrite!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> >+0x13 [c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\xstring @ 2461]
07 00000023`eb94fdf0 00007ff7`547c4d34 swrite!main+0x7d [c:\src\swrite.cpp @ 30]
08 (Inline Function) --------`-------- swrite!invoke_main+0x22 [d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 78]
09 00000023`eb94fe60 00007ffc`ac597c24 swrite!__scrt_common_main_seh+0x10c [d:\agent\_work\2\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
0a 00000023`eb94fea0 00007ffc`aceacea1 KERNEL32!BaseThreadInitThunk+0x14
0b 00000023`eb94fed0 00000000`00000000 ntdll!RtlUserThreadStart+0x21


PD. El operador == de std::string llama a std::string::compare que es case sensitive.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón