PDA

Ver la Versión Completa : Cómo implementar el siguiente código en una clase


eennzzoo
01-07-2014, 14:42:51
Hola, tengo este codigo [agrega datos de clientes a un archivo] y quisiera implementarle una clase para este codigo.


void __fastcall TAgregarCliente::menuNuevoClick(TObject *Sender)
{
editNombre->Text="";
editApellido->Text="";
editDni->Text="";
}
void __fastcall TAgregarCliente::btnGuardarClick(TObject *Sender)
{
TS1->LoadFromFile("datos.txt");
if ((editNombre->Text != "")&&(editApellido->Text != "")&&(editDni->Text != "")){
for(int i=0; i<TS1->Count; i=i+3) {
if (TS1->Strings[i]==editDni->Text) {
editNombre->Text = "";
editApellido->Text = "";
editDni->Text="";
Application->MessageBox(L"El cliente ya es socio.",L"AVISO", MB_OK | MB_ICONEXCLAMATION);
break;
}else if (i==(TS1->Count-3)){
FILE *F1;
char Nombre[30], Apellido[30], Dni[10];
strcpy(Nombre, AnsiString(editNombre->Text).c_str());
strcpy(Apellido, AnsiString(editApellido->Text).c_str());
strcpy(Dni, AnsiString(editDni->Text).c_str());
F1 = fopen("datos.txt", "a");
if( FS1 == NULL ){
ShowMessage("El archivo no se pudo guardar");
return;
}
fprintf(F1, "%s\n", Dni);
fprintf(F1, "%s\n", Nombre);
fprintf(F1, "%s\n", Apellido);
fclose(F1);
editNombre->Text = "";
editApellido->Text = "";
editDni->Text = "";
Application->MessageBox(L"Has agregado un nuevo cliente.",L"Nuevo cliente", MB_OK);
}
}
}else {
Application->MessageBox(L"Completar todos los campos.",L"AVISO", MB_OK | MB_ICONEXCLAMATION);
}
}

Gracias.

aguml
03-07-2014, 13:54:12
¿Y que problema tienes? Crea el .h y declara la clase con sus metodos publicos y demas.

eennzzoo
03-07-2014, 14:26:06
¿Y que problema tienes? Crea el .h y declara la clase con sus metodos publicos y demas.

Si ya se, pero no se me ocurre cuales podrian ser sus atributos y metodos. Para que luego la pueda usar dentro de ese codigo.

dec
03-07-2014, 15:01:23
Hola,

Me temo que el código en cuestión encierra muchas "cosas" que no son fáciles de dilucidar. Ahí se ven variables, objetos, etc., que no se sabe muy bien de dónde salen, y, así, es casi imposible ayudarte. Tal vez deberías plantear la cuestión de otra forma. Indicando, por ejemplo, qué es lo que se supone que quieres hacer y porqué crees que ello ha de estar en una clase aparte. Por otro lado, recuerda que en el foro se trata de ayudar a resolver problemas más concretos: no se trata de traducir código de un lenguaje a otro, ni de que se desarrollen clases enteras en base a cierto código, etc. Así que deberías concretar bastante más, en mi opinión.

P.D. No escribas en "negrita", puesto que lo que tengas que decir se lee peor, al contrario de lo que pudiera parecer.

eennzzoo
03-07-2014, 15:10:11
Hola,

Me temo que el código en cuestión encierra muchas "cosas" que no son fáciles de dilucidar. Ahí se ven variables, objetos, etc., que no se sabe muy bien de dónde salen, y, así, es casi imposible ayudarte. Tal vez deberías plantear la cuestión de otra forma. Indicando, por ejemplo, qué es lo que se supone que quieres hacer y porqué crees que ello ha de estar en una clase aparte. Por otro lado, recuerda que en el foro se trata de ayudar a resolver problemas más concretos: no se trata de traducir código de un lenguaje a otro, ni de que se desarrollen clases enteras en base a cierto código, etc. Así que deberías concretar bastante más, en mi opinión.

P.D. No escribas en "negrita", puesto que lo que tengas que decir se lee peor, al contrario de lo que pudiera parecer.

Lo que me piden que use clases y solo tengo ese form que agrega clientes a un archivo. No pido traducir el código a otro lenguaje. Solo pido una idea de como podría implementar una clase para ese programa por así decirlo.

dec
03-07-2014, 16:09:39
Hola,

En cualquier caso pides demasiado, en el sentido de que no concretas nada. Por otro lado, y, como te he dicho arriba, el código que has mostrado es difícilmente convertible en una clase: así podrías decírselo a quien te lo haya pedido si lo ha hecho tal cual. Tal vez, insisto, como ya he dicho arriba, podrías decir qué es lo que quieres conseguir, cuál debe ser la funcionalidad de la clase en cuestión. Ahí ya estarías pidiendo que te escribieran dicha clase... pero igual alguien tiene tiempo y ganas suficientes o al menos podría darte alguna orientación sobre cómo hacerlo tú mismo.

Edito: Bueno; mirando de nuevo el código ya se me ocurre alguna cosa... pero yo no domino C++ como para hacer lo que tengo en la cabeza. Tal vez algún otro compañero pueda ayudarte, pues.

dec
03-07-2014, 16:36:16
Hola,

No es exactamente lo mismo, porque, por lo demás debe haber muchísimas maneras de hacer lo mismo o algo parecido. Por otro lado, el siguiente código no es C++ (sino Delphi), pero, en fin, por si pudiera servirte de algo, aquí tienes:


unit UContactos;

interface

uses
Classes, SysUtils;

type
EContactoInvalido = Exception;

type
TContacto = record
DNI: string;
Nombre: string;
Apellidos: string;
end;

type
TContactos = class(TObject)
private
FRutaBaseDatos: string;
FContenidoBaseDatos: TStrings;
private
function ExisteContacto(const datosContacto: TContacto): Boolean;
public
constructor Create(const rutaBaseDatos: string = '');
public
procedure GuardarContactos();
function InsertarContacto(const datosContacto: TContacto): Integer;
end;

implementation

const
RUTA_POR_DEFECTO_BASE_DATOS = 'Contactos.txt';

resourcestring
rsDatosContactoInvalidos = 'Datos del contacto inválidos.';

{ TContactos }

constructor TContactos.Create(const rutaBaseDatos: string = '');
begin
FRutaBaseDatos := rutaBaseDatos;
FContenidoBaseDatos := TStringList.Create();

if Trim(FRutaBaseDatos) = EmptyStr then
FRutaBaseDatos := ExtractFilePath(ParamStr(0))+RUTA_POR_DEFECTO_BASE_DATOS;

if FileExists(rutaBaseDatos) then
FContenidoBaseDatos.LoadFromFile(FRutaBaseDatos);
end;

function TContactos.InsertarContacto(const datosContacto: TContacto): Integer;
begin
Result := -1;
if (Trim(datosContacto.DNI) = EmptyStr)
or (Trim(datosContacto.Nombre) = EmptyStr)
or (Trim(datosContacto.Apellidos) = EmptyStr) then
begin
raise EContactoInvalido.Create(rsDatosContactoInvalidos);
end;
if not Self.ExisteContacto(datosContacto) then
begin
Result := FContenidoBaseDatos.Add(Format
(
'%s|%s|%s',
[datosContacto.DNI, datosContacto.Nombre, datosContacto.Apellidos]
));
end;
end;

procedure TContactos.GuardarContactos();
begin
if Trim(FRutaBaseDatos) = EmptyStr then
FRutaBaseDatos := ExtractFilePath(ParamStr(0))+RUTA_POR_DEFECTO_BASE_DATOS;
FContenidoBaseDatos.SaveToFile(FRutaBaseDatos);
end;

function TContactos.ExisteContacto(const datosContacto: TContacto): boolean;
begin
Result := FContenidoBaseDatos.IndexOf(datosContacto.DNI) = -1;
end;

end.

eennzzoo
03-07-2014, 16:40:47
Hola,

No es exactamente lo mismo, porque, por lo demás debe haber muchísimas maneras de hacer lo mismo o algo parecido. Por otro lado, el siguiente código no es C++ (sino Delphi), pero, en fin, por si pudiera servirte de algo, aquí tienes:


unit UContactos;

interface

uses
Classes, SysUtils;

type
EContactoInvalido = Exception;

type
TContacto = record
DNI: string;
Nombre: string;
Apellidos: string;
end;

type
TContactos = class(TObject)
private
FRutaBaseDatos: string;
FContenidoBaseDatos: TStrings;
private
function ExisteContacto(const datosContacto: TContacto): Boolean;
public
constructor Create(const rutaBaseDatos: string = '');
public
procedure GuardarContactos();
function InsertarContacto(const datosContacto: TContacto): Integer;
end;

implementation

const
RUTA_POR_DEFECTO_BASE_DATOS = 'Contactos.txt';

resourcestring
rsDatosContactoInvalidos = 'Datos del contacto inválidos.';

{ TContactos }

constructor TContactos.Create(const rutaBaseDatos: string = '');
begin
FRutaBaseDatos := rutaBaseDatos;
FContenidoBaseDatos := TStringList.Create();

if Trim(FRutaBaseDatos) = EmptyStr then
FRutaBaseDatos := ExtractFilePath(ParamStr(0))+RUTA_POR_DEFECTO_BASE_DATOS;

if FileExists(rutaBaseDatos) then
FContenidoBaseDatos.LoadFromFile(FRutaBaseDatos);
end;

function TContactos.InsertarContacto(const datosContacto: TContacto): Integer;
begin
Result := -1;
if (Trim(datosContacto.DNI) = EmptyStr)
or (Trim(datosContacto.Nombre) = EmptyStr)
or (Trim(datosContacto.Apellidos) = EmptyStr) then
begin
raise EContactoInvalido.Create(rsDatosContactoInvalidos);
end;
if not Self.ExisteContacto(datosContacto) then
begin
Result := FContenidoBaseDatos.Add(Format
(
'%s|%s|%s',
[datosContacto.DNI, datosContacto.Nombre, datosContacto.Apellidos]
));
end;
end;

procedure TContactos.GuardarContactos();
begin
if Trim(FRutaBaseDatos) = EmptyStr then
FRutaBaseDatos := ExtractFilePath(ParamStr(0))+RUTA_POR_DEFECTO_BASE_DATOS;
FContenidoBaseDatos.SaveToFile(FRutaBaseDatos);
end;

function TContactos.ExisteContacto(const datosContacto: TContacto): boolean;
begin
Result := FContenidoBaseDatos.IndexOf(datosContacto.DNI) = -1;
end;

end.



Ok gracias.

ecfisa
03-07-2014, 17:54:22
Hola eennzzoo.

Yo también había pensado en una opción similar a la publicada por dec.

.h:

#ifndef Unit2H
#define Unit2H

#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>

class Cliente {

private:
String FNombre;
String FApellido;
String FDni;
String FFileName;
TStrings *FTS;

public:
Cliente();
__property String Nombre = { read = FNombre, write = FNombre };
__property String Apellido = { read = FApellido, write = FApellido };
__property String Dni = { read = FDni, write = FDni };
__property String FileName = { read = FFileName, write = FFileName };
bool Open();
bool GetData(const String Dni);
bool Delete(const String Dni);
bool Save();
~Cliente();
};

#endif


.cpp

#pragma hdrstop
#include "Unit2.h"
#pragma package(smart_init)

Cliente::Cliente()
{
FTS = new TStringList;
}

bool Cliente::Open()
{
FTS->LoadFromFile(FFileName);
return FileExists(FFileName);
}

bool Cliente::GetData(const String Dni)
{
int p = FTS->IndexOf(Dni);
if (p != -1) {
FNombre = FTS->Strings[p-2];
FApellido = FTS->Strings[p-1];
FDni = FTS->Strings[p];
return true;
} else {
MessageBox(0,"Cliente no encontrado", "", MB_ICONERROR);
return false;
}
}

bool Cliente::Delete(const String Dni)
{
int p = FTS->IndexOf(Dni);
bool r = false;
if (p == -1)
MessageBox(0,"Cliente no encontrado", "", MB_ICONERROR);
else if (MessageBox(0, "¿ Borra el cliente ?","",MB_YESNO+MB_ICONQUESTION)==IDYES) {
FTS->Delete(p);
r = true;
}
return r;
}

bool Cliente::Save()
{
if (FNombre.IsEmpty() || FApellido.IsEmpty() || FDni.IsEmpty()) {
MessageBox(0,"Faltan uno o mas datos requeridos", "", MB_ICONERROR);
return false;
} else if (FTS->IndexOf(FDni)!= -1) {
MessageBox(0,"Cliente existente", "", MB_ICONERROR);
return false;
} else {
FTS->Add(FNombre);
FTS->Add(FApellido);
FTS->Add(FDni);
FTS->SaveToFile(FFileName);
return true;
}
};

Cliente::~Cliente()
{
delete FTS;
}


Ejemplo de uso:

...
#include "Unit2.h"
...

Cliente *cl;

void __fastcall TForm1::FormCreate(TObject *Sender)
{
cl = new Cliente();
cl->FileName = "cliente.txt"; /* ruta+nombre de archivo */
cl->Open();
}

void __fastcall TForm1::btnShowClick(TObject *Sender)
{
if (cl->GetData(Edit1->Text)) {
edNom->Text = cl->Nombre;
edApe->Text = cl->Apellido;
edDni->Text = cl->Dni;
}
}

void __fastcall TForm1::btnDeleteClick(TObject *Sender)
{
if (cl->Delete(Edit1->Text)) {
edNom->Clear();
edApe->Clear();
edDni->Clear();
}
}

void __fastcall TForm1::btnSaveClick(TObject *Sender)
{
cl->Save();
}
...

Espero que de las dos sugerencias puedas sacar ideas para implementar tu clase.

Saludos :)

eennzzoo
03-07-2014, 17:59:23
Hola eennzzoo.

Yo también había pensado en una opción similar a la publicada por dec.

.h:

#ifndef Unit2H
#define Unit2H

#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>

class Cliente {

private:
String FNombre;
String FApellido;
String FDni;
String FFileName;
TStrings *FTS;

public:
Cliente();
__property String Nombre = { read = FNombre, write = FNombre };
__property String Apellido = { read = FApellido, write = FApellido };
__property String Dni = { read = FDni, write = FDni };
__property String FileName = { read = FFileName, write = FFileName };
bool Open();
bool GetData(const String Dni);
bool Delete(const String Dni);
bool Save();
~Cliente();
};

#endif


.cpp

#pragma hdrstop
#include "Unit2.h"
#pragma package(smart_init)

Cliente::Cliente()
{
FTS = new TStringList;
}

bool Cliente::Open()
{
FTS->LoadFromFile(FFileName);
return FileExists(FFileName);
}

bool Cliente::GetData(const String Dni)
{
int p = FTS->IndexOf(Dni);
if (p != -1) {
FNombre = FTS->Strings[p-2];
FApellido = FTS->Strings[p-1];
FDni = FTS->Strings[p];
return true;
} else {
MessageBox(0,"Cliente no encontrado", "", MB_ICONERROR);
return false;
}
}

bool Cliente::Delete(const String Dni)
{
int p = FTS->IndexOf(Dni);
bool r = false;
if (p == -1)
MessageBox(0,"Cliente no encontrado", "", MB_ICONERROR);
else if (MessageBox(0, "¿ Borra el cliente ?","",MB_YESNO+MB_ICONQUESTION)==IDYES) {
FTS->Delete(p);
r = true;
}
return r;
}

bool Cliente::Save()
{
if (FNombre.IsEmpty() || FApellido.IsEmpty() || FDni.IsEmpty()) {
MessageBox(0,"Faltan uno o mas datos requeridos", "", MB_ICONERROR);
return false;
} else if (FTS->IndexOf(FDni)!= -1) {
MessageBox(0,"Cliente existente", "", MB_ICONERROR);
return false;
} else {
FTS->Add(FNombre);
FTS->Add(FApellido);
FTS->Add(FDni);
FTS->SaveToFile(FFileName);
return true;
}
};

Cliente::~Cliente()
{
delete FTS;
}


Ejemplo de uso:

...
#include "Unit2.h"
...

Cliente *cl;

void __fastcall TForm1::FormCreate(TObject *Sender)
{
cl = new Cliente();
cl->FileName = "cliente.txt"; /* ruta+nombre de archivo */
cl->Open();
}

void __fastcall TForm1::btnShowClick(TObject *Sender)
{
if (cl->GetData(Edit1->Text)) {
edNom->Text = cl->Nombre;
edApe->Text = cl->Apellido;
edDni->Text = cl->Dni;
}
}

void __fastcall TForm1::btnDeleteClick(TObject *Sender)
{
if (cl->Delete(Edit1->Text)) {
edNom->Clear();
edApe->Clear();
edDni->Clear();
}
}

void __fastcall TForm1::btnSaveClick(TObject *Sender)
{
cl->Save();
}
...

Espero que de las dos sugerencias puedas sacar ideas para implementar tu clase.

Saludos :)
Si ahora si, gracias.

dec
03-07-2014, 19:23:13
Hola,

Conste que mi clase de más arriba contiene un error: no destruyo la instancia de "FContenidoBaseDatos". No me he dado cuenta antes.

aguml
03-07-2014, 20:21:59
ecfisa ¿Que es eso de __property? Suena mas a un componente.

ecfisa
03-07-2014, 21:10:35
Hola aguml.

Básicamente una propiedad (http://bcbjournal.org/articles/vol3/9904/Using_properties_in_C_classes.htm?PHPSESSID=9544a0fd673de4d6c5c3b316621b6fe5), es una extensión creada para C++ Builder que permite unificar métodos de acceso y modificación a miembros de una clase. Su uso no es privativo de los componentes.

Cabe aclarar que C++ estandar no incluye el concepto de propiedad y que C++ Builder recibe de la VCL, si tratásemos con ANSI C++ tendríamos que escribir:

class MiClass {
private:
int FValue;
public:
void SetValue(int Value) { FValue = Value; }
int GetValue() { return FValue; }
};


Saludos :)