PDA

Ver la Versión Completa : Método Add(s) de TStringList no me hace caso


david.rguez
24-01-2008, 18:59:04
Hola a todos/as:

En un módulo de un programa tengo que utilizar un TStringList ya que tengo que mantener de forma dinámica una lista de claves de exclusión durante la ejecución del programa (para evitar que cierto proceso que tengo que hacer se duplique, generando basura en los resultados).

El caso es que cuando intento añadir un nuevo String a la lista:

lista.add(qtrazaTRAZA12.Value);

No hace ni caso. Es decir, no salta ningún error, pero la lista continúa vacía, con lo que se va al carajo el sistema de control que estoy montando para guiar el proceso.

El campo TRAZA12 al que hago referencia sí es un String y antes de usar la lista hago un create sobre la variable.

¿Alguien sabe por qué no hace nada?

maeyanes
24-01-2008, 19:01:30
Y estás seguro que esa línea se ejecuta?

A lo mejor el compilador la elimina por que no le encuentra relevancia...

Pon un breakpoint en esa linea (F5) y compila tu programa, si el breakpoint sigue activo, ejecuta el programa y ve que sucede antes y despúes de esa línea...


Saludos...

luisgutierrezb
24-01-2008, 19:01:46
y si usas un cast?
lista.add(string(qtrazaTRAZA12.Value));

o incluso no se si puedas hacer esto:
lista.add(qtrazaTRAZA12.AsString);

o ya de plano:
stringTemp := qtrazaTRAZA12.Value;
lista.add(stringTemp);

jachguate
24-01-2008, 19:10:51
De verdad, no me la creo!!! :D

Nunca he visto a un StringList fallar de esta manera. Creo que la línea de código no está ejecutándose, quizás porque las condiciones no se dan para que pase por allí. Estoy seguro que el optimizador no eliminaría una línea como esta.

Otra posibilidad es que estes determinando erroneamente que la línea no se añade, pero que realmente si lo hace. Ambas cosas son fáciles de determinar:


Lista.Add(qTrazaTRAZA12.Value);
ShowMessage(Lista.Text);


Si se muestra el mensaje, el código se está ejecutando. Si el mensaje mostrado es distinto del valor del campo, sigamos echandole la culpa al StringList, si no, busquemos al verdadero culpable!!.

Hasta luego.

;)

david.rguez
24-01-2008, 23:24:04
LA línea sí llega a ejecutarse. Puse puntos de depuración lo primero para corroborarlo y sí llega ahí sin dar problemas.

Sin embargo, no hace nada, tras pasar esa línea el depurador me indica que la lista continúa vacía (no he puesto ShowMessage, lo consulté desde un estado de parada en depuración).

Ya he probado otros modos que me comentasteis como el AsString y el cast, pero el resultado es el mismo :(

jachguate
24-01-2008, 23:34:40
¿Cómo estas comprobando que la lista está vacía?

ixMike
24-01-2008, 23:49:14
¿Podemos ver el código (no sólo una línea)? :)

Al González
25-01-2008, 05:39:04
Hola.

...LA línea sí llega a ejecutarse...tras pasar esa línea el depurador me indica que la lista continúa vacía...
Entonces la única explicación razonable que queda (considerando no te has equivocado de lista), es que la expresión qtrazaTRAZA12.Value, devuelve una cadena vacía en ese momento. ¿Estará ese campo vacío? (campo en blanco en el registro actual, cero registros en el conjunto de datos por estar éste cerrado o filtrado...).

No dejes de respondernos sobre estas cuestiones, aún cuando hayas encontrado la solución.

Saludos.

Al González. :)

jachguate
25-01-2008, 06:06:02
Entonces la única explicación razonable que queda (considerando no te has equivocado de lista), es que la expresión qtrazaTRAZA12.Value, devuelve una cadena vacía en ese momento. ¿Estará ese campo vacío?

Me temo Al, que si ese fuese el caso, la lista no estaría vacía, pues contendría una cadena vacía en su primer elemento.

Se que puede tomarse por un tecnicismo... tampoco creas que me estoy entrenando para abogado, pero francamente no es lo mismo.

Hasta luego.

;)

Al González
25-01-2008, 07:41:05
Vaya que no es lo mismo. Mayor razón para que David responda a tu última pregunta con más precisión. Tú y yo sabemos lo que es una lista realmente vacía, pero en el sentido general un texto sin caracteres (visibles) es coloquialmente considerado como algo vacío. Mi sospecha va por esa línea de investigación. :p

Saludos.

Al González. :)

david.rguez
25-01-2008, 10:49:29
El valor de la traza que guardo no está vacío (lo compruebo pasando el ratón por encima de la variable cuando está en el punto de interrupción del Add, mostrando un cuadro emergente con el valor actual).

Os pongo la porción de código que se encarga del proceso:



lista.Free;
lista:= TStringList.Create;

qtraza.SQL.Clear;

if Label1.Caption = 'atras' then
qtraza.SQL.Add('select * from trazavin where traza27 = :ref and traza05 = ''TRE''')
else
qtraza.SQL.Add('select * from trazavin where traza27 = :ref and traza05 = ''TRS''');
qtraza.Parameters.ParamByName('ref').Value:= refPadre;
qtraza.Open;

while not qtraza.Eof do
begin

// En primer lugar debemos buscar si el parte actual está examinado. Si no lo está, continuamos.
if not buscarLista(lista, qtrazaTRAZA12.Value) then
begin

qprocesos.Close;
qprocesos.SQL.Clear;
qprocesos.SQL.Add('select * from moviproce where mopromovi = :parte and moproorden = :orden');
qprocesos.Parameters.ParamByName('parte').Value:= qtrazaTRAZA12.Value;
qprocesos.Parameters.ParamByName('orden').Value:= qtrazaTRAZA23.Value;
qprocesos.Open;
while not qprocesos.Eof do
begin
taprocesos.Open;
taprocesos.Locate('PROCODIGO',qprocesosMOPROCODIGO.Value,[]);
texto:= texto + taprocesosPRONOMBRE.Value + #13;
taprocesos.Close;
qprocesos.Next;
end;
// Ahora que ya está compuesto el texto lo agregamos
conex.Text.Add(texto);
conex.Style:= csSides;
conex.Text.VertAlign:= vtaTop;
conex.Text.Angle:= 90;

// También debemos agregar este parte a la lista dinámica, para evitar que duplique la búsqueda
lista.Add(qtrazaTRAZA12.AsString);


end;

qtraza.Next;




El Free y Create inicial es para asegurarme de que no quedan rastros si se producen ejecuciones consecutivas.
"qprocesos" y "qtraza" son componentes TADOQuery y "conex" es un componente de terceros para la composición de diagramas.

"buscarLista" es una función que he creado que comprueba mediante el método "IndexOf" si el elemento en cuestión está dentro de la lista.

Como veis, si el elemento no está, busca los datos necesarios, configura el componente del diagrama y agrega el elemento (o eso pretendía) a la lista para que si se repite en el bucle no vuelva a ejecutar todo el proceso.


Pd: Ahí puse "asString" porque fue lo último que probé, pero con "Value" el resultado es el mismo.

david.rguez
25-01-2008, 11:18:10
Bueno, ya se resolvió.

Puse un ShowMessage con el Text y sí que me lo mostraba ahí (el error posterior es que el Free lo tenía colocado donde no debía), pero me queda una cuestión que no entiendo...

...si sí almacenaba correctamente el valor... ¿por qué no me lo mostraba al inspeccionar la lista durante un punto de interrupción (justo después de haber ejecutado el "Add")? :mad:

Gracias a todos por la ayuda.

jachguate
25-01-2008, 15:17:35
...si sí almacenaba correctamente el valor... ¿por qué no me lo mostraba al inspeccionar la lista durante un punto de interrupción (justo después de haber ejecutado el "Add")? :mad:

Ahora veo que maeyanes podría estar en lo correcto cuando dijo:

A lo mejor el compilador la elimina por que no le encuentra relevancia...

Mientras yo estaba equivocado al decir:
Estoy seguro que el optimizador no eliminaría una línea como esta..

Te explico brevemente: Delphi cuenta con un optimizador, que elimina todas aquellas instrucciones irrelevantes al ensamblar tu programa, de manera que no se gasten innecesariamente ciclos del procesador.

Así, si tenemos un código como este:


var
I: Integer;
begin
I:= 10;
end;


Al comiplar, el optimizador se da cuenta que el valor de I no es usado nunca, nos muestra un hint en la consola y elimina la instrucción de asignación, pues el valor no se utilizará en el programa. Esta pieza de delphi es realmente sofisticada, y nunca lo he visto fallar. Así, al hacer algo como:


var
L: TList;
begin
L:= TList.Create;
try
L.Add(Objeto1);
UsarLista(L);
L.Add(Objeto2);
finally
L.Free;
end;
end;


Es probable que el optimizador también note que luego de añadir el Objeto2, la lista no se use mas, y por tanto, la instrucción no es necesaria. Esto supone que el optimizador conoce la VCL, y por tanto sabe cómo optimizar también su uso, cosa que yo no creía probable.

Habrá que leer un poco acerca de él.

Hasta luego.

;)

pd. Edité tu mensaje para cambiar la etiqueta code por la etiqueta delphi. Veras que queda mucho mejor.

maeyanes
25-01-2008, 15:23:28
Hola...

Para poder ver lo que tiene un TStringList mediante el Watch, tienes dos formas:

1. Colocar en el Watch Lista.Text o
2. Colocar en el Watch Lista[n], donde n es el índice que quieras ver, así para ver que valor está en la primera posición de la lista haces: Lista[0]

Si colocas el cursor sobre la variable Lista no vas a ver el contenido de la variable, para eso tendrías que tener en código algo como Lista.Text y poner el cursor sobre Text...


Saludos...

david.rguez
25-01-2008, 16:10:09
jachguate, gracias por la información, realmente interesante; aunque no creo que ese sea el problema, pues sigue sin mostrarlo en depuración aunque sí lo graba (habiendo ya colocado correctamente el Free).

Hola...

Para poder ver lo que tiene un TStringList mediante el Watch, tienes dos formas:

1. Colocar en el Watch Lista.Text o
2. Colocar en el Watch Lista[n], donde n es el índice que quieras ver, así para ver que valor está en la primera posición de la lista haces: Lista[0]

Si colocas el cursor sobre la variable Lista no vas a ver el contenido de la variable, para eso tendrías que tener en código algo como Lista.Text y poner el cursor sobre Text...


Saludos...

Pues yo había mirado lo del cursor porque cuando voy a un objeto que no tiene valor como tal (sino que hay que acceder a una de sus propiedades) me sale el tipo y herencia del componente. Por eso, al ver dos paréntesis sin nada dentro en este, asumí que mostraba una lista sin contenido.

Gracias.