Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Como paso un Tstring a String (https://www.clubdelphi.com/foros/showthread.php?t=24187)

Antuan 11-08-2005 10:03:02

Como paso un Tstring a String
 
Como siempre novato total.
Quizas esto sea lo mas facil pero a mi me trae de calle.
Como estoy aprendiendo pues me cojo ejemplos ya resueltos y me los machaco y de vez en cuando me aparecen incoveniente miro la ayuda de Delphi y parece que a mi no me hace caso no veo lo que busco asi que tengo que recurrir al foro, que para mi es donde mas aprendo.
Perdonarme con esta pregunta que a lo mejor es muy tonta pero no la se.
Es una funcion ya hecha de un ejemplo.
Es una funcion con el resultado a TString y yo lo quiero convertir a una variable de String y no lo se.

dec 11-08-2005 10:17:14

Hola,

Antuan, la clase "TStrings" cuenta con una propiedad de nombre "Text". La misma contiene el texto de todos elementos/items del objeto de tipo "TStrings" de turno: dicha propiedad es de tipo "string". Cualquier otra cosa, ya sabes dónde estamos.

Antuan 11-08-2005 10:24:15

Esto me lo figuraba
 
Esto me lo figuraba pero la compilacion se detiene y me dice Incompatible types. "String' and Tstring
Asi que supongo habra que convertirla de alguna forma ¡No?

dec 11-08-2005 10:53:18

Hola,

Lo que no puedes hacer es que una función que ha de devolver un resultado de tipo "TStrings" devuelva uno de tipo "string" sin más. Lo que has de hacer es cambiar el tipo de resultado de la función a "string". Una vez en la función, si es que es menester utilizar la clase "TStrings", siempre podrás devolver la propiedad "Text", que es de tipo "string". En todo caso, podrías tratar de que la función en cuestión no trabajara con un "TStrings", sino con "string", directamente. Aquí va un ejemplo.

Código Delphi [-]
 function Operaciones : TStrings;
  var
    temp: TStrings;
  begin
    Result := nil;
    temp := TStringList.Create;
    try
      { Resto de instrucciones }
      Result := temp; 
    finally
      temp.Free;
    end;
  end;
Esa función que devuelve un resultado de tipo "TStrings" podría reconvertirse a algo así para devolver un resultado de tipo "strings":

Código Delphi [-]
 function Operaciones : string;
   var
     temp: TStrings;
   begin
     Result := '';
     temp := TStringList.Create;
     try
       { Resto de instrucciones }
       Result := temp.Text; 
     finally
       temp.Free;
     end;
   end;
Y si acaso pudieras sustituir el tipo "TStrings" y trabajar con "strings" directamente, pues entonces podría quedar algo así, pero esto ya lo sabes:

Código Delphi [-]
 function Operaciones : string;
 var
   temp: string;
   begin
   { Instrucciones }
   Result := temp; 
 end;

Casimiro Notevi 11-08-2005 11:01:55

Dec lo ha explicado claramente, pero seguramente Antuan no comprende bien la diferencia entre TStrings, string, etc

La clase TString es "abstracta", sirve de base para otras clases, no se usa directamente, por ejemplo, puedes crear un TStringList que hereda de TStrings y usarla entonces, algo así:

Código Delphi [-]
 procedure TForm1.Button1Click(Sender: TObject);
  var
      sLista : TStrings;
  begin
      sLista := TStringList.Create;
  
      sLista.Add('Este es el string 1');
      sLista.Add('Y este es el 2');
  
      ShowMessage( sLista[0] );
      ShowMessage( sLista[1] );
      ShowMessage( sLista.Text );
 
      sLista.Free;
  end;

Antuan 11-08-2005 11:42:17

La funcion en concreto es???
 
Esta es la funcion en concreto:
Código Delphi [-]
uses NB30;

function GetMACAdress: string;
var
  NCB: PNCB;
  Adapter: PAdapterStatus;

  URetCode: PChar;
  RetCode: char;
  I: integer;
  Lenum: PlanaEnum;
  _SystemID: string;
  TMPSTR: string;
begin
  Result    := '';
  _SystemID := '';
  Getmem(NCB, SizeOf(TNCB));
  Fillchar(NCB^, SizeOf(TNCB), 0);

  Getmem(Lenum, SizeOf(TLanaEnum));
  Fillchar(Lenum^, SizeOf(TLanaEnum), 0);

  Getmem(Adapter, SizeOf(TAdapterStatus));
  Fillchar(Adapter^, SizeOf(TAdapterStatus), 0);

  Lenum.Length    := chr(0);
  NCB.ncb_command := chr(NCBENUM);
  NCB.ncb_buffer  := Pointer(Lenum);
  NCB.ncb_length  := SizeOf(Lenum);
  RetCode         := Netbios(NCB);

  i := 0;
  repeat
    Fillchar(NCB^, SizeOf(TNCB), 0);
    Ncb.ncb_command  := chr(NCBRESET);
    Ncb.ncb_lana_num := lenum.lana[i];
    RetCode          := Netbios(Ncb);

    Fillchar(NCB^, SizeOf(TNCB), 0);
    Ncb.ncb_command  := chr(NCBASTAT);
    Ncb.ncb_lana_num := lenum.lana[i];
    // Must be 16
    Ncb.ncb_callname := '*               ';

    Ncb.ncb_buffer := Pointer(Adapter);

    Ncb.ncb_length := SizeOf(TAdapterStatus);
    RetCode        := Netbios(Ncb);
    //---- calc _systemId from mac-address[2-5] XOR mac-address[1]...
    if (RetCode = chr(0)) or (RetCode = chr(6)) then
    begin
      _SystemId := IntToHex(Ord(Adapter.adapter_address[0]), 2) + '-' +
        IntToHex(Ord(Adapter.adapter_address[1]), 2) + '-' +
        IntToHex(Ord(Adapter.adapter_address[2]), 2) + '-' +
        IntToHex(Ord(Adapter.adapter_address[3]), 2) + '-' +
        IntToHex(Ord(Adapter.adapter_address[4]), 2) + '-' +
        IntToHex(Ord(Adapter.adapter_address[5]), 2);
    end;
    Inc(i);
  until (I >= Ord(Lenum.Length)) or (_SystemID <> '00-00-00-00-00-00');
  FreeMem(NCB);
  FreeMem(Adapter);
  FreeMem(Lenum);
  GetMacAdress := _SystemID;
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
  label1.Caption := GetMACAdress;
end;

Yo quiero dejar de usar el boton y en resultado del label1.caption ponerlo en una variable de string.

Seria asi como me comentais?????????¡No!
Código Delphi [-]
function NumeroMac : string;
   var
     temp: TStrings;
   begin
     Result := '';
     temp := TStringList.Create;
     try
       temp := GetMACAdress;{ Resto de instrucciones }
       Result := temp.Text; 
     finally
       temp.Free;
     end;
   end;

dec 11-08-2005 11:51:42

Hola,

No sé si me estoy perdiendo algo, pero, según veo la función que escribiste arriba no devuelve nada más que una cadena vacía... al principio de la misma... ¡no hay otro "Result" en todo lo que resta de función, siempre devolverá una cadena vacía! ¿Seguro que la copiaste/transcribiste completamente? Y, por otro lado, la función devuelve un "string", no un "TStrings"... ¿No te habrás confundido con la función? ;)

Antuan 11-08-2005 12:12:38

Perdon que me he equivocado que no es esa funcion
 
Lo siento mucho pero es tal el cacao que tengo que me he equivocado de funcion.
Es esta:
Código Delphi [-]
 function getIPs: Tstrings;
 type
   TaPInAddr = array[0..10] of PInAddr;
   PaPInAddr = ^TaPInAddr;
 var
   phe: PHostEnt;
   pptr: PaPInAddr;
   Buffer: array[0..63] of Char;
   I: Integer;
   GInitData: TWSAData;
 begin
   WSAStartup($101, GInitData);
   Result := TstringList.Create;
   Result.Clear;
   GetHostName(Buffer, SizeOf(Buffer));
   phe := GetHostByName(buffer);
   if phe = nil then Exit;
   pPtr := PaPInAddr(phe^.h_addr_list);
   I    := 0;
   while pPtr^[i] <> nil do
   begin
     Result.Add(inet_ntoa(pptr^[i]^));
     Inc(I);
   end;
   WSACleanup;
 end;

Y es resultado de esta funcion es el que lo quiero pasar a una variable de String
Y supongo que seria asi:
Código Delphi [-]
  function Operaciones : string;
    var
      temp: TStrings;
    begin
      Result := 'GetIPs';
      temp := TStringList.Create;
      try
        { Resto de instrucciones }
        Result := temp.Text;
      finally
        temp.Free;
      end;
    end;`

Y la variable de String seria Operaciones???????
Es asi verdad??????
Perdonar por haber cometido tan gran error.
Y muchas gracias por vuestra ayuda.

dec 11-08-2005 13:12:36

Hola,

Cita:

Empezado por Antuan
Perdonar por haber cometido tan gran error.

Nada, hombre, qué dices, no hay nada que perdonar ;)

Por otro lado con la función que escribes últimamente hay un pequeño problema para hacer que esta pase a devolver una cadena, o sea, una variable de tipo "string". ¿Porqué? Pues porque por algo devuelve el tipo que devuelve: la función se llama "GetIps" y puede devolver varias IPs, no solamente una.

Claro está, sería más sencillo de "recorrer" el resultado de la función para obtener cada una de las IPs devuelta, o una, si ese fuera el caso. Desconozco cómo hace lo que hace la función y si, por ejemplo, siempre devuelve una primera IP, digamos, principal, por defecto, acaso la que se persigue... de no ser así... devolver el resultado como "string" podría ocasionarte quebraderos de cabeza, puesto que la variable "resultado" podría contener más de una IP... y habría a partir de ahí que discriminarlas.

En todo caso, así quedaría la función devolviendo una cadena, un tipo "string", en lugar de un "TStrings":

Código Delphi [-]
   function getIPs: string;
  type
    TaPInAddr = array[0..10] of PInAddr;
    PaPInAddr = ^TaPInAddr;
  var
    phe: PHostEnt;
    pptr: PaPInAddr;
    Buffer: array[0..63] of Char;
    I: Integer;
    GInitData: TWSAData;
    temp: TStrings;
  begin
    Result := '';
    WSAStartup($101, GInitData);
    temp := TstringList.Create;
    temp.Clear;
    GetHostName(Buffer, SizeOf(Buffer));
    phe := GetHostByName(buffer);
    if phe = nil then Exit;
    pPtr := PaPInAddr(phe^.h_addr_list);
    I    := 0;
    try
      while pPtr^[i] <> nil do
      begin
        temp.Add(inet_ntoa(pptr^[i]^));
        Inc(I);
      end;
      Result := temp.Text;
    finally
      temp.Free;
    end;
    WSACleanup;
  end;
Se me ocurre a bote pronto, que, si no se encuentra otra forma mejor de hacerlo, tal vez podría cambiarse la siguiente instrucción a algo parecido a:

Código Delphi [-]
  if temp.Count > 0 then
    temp.Add(' $$ ' + inet_ntoa(pptr^[i]^))
  else
    temp.Add(inet_ntoa(pptr^[i]^));
De ese modo, en la cadena que obtuvieras como resultado, caso de haber más de una dirección IP obtendrías algo así como resultado:

Código:

  123.45.32.45 $$ 234.42.23.12
Acaso esos signos "dólar" pudieran servirte luego para averiguar, primero, si hay más de una IP en la cadena "resultado" y, en ese caso, conseguir todas las que hubiera, con ayuda de funciones como "Pos" y "Copy", por ejemplo.

dec 11-08-2005 13:19:39

Hola,

Metí un tanto la pata... puesto que, si ya no se piensa devolver un tipo "TStrings" con la función, ¿a qué utilizarlo entonces, pudiendo utilizar directamente una cadena? Así tal cual:

Código Delphi [-]
  function getIPs: string;
 type
   TaPInAddr = array[0..10] of PInAddr;
   PaPInAddr = ^TaPInAddr;
 var
   phe: PHostEnt;
   pptr: PaPInAddr;
   Buffer: array[0..63] of Char;
   I: Integer;
   GInitData: TWSAData;
 begin
   Result := '';
   WSAStartup($101, GInitData);
   GetHostName(Buffer, SizeOf(Buffer));
   phe := GetHostByName(buffer);
   if phe = nil then Exit;
   pPtr := PaPInAddr(phe^.h_addr_list);
   I    := 0;
   while pPtr^[i] <> nil do
   begin
     if Result = '' then
       Result := (inet_ntoa(pptr^[i]^))
     else
       Result := ' $$ ' + (inet_ntoa(pptr^[i]^);     
     Inc(I);
   end;
   WSACleanup;
 end;
Eso que nos ahorramos, ¿no te parece? ;)

Antuan 11-08-2005 13:51:10

Esta es la que sirve
 
Esta que te pongo es la que sirve:
Código Delphi [-]
function getIPs: Tstrings;
 type
   TaPInAddr = array[0..10] of PInAddr;
   PaPInAddr = ^TaPInAddr;
 var
   phe: PHostEnt;
   pptr: PaPInAddr;
   Buffer: array[0..63] of Char;
   I: Integer;
   GInitData: TWSAData;
 begin
   WSAStartup($101, GInitData);
   Result := TstringList.Create;
   Result.Clear;
   GetHostName(Buffer, SizeOf(Buffer));
   phe := GetHostByName(buffer);
   if phe = nil then Exit;
   pPtr := PaPInAddr(phe^.h_addr_list);
   I    := 0;
   while pPtr^[i] <> nil do
   begin
     Result.Add(inet_ntoa(pptr^[i]^));
     Inc(I);
   end;
   WSACleanup;
 end;
De momento me devuelve una ip solo
Muchas gracias por cambiarme la funcion.
Tengo varias de este tipo y las tendre que cambiar.
Ya he cogido la forma de trabajar con el TString que es para variables de matriz por eso se representa en un TMemo o en un TList.
De ahi el haberte mandado ayer un correo con esta misma funcion para si podias hacerme un pequeño ejemplo del objeto rectangulo.
Con esta misma funcion original que el resultado lo da en un TMemo.
David muchas gracias y perdona por hacerte perder un poco el tiempo.

Casimiro Notevi 11-08-2005 14:27:50

:confused: :confused: :confused:

dec 11-08-2005 15:02:40

Hola,

Cita:

Empezado por Casimiro Notevi
:confused: :confused: :confused:

Creo que Casimiro se sorprende porque sigues utilizando una función que devuelve un "TStrings" como una catedral ;)

Cita:

Empezado por Antuan
De ahi el haberte mandado ayer un correo con esta misma funcion para si podias hacerme un pequeño ejemplo del objeto rectangulo.

Otra vez no entenderán de qué hablamos, pero, en todo caso, creo que lo importante es que... ¡¿No te llegó el correo que te envié ayer noche!? En él llevaba a cabo justo lo que me pedías, junto con algunas aclaraciones y notas al respecto.

* Nota para todos: Un "objeto rectángulo" es un "objeto" de cierto programa de nombre Neobook que permite que puedan añadírsele "plugins", por ejemplo, programados con Delphi. En dicho objeto rectángulo el programador del "plugin" tiene la posibilidad de "añadir" un determinado componente "visual" de Delphi, por ejemplo un "TMemo". Básicamente es esto. ;)

Casimiro Notevi 11-08-2005 16:13:52

Cita:

Empezado por dec
Creo que Casimiro se sorprende porque sigues utilizando una función que devuelve un "TStrings" como una catedral ;)

Efectivamente, es como si una función tiene que devolver un string y hago que devuelva un entero, y luego convertir ese entero a string, sin motivo, necesidad ni falta que hace.

Pero, bueno, allá cada uno con sus manías :)

Lepe 11-08-2005 17:29:25

Pues ahora que hablamos de un memo, mas liado estoy "compadre"

Código Delphi [-]
var lista:TStringList;
begin
lista := GetIps;
Memo.Lines.Assign(lista);
lista.Free;

Y como la funcion devuelve un TStrings, que es del mismo tipo que un Memo.Lines, pues nada se asigna el contenido de uno a otro y corriendo que es gerundio.

Que no, que solo quiero una IP:
Código Delphi [-]
var listaIps:TStringList;
begin
  listaIps:= GetIps;
  if listaips.count>0 then
    memo1.lines.Add(listaips.items[0];
  listaIps.Free;
end;

Advertencia Gorda: La función GetIps se encarga de crear el TStringList que está devolviendo en Result; por eso yo no creo la ListaIps. Solo me encargo de destruirlo con .Free

Otra cosa: Devolver un String con un separador de $$, pues que quieres que os diga, no lo veo yo claro, ya que para eso usamos las propiedades del propio TString:

CharDelimiter
DelimitedText
Y si queremos usar el delimitador "coma" pues ni siquiera tenemos que usar CharDelimiter, ya que el TString provee la propiedad CommaText que precisamente nos devuelve un String con todos lo items separados por comas.

Despues de todo este rollo, ¿que vas a suar? :D

Un saludo

dec 11-08-2005 17:44:04

Hola,

Cita:

Empezado por Lepe
Devolver un String con un separador de $$, pues que quieres que os diga, no lo veo yo claro, ya que para eso usamos las propiedades del propio TString

¡Pero se trata de devolver una cadena de caracteres! Si devolviésemos un "TStrings" claro está que podríamos hacer uso de las propiedades a que haces referencia ;)

Cita:

Empezado por Lepe
Advertencia Gorda: La función GetIps se encarga de crear el TStringList que está devolviendo en Result; por eso yo no creo la ListaIps. Solo me encargo de destruirlo con .Free

Buena advertencia, sí señor. Creo que leí en estos mismos Foros cómo se desaconsejaba devolver "así" los resultados de una función de esas características... ahora digo que trataré de quedarme con la solución que das a eso Lepe.

Casimiro Notevi 11-08-2005 20:54:47

Esa función GetIps es muy peligrosa, tener que acordarse que no libera la memoria del objeto creado. Es una fuente de posibles problemas. Jamás usaría algo así.


nunca digas nunca jamás (me ha venido a la cabeza ese título de 007) :D

Lepe 12-08-2005 12:20:33

Cita:

Empezado por dec

¡Pero se trata de devolver una cadena de caracteres! Si devolviésemos un "TStrings" claro está que podríamos hacer uso de las propiedades a que haces referencia ;)

No me habré explicado con claridad, La primera funcion devuelve un TStrings ¿verdad?, pues simplemente:
- cambiamos el parámetro de salida por String,
- devolvemos CommaText ó DelimitedText, Se acabó el trabajo.
- Liberamos la memoria del TStringList de la función.

Cita:

Empezado por Casimiro Notevi
Esa función GetIps es muy peligrosa, tener que acordarse que no libera la memoria del objeto creado. Es una fuente de posibles problemas. Jamás usaría algo así.

Y no solo eso, ya que además, intuitivamente tu creas el TStringList en memoria antes de usar la función, y despues la susodicha, crea de nuevo el TStringList, por tanto, el que tú creaste, se queda en el limbo y jamás se libera.

La solución sería crear algo así:
Código Delphi [-]
function getIPs(Lista: Tstrings):Boolean;
 type
   TaPInAddr = array[0..10] of PInAddr;
   PaPInAddr = ^TaPInAddr;
 var
   phe: PHostEnt;
   pptr: PaPInAddr;
   Buffer: array[0..63] of Char;
   I: Integer;
   GInitData: TWSAData;
 begin
   WSAStartup($101, GInitData);
   if not Assigned(Lista) then
     raise Exception.Create('func GetIps: Se necesita un TString previamente creado.');
  Lista.Add('lo que sea');
  // demás instrucciones


Un saludo.

dec 13-08-2005 01:44:02

Hola,

Cita:

Empezado por Lepe
No me habré explicado con claridad, La primera funcion devuelve un TStrings ¿verdad?, pues simplemente:
- cambiamos el parámetro de salida por String,
- devolvemos CommaText ó DelimitedText, Se acabó el trabajo.
- Liberamos la memoria del TStringList de la función.

El que no se ha explicado con claridad soy yo, ¡pero si hasta rectifiqué uno de los mensajes que he publicado en este Hilo! Digo que si la función va a devolver un "string", ¿para qué queremos usar el "TStrings"? ¿Para ir añadiendo una línea a cada IP que se encuentre? Pero, suponiendo que queremos que esa función, precisamente, devuelva un "string", ¿porqué no nos olvidamos del "TStrings" y concatenamos en una cadena las posibles "Ips" y luego damos como resultado esta cadena?

Sobre todo, porque, en el momento en que no necesitemos que esa función nos devuelva un "string" bien podemos usarla tal cual, eso sí, devolviendo la lista de "Ips" en un parámetro "TStrings" pasado como referencia a la función o creando una variable de tipo "TStrings" en la función, que sea la que devuelva, nunca haciéndolo como se hace arriba (no liberando el "TStrings" creado en "Result") pues a simple vista llama la atención que ese no es un buen camino.


La franja horaria es GMT +2. Ahora son las 06:35:58.

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