How to create a function that returns a whole structure in C++ Builder 6?

J

Jimakos Bilakis

Hi guys!

I'm using the C++ Builder 6 Enterprise Edition where I create some
tables in Paradox and with the help of a structure i pass my data from
the form (Edit boxes) to the Paradox table with a speedbutton. (I am
also using several data modules where i keep all my tables and
queries).

First of all i need some "mechanism" to read the data from the tables
and also to be able to change these already stored values. I tried with

some DBEdit boxes...but it didn't work. It seems that at run time, when

i press Enter, the value that the user enters pass to the table without

letting me check the validity of user's values.

Is there any way to fix that?

If not, i thought of a way with a structure.
In the data module, in the header sheet ("project name".h) i have
(right down the public:) the struct:

struct PinSynt
{
int SyntAA;
AnsiString SyntKathg;
AnsiString SyntAKK;
float SyntSynt;
AnsiString SyntParat;
};

I'm trying to create a function that it will return whole structure. If

i do that, i'll replace the DBedits with Edits, as i'll pass the values

of my fields in the edits (as they do now with the DBedits).
Just below my struct, I'm writing:

struct PinSynt FunctionRead (int SyntAAKey); // where SyntAAKey =
Primary key

I compile the code, evething's ok. (Build All)

Now in the *.cpp sheet, i'm trying to write:

struct PinSynt TDM_Pinakas_Syntelestvn::FunctionRead (int SyntAAKey);
// where DM_Pinakas_Syntelestvn -> the name of my Data module.
{
struct PinSynt Help; // another struct of the same type for
help.

Query1->Close();
Query1->SQL->Clear();
// * SQL statements*//
//------------------------------//
// some code with if and other statements....//

return Help; // Help = whole structure.
}

Now if i compile the code...an error will occur:
'TDM_Pinakas_Syntelestvn::FunctionRead(int)' is not a member of
'TDM_Pinakas_Syntelestvn'

I'm trying again this way:

struct TDM_Pinakas_Syntelestvn::pinSynt FunctionRead (int SyntAAKey);
// where DM_Pinakas_Syntelestvn -> the name of my Data module.
{
struct PinSynt Help; // another struct for help.

Query1->Close();
Query1->SQL->Clear();
// * SQL statements*//
//------------------------------//
// some code with if and other statements....//

return Help;
}

Now several errors occur:

- Undefined structure 'PinSynt'
- Size of 'StructRead' is unknown or zero
- Undefined symbol 'Query1'
- and every single variable that has to do with my struct PinSynt (i.e.

Help.SyntAA, Help.SyntKathg etc.)

i tried several times but nothing so far. My last try was:

//-------- .h sheet ----------//
PinSynt FunctionRead (int SyntAAKey); // where SyntAAKey = Primary key

//-------- .cpp sheet ---------//
PinSynt TDM_Pinakas_Syntelestvn::FunctionRead (int SyntAAKey);
// or TDM_Pinakas_Syntelestvn::pinSynt FunctionRead (int SyntAAKey);
// or PinSynt FunctionRead (int SyntAAKey);
// it's always the same error!!! ===> Declaration syntax error
{
// the same code
}

I would be grateful if you could write a few lines of code so that i
could understand how i can create a function that returns a whole
structure.

Thanks in advance and please forgive my English..:)
 
J

John Carson

Jimakos Bilakis said:
Hi guys!

I'm using the C++ Builder 6 Enterprise Edition where I create some
tables in Paradox and with the help of a structure i pass my data from
the form (Edit boxes) to the Paradox table with a speedbutton. (I am
also using several data modules where i keep all my tables and
queries).

First of all i need some "mechanism" to read the data from the tables
and also to be able to change these already stored values. I tried
with

some DBEdit boxes...but it didn't work. It seems that at run time,
when

i press Enter, the value that the user enters pass to the table
without

letting me check the validity of user's values.

Is there any way to fix that?

If not, i thought of a way with a structure.
In the data module, in the header sheet ("project name".h) i have
(right down the public:) the struct:

struct PinSynt
{
int SyntAA;
AnsiString SyntKathg;
AnsiString SyntAKK;
float SyntSynt;
AnsiString SyntParat;
};

I'm trying to create a function that it will return whole structure.
If

i do that, i'll replace the DBedits with Edits, as i'll pass the
values

of my fields in the edits (as they do now with the DBedits).
Just below my struct, I'm writing:

struct PinSynt FunctionRead (int SyntAAKey); // where SyntAAKey =
Primary key

I compile the code, evething's ok. (Build All)

Now in the *.cpp sheet, i'm trying to write:

struct PinSynt TDM_Pinakas_Syntelestvn::FunctionRead (int SyntAAKey);
// where DM_Pinakas_Syntelestvn -> the name of my Data module.
{
struct PinSynt Help; // another struct of the same type for
help.

Query1->Close();
Query1->SQL->Clear();
// * SQL statements*//
//------------------------------//
// some code with if and other statements....//

return Help; // Help = whole structure.
}

Now if i compile the code...an error will occur:
'TDM_Pinakas_Syntelestvn::FunctionRead(int)' is not a member of
'TDM_Pinakas_Syntelestvn'

The C++ standard does not define "Data module" and I don't know what you
mean by it.

You should only be using TDM_Pinakas_Syntelestvn::FunctionRead if

1. FunctionRead is a member of a class or struct or namespace called
TDM_Pinakas_Syntelestvn, and
2. you are defining the function outside the scope of the
class/struct/namespace, having previously declared it inside the
class/struct declaration or within the scope of the namespace.

Your declaration of FunctionRead means that it is not a member of a class or
struct and I would hazard a guess that namespaces are not being used either.
Accordingly, your declaration and definition are inconsistent. I could go
on, but I suspect that some time spent studying a C++ textbook is called for
here.
I'm trying again this way:

struct TDM_Pinakas_Syntelestvn::pinSynt FunctionRead (int SyntAAKey);
// where DM_Pinakas_Syntelestvn -> the name of my Data module.
{
struct PinSynt Help; // another struct for help.

Query1->Close();
Query1->SQL->Clear();
// * SQL statements*//
//------------------------------//
// some code with if and other statements....//

return Help;
}
Now several errors occur:

- Undefined structure 'PinSynt'
- Size of 'StructRead' is unknown or zero
- Undefined symbol 'Query1'
- and every single variable that has to do with my struct PinSynt
(i.e.

Help.SyntAA, Help.SyntKathg etc.)

i tried several times but nothing so far. My last try was:

//-------- .h sheet ----------//
PinSynt FunctionRead (int SyntAAKey); // where SyntAAKey = Primary key

//-------- .cpp sheet ---------//
PinSynt TDM_Pinakas_Syntelestvn::FunctionRead (int SyntAAKey);
// or TDM_Pinakas_Syntelestvn::pinSynt FunctionRead (int SyntAAKey);
// or PinSynt FunctionRead (int SyntAAKey);
// it's always the same error!!! ===> Declaration syntax error
{
// the same code
}

I would be grateful if you could write a few lines of code so that i
could understand how i can create a function that returns a whole
structure.


You need to read a good C++ textbook, not engage in random experimentation.
Returning a struct from a function is trivial. You just define it and return
it. That is not your problem. Your problem is you don't understand the
difference between

1. members variables and functions,

and

2. non-member variables and functions.
 
S

Simon Elliott

First of all i need some "mechanism" to read the data from the tables
and also to be able to change these already stored values. I tried
with
some DBEdit boxes...but it didn't work. It seems that at run time,
when
i press Enter, the value that the user enters pass to the table
without
letting me check the validity of user's values.

Is there any way to fix that?

AFAIK not. I usually use a text box and save my data via ADO. This
gives flexibility in validation, and allows me to connect my app to any
SQL DBMS. The people over at the borland newsgroups may have more
details on this: you'll need to point your newsreader at
newsgroups.borland.com
struct PinSynt
{
int SyntAA;
AnsiString SyntKathg;
AnsiString SyntAKK;
float SyntSynt;
AnsiString SyntParat;
};

struct PinSynt FunctionRead (int SyntAAKey); // where SyntAAKey =
Primary key

This is a standalone function...
Now in the *.cpp sheet, i'm trying to write:

struct PinSynt TDM_Pinakas_Syntelestvn::FunctionRead (int SyntAAKey);

BTW, you should lose the semicolon here, and you don't need the
'struct' keyword.
Now if i compile the code...an error will occur:
'TDM_Pinakas_Syntelestvn::FunctionRead(int)' is not a member of
'TDM_Pinakas_Syntelestvn'

.... but you're now trying to define FunctionRead as a member of the
class TDM_Pinakas_Syntelestvn.

There are several ways of doing what you're attempting. Here's how I
would do it:

In the header file where class TDM_Pinakas_Syntelestvn is defined:

struct PinSynt
{
int SyntAA;
AnsiString SyntKathg;
AnsiString SyntAKK;
float SyntSynt;
AnsiString SyntParat;
};

Find the "class TDM_Pinakas_Syntelestvn" and add this to the public
section:

bool FunctionRead (int SyntAAKey, PinSynt& pinSynt);

In the .cpp file where the methods of class TDM_Pinakas_Syntelestvn are
defined:

bool TDM_Pinakas_Syntelestvn::FunctionRead (int SyntAAKey, PinSynt&
pinSynt)
{
bool result = false;
// perform the SQL query to find SyntAAKey
if (!(Query->Bof && Query->Eof))
{
Query->First();
pinSynt.SyntAA = Query->FieldByName("SyntAA")->AsInteger;
pinSynt.SyntKathg = Query->FieldByName("SyntKathg")->AsString;
// etc for the other fields
result = true;
}
return(result)
}

When you want to call this function to get your data from the database,
you can only call it where you've got an instance of
TDM_Pinakas_Syntelestvn. Let's say this is called myPinakasSyntelestvn
(I think that by default if this is your data module BCB6 creates an
instance for you, probably called DM_Pinakas_Syntelestvn. Once you've
got to grips with this, you probably want to manage the lifecycle of
your data modules yourself. In BCB6 you can only create a data module
on the heap, so myPinakasSyntelestvn must be a pointer.)

PinSynt myPinSynt;
if (myPinakasSyntelestvn->FunctionRead(42, myPinSynt))
{
// You got the data. Do something with it, eg:
mytextbox->Text = pinSynt.SyntKathg;
}
else
{
// do something with the error
}

I haven't compiled any of the above, so there may be the odd typo, but
the basics are there.
 
N

Nikolay Moskvichev

Jimakos said:
First of all i need some "mechanism" to read the data from the tables
and also to be able to change these already stored values. I tried with

look at TDataSet::Insert TDataSet::Edit TDataSet::FieldByName,
TDataSet::Fields TDataSet::post
some DBEdit boxes...but it didn't work. It seems that at run time, when

i press Enter, the value that the user enters pass to the table without

letting me check the validity of user's values.

Is there any way to fix that?

look at TDataSet::BeforePost and other TDataSet events
 
J

Jimakos Bilakis

Firstly John, you're right i need more study! I'm only at the begging
as i don't have more than 4 - 6 months since i started to create my own
projects.

Then again, Simon, you saved me!!.. :)

Yes my mistake the semicolon! I don't write it in my code. Thanks for
your advise for the keyword struct BTW. I have erased it as well.

Yes, DM_Pinakas_Syntelestvn is the name.

No more annoying errors... Actually I would like to ask you:

Where exactly do you mean? Published, private or public? Here is what i
wrote in my code (in the .h sheet):

#ifndef Promier_DM_Pinakas_SyntelestvnH
#define Promier_DM_Pinakas_SyntelestvnH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <DB.hpp>
#include <DBTables.hpp>

class TDM_Pinakas_Syntelestvn : public TDataModule
{
__published: // IDE-managed Components ====> First
TQuery *QueryAA;
TQuery *QueryInsert;
TTable *PinakasSynt;
TQuery *QueryExists;
TQuery *QueryUpdate;
TSmallintField *PinakasSyntSynt_AA;
TStringField *PinakasSyntSynt_Kathg;
TStringField *PinakasSyntSynt_AKK;
TFloatField *PinakasSyntSynt_Synt;
TStringField *PinakasSyntSynt_Parat;
TQuery *QueryRead;
private: // User declarations
public: // User declarations
__fastcall TDM_Pinakas_Syntelestvn(TComponent* Owner);

// --- * --- * --- * --- * --- V A R I A B L E S --- * --- * --- * ---
*--- //
struct PinSynt
{
int SyntAA;
AnsiString SyntKathg;
AnsiString SyntAKK;
float SyntSynt;
AnsiString SyntParat;
};
// --- * --- * --- * --- * --- F U N C T I O N S --- * --- * --- * ---
*--- //
// variable functions of mine //

bool FunctionRead (int SyntAAKey, PinSynt& PinSyntRef);
};
//---------------------------------------------------------------------------
extern PACKAGE TDM_Pinakas_Syntelestvn *DM_Pinakas_Syntelestvn;
//---------------------------------------------------------------------------
#endif

Is that ok? Following your steps i wrote in .cpp file:

bool TDM_Pinakas_Syntelestvn::FunctionRead (int SyntAAKey, PinSynt&
PinSyntRef)
{
bool Result = false;

QueryRead->Close();
QueryRead->SQL->Clear();
QueryRead->SQL->Add(" SELECT * ");
QueryRead->SQL->Add(" FROM Promier_Syntelestes.DB ");
QueryRead->SQL->Add(" WHERE Synt_AA = " + IntToStr(SyntAAKey));
QueryRead->Prepare();
QueryRead->Open();

if (!(QueryRead->Bof && QueryRead->Eof))
{
QueryRead->First();
PinSyntRef.SyntAA =
QueryRead->FieldByName("Synt_AA")->AsInteger;
PinSyntRef.SyntKathg =
QueryRead->FieldByName("Synt_Kathg")->AsString;
PinSyntRef.SyntAKK =
QueryRead->FieldByName("Synt_AKK")->AsString;
PinSyntRef.SyntSynt =
QueryRead->FieldByName("Synt_Synt")->AsFloat;
PinSyntRef.SyntParat =
QueryRead->FieldByName("Synt_Parat")->AsString;

Result = true;
}
else
Result = false;

QueryRead->Close();

return Result;
}

Everything works fine.

Now I'm trying something else.
In the main form, i have a DBGrid and a PageControl with 2 tabs The
first for changing (TabSheet0) and the second for adding (TabSheet1)
values. The whole idea is when the user wants to change some of the
already stored values to do it with a simple click in the first Tab of
PageControl (TabSheet0). There he can click on any DBGrid's cell and
the values of the record to pass through the FunctionRead to the right
Edit Boxes. So far i wrote:

void __fastcall TPinakas_Syntelestvn::DBGrid1CellClick(TColumn *Column)
{
struct TDM_Pinakas_Syntelestvn::pinSynt StructRef;

if (DM_Pinakas_Syntelestvn->FunctionRead(StructRef.SyntAA,
StructRef))
{
Edit11->Text = StructRef.SyntKathg;
Edit12->Text = StructRef.SyntAKK;
Edit13->Text = StructRef.SyntSynt;
Edit14->Text = StructRef.SyntParat;
}
}

I know that it doesn't make sense, i'm still working on it. The problem
is that no matter which cell i press on (at run-time), i can only see
the first's record values!
I want every time i press a cell (and that cell belongs to a different
record), my Edit boxes to display the right values.

Thanks so much again!
 
S

Simon Elliott

Where exactly do you mean? Published, private or public?

That kind of depends where you want the function to be called from. If
you don't understand public, private or protected, one option is to
read Bruce Eckel's "Thinking in C++", available free at
http://mindview.net/Books/TICPP/ThinkingInCPP2e.html

There's also an excellent C++ FAQ at
http://www.parashift.com/c++-faq-lite/

However, as you've noticed, there's also a __published section in your
class. This is an extension to C++ which is specific to Borland C++
Builder. There are one or two other extensions in BCB, and a lot of
concepts you'll need to get to grips with which are more BCB than C++.
This is why I suggested that you consider posting in the Borland
newsgroups.

BCB is a good way of quickly writing W32 apps, but you will have to get
to grips with C++ and quite a few BCB concepts!
Here is what
i wrote in my code (in the .h sheet):
[snip]

class TDM_Pinakas_Syntelestvn : public TDataModule [snip]
public: // User declarations [snip]
struct PinSynt
{
int SyntAA;
AnsiString SyntKathg;
AnsiString SyntAKK;
float SyntSynt;
AnsiString SyntParat;
};

You've defined the type PinSynt within the class
TDM_Pinakas_Syntelestvn. This may or may not be what you want,
depending on where you plan to use this type.
QueryRead->SQL->Add(" SELECT * ");
QueryRead->SQL->Add(" FROM Promier_Syntelestes.DB ");
QueryRead->SQL->Add(" WHERE Synt_AA = " +
IntToStr(SyntAAKey)); QueryRead->Prepare();

Not a C++ issue, but consider using query parameters here: it may
improve performance.

[snip DBGrid problem]
This is probably better asked in the Borland groups: then instead of
getting just my opinions, you'll get answers from lots of BCB
developers and TeamB (unpaid Borland semi official support). And we
won't irritate the huge number of C++ developers on comp.lang.c++ who
don't use BCB!

See http://info.borland.com/newsgroups/
 
J

Jimakos Bilakis

Thanks again for your opinions and for your valuable help. I'll try to
post my problems in the Borland newsgroups. Sorry if i bothered you and
thank you for your time to apply to my post!
 
S

Simon Elliott

Thanks again for your opinions and for your valuable help. I'll try to
post my problems in the Borland newsgroups. Sorry if i bothered you
and thank you for your time to apply to my post!

Not at all: I just thought it worthwhile to direct you to the
newsgroups where I've received much valuable assistance myself.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,981
Messages
2,570,187
Members
46,730
Latest member
AudryNolan

Latest Threads

Top