Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Error en evaluación (https://www.clubdelphi.com/foros/showthread.php?t=91760)

Angel.Matilla 19-04-2017 11:36:36

Error en evaluación
 
Me está ocurriendo con relativa frecuencia este error. Trato de dar valor a una variable con una expresión de este estilo:
Código:

AnsiString Nombre, Prueba = "SISTEMA";
Nombre = Usuario->Text == Prueba ? "sysdba" : Usuario->Text;

En principio la estructura es correcta pero como digo con relativa frecuencia al compilar me da este error:
Cita:

E2354 Two operands must evaluate to the same type
Y hasta donde entiendo ambos lados de la comparación son del mismo tipo. ¿Alguna idea?

Ñuño Martínez 19-04-2017 15:39:57

Tiene pinta de ser un error por precedencia de operadores, o posiblemente por la sobrecarga de operadores (¿== quizá?). Prueba a usar paréntesis:
Código:

Nombre = ((Usuario->Text == Prueba) ? "sysdba" : Usuario->Text);
También puede ser porque la propiedad Text no sea AnsiString sino otra cosa (¿char*?) y no sea capaz de hacer la conversión. O vice versa, que sí lo sean y que sea la constante "sysdba" la que da problemas:

Código:

// Asegurándose de que TODO sea AnsiString...
Nombre = (((AnsiString)(Usuario->Text)) == Prueba) ? (AnsiString)"sysdba" : (AnsiString)(Usuario->Text));

Sé que uso muchos paréntesis pero me fío de la precedencia de operadores de C++ menos que de un camión de bombas conducido por un ciego. No sería la primera vez que C++ me cambia el orden cuando hay conversión de tipos con sobrecarga de operadores de por medio. Por ejemplo, que me lo evalúe como:
Código:

(Nombre = (Usuario->Text == Prueba)) ? "sysdba" : Usuario->Text;

Angel.Matilla 19-04-2017 19:09:26

Gracias por tu contestación. Lo cierto es que no se me ocurrió probar las sugerencias que me haces, pero me llamó la atención que si en vez de poner el literal "sysdba" metía ese valor en una variable, así:
Código:

AnsiString cUser = "sysdba", cClave = "masterkey";

NombreUser = Usuario->Text == Date().FormatString("yymmdd") ? cUser : Usuario->Text.Trim();
ClaveUser  = Usuario->Text == Date().FormatString("yymmdd") ? cClave : Clave->Text.Trim();

¡no da error de compilación! lo cual me deja totalmente perplejo. Como alternativa, que no he probado, se me ocurre hacer la comparación así:
Código:

NombreUser = Usuario->Text == Date().FormatString("yymmdd") ? AnsiString("sysdba") : Usuario->Text.Trim();
ClaveUser  = Usuario->Text == Date().FormatString("yymmdd") ? AnsiString("masterkey") : Clave->Text.Trim();


escafandra 19-04-2017 23:31:51

Cita:

Empezado por Angel.Matilla (Mensaje 515669)
...me llamó la atención que si en vez de poner el literal "sysdba" metía ese valor en una variable, así:
Código:

AnsiString cUser = "sysdba", cClave = "masterkey";

NombreUser = Usuario->Text == Date().FormatString("yymmdd") ? cUser : Usuario->Text.Trim();
ClaveUser  = Usuario->Text == Date().FormatString("yymmdd") ? cClave : Clave->Text.Trim();

¡no da error de compilación! lo cual me deja totalmente perplejo.

Al colocar el literal "sysdba" el compilador puede tratarlo como un char[], como un AnsiString o como un String. Lo suyo es declarar la variable del tipo apropiado o forzar el cast en la expresión.
Código:

AnsiString Nombre, Prueba = "SISTEMA"; Nombre = Usuario->Text == Prueba ? AnsiString("sysdba") : Usuario->Text;

Ñuño Martínez 20-04-2017 11:32:27

Justo como dice escafandra, el compilador debe elegir entre tres tipos diferentes (como mínimo). Supongo (nunca he usado Borland C++, me quedé con Turbo C/C++ 2.0) que tanto AnsiString como String son clases que definen operadores diversos, entre ellos alguno para combinarlos con char[], y ahí es donde creo que el compilador se hace el lío y no sabe qué hacer.

Yo dejé de usar C++ precisamente por eso: porque muchas veces se daba un caso similar a este (sobre todo si se usaba la vieja de la STL, no sé si con la nueva habrán arreglado algo) y lo mejor que podría pasarte es que no compilara y devolviera un error, porque si compilaba entonces funcionaba pero mal y era complicadísimo encontrar dónde estaba realmente el error.

Angel.Matilla 20-04-2017 11:36:25

Debe ser algo así. Lo cierto es que poniendolo así:
Código:

NombreUser = Usuario->Text == Date().FormatString("yymmdd") ? AnsiString("sysdba") : Usuario->Text.Trim();
compila bien. ¡Cada día se descubre algo!

ecfisa 20-04-2017 13:54:06

Hola.
Cita:

Empezado por Angel.Matilla (Mensaje 515689)
Debe ser algo así. Lo cierto es que poniendolo así:
Código:

NombreUser = Usuario->Text == Date().FormatString("yymmdd") ? AnsiString("sysdba") : Usuario->Text.Trim();
compila bien.

Si, por que cuando escribes
Código PHP:

   ... ? AnsiString("sysdba") : ... 

estas construyendo una instancia de la clase AnsiString desde la constante literal.

Y del mismo modo funciona si aplicas un moldeo:
Código PHP:

  ... ? (AnsiString)"sysdba" : ... 

Vale aclarar que la constante de cadena es interpretada por el compilador C++ Builder como un arreglo de caracteres terminado en nulo.

Para ejemplificar, la constante "sysdba" es interpretada como char[7], cosa que podes comprobar fácilmente:
Código PHP:

#include <typeinfo>
...
{
  
AnsiString User  "sysdba";
  
TVarRec vr[3];

  
vr[0] = typeid(User).name();
  
vr[1] = '\n';
  
vr[2] = typeid("sysdba").name();

  
ShowMessage(Format("User es tipo: %s %s""sysdba"" es tipo: %s"vr3));


Saludos :)

Angel.Matilla 20-04-2017 14:03:57

^\||/ ¡Más claro, agua!


La franja horaria es GMT +2. Ahora son las 11:31:20.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi