/*
ProgEx20 -- This is a C++ program and must be set up as such! Save this
file as Main.cpp.
Well, now I've done it! I've dug myself into a hole and now I can't get out!
And how I thought things were going so well with this tutorial! We've covered
basic output using printf(), pointer (byval) and reference parameter passing
mechanisms both in C and C++, implicit and explicit dynamic linking using
both C/C++ and PowerBASIC servers and clients, and now finally structs and how
using them differs in C and C++. I decided that in this tutorial, along with
further use of structs (UDTs), I'd introduce file access in C/C++. I created
anew our Employee struct we've been using for the last two tutorials below,
and decided to show how to write this data in the form of arrays of these
structs to a comma delimited text file. Sounds good huh? Well, the problem
is, if I'm going to show how to write them to a comma delimited text file, I
ought to for the sake of symetry show how to read the data back out of the
text files and reconstitute it in the same form in the Employee structs where
it originally existed. The reading it back out part isn't hard. The hard
part is reconstituting it back to its original form. For you see, C and C++
just don't have the high level built in file handling capacities that Power-
BASIC has. You'll see why momentarily. So I've resigned myself for what I
have to cover. Maybe things will work out afterall. So in this tutorial I'll
show as much as I can about file access, and continue with the discussion of
structs from the last two tutorials. The next couple tutorials are going to
have to be about what I've neglected up until now in C++, and that's classes.
For you see, we have been accumulating problems, and they are piling up.
First, we had the problem of not being able in C or C++ to simply assign a
string to any kind of variable like we would do in PowerBASIC. We've had to
first allocate memory in some kind of buffer, then use strcpy() to copy the
bytes into the buffer. If you've been feeling this is pretty ridiculous
you're in good company!
Now we've run into the problem (or more accurately, I've run into the problem)
of there being no easy way to get some data back out of a file to which it was
written. The answer to all these problems and many more can be found in
C++ classes. So that's what the next few tutorials will be about. But for
now, lets see how far we can get with my original plan. When we can't go any
farther we'll stop, study classes, then pick up where we left off here.
So, in the program below you'll see at top our Employee struct and you'll also
see I didn't use a typedef with it. In C++ you don't need the typedef
statement to be able to create an instance of the UDT like so...
Employee emp;
That's one of the changes made in the C++ language from C. Also in the
program below note I created an array of Employee structs like so...
Employee emp[2];
Array subscripting in C/C++ does not work like in PowerBASIC where the number
in brackets represents the upper bound of the array. In C/C++ the number in
brackets represents the count of elements. What this means is that the above
declaration will create an emp[0] and an emp[1]. There won't be any emp[2].
If you need an emp[2] then your declaration would need to be for three
elements like so...
Employee emp[3];
Differnt from PowerBASIC but logical, not? So down in main() you can see how
I filled both elements with some character string and numeric data.
So now we've got data for two folks in our Employee array of structs, so lets
write the data to a comma delimited text file. There is a struct defined in
stdio.h named FILE. Feel free to open stdio.h in a text editor and examine it
if you like, but don't get concerned if you don't understand it very well.
Using it is fairly easy. To read/write text files using the C runtime library
(the best way to do it in my opinion) you simply need to declare a pointer to
this FILE struct like so...
FILE* fp;
Its actually a better idea to do it like this...
FILE* fp=NULL;
The reason I say this is that we are going to call a function named fopen() to
open a file very much like BASIC's 'Open' statement, and if the function fails
we can test for a NULL. If the function succeeds we'll have a valid file
pointer in fp. The statement to open a file named "Data.dat" in the current
directory for writting only (OUTPUT in basic speak) is...
fp=fopen("Data.dat","w");
The "w" stands for 'writing'. For read operations you use "r". Fairly basic
really, even though it isn't BASIC! By the way, this only applies to text
files. Binary files, which I havn't gotten to yet, require a "b".
*/
#include <stdio.h>
#include <string.h>
struct Employee //Same as Type Employee
{
char szName[32];
char szAddress[32];
char szCity[16];
char szState[16];
char szCountry[16];
char szZipCode[16];
unsigned int iAge;
unsigned int iEmpNum;
double dblSalary;
}; //End Type
void Initialize(Employee* pEmp)
{
strcpy(pEmp[0].szName,"Martin Veneski"); //1st employee
strcpy(pEmp[0].szAddress,"1016 Wabash Street");
strcpy(pEmp[0].szCity,"Shamokin");
strcpy(pEmp[0].szState,"PA");
strcpy(pEmp[0].szCountry,"USA");
strcpy(pEmp[0].szZipCode,"17872");
pEmp[0].iAge=23;
pEmp[0].iEmpNum=123456;
pEmp[0].dblSalary=45000;
strcpy(pEmp[1].szName,"Raymond Latchkoski"); //2nd employee
strcpy(pEmp[1].szAddress,"1624 Tioga Street");
strcpy(pEmp[1].szCity,"Shamokin");
strcpy(pEmp[1].szState,"PA");
strcpy(pEmp[1].szCountry,"USA");
strcpy(pEmp[1].szZipCode,"17872");
pEmp[1].iAge=25;
pEmp[1].iEmpNum=789123;
pEmp[1].dblSalary=50000;
}
int main()
{
char szBuffer[256];
Employee emp[2];
FILE* fp;
Initialize(emp);
fp=fopen("Data.dat","w"); //Same as Open "Data.dat" For Output As #fp
for(unsigned int i=0; i<sizeof(emp)/sizeof(emp[0]); i++) //For i=0 To 1
{
fprintf //Print #fp, ...
(
fp,
"%s,%s,%s,%s,%s,%s,%u,%u,%6.2f\n",
emp[i].szName,emp[i].szAddress,emp[i].szCity,emp[i].szState,
emp[i].szCountry,emp[i].szZipCode,emp[i].iAge,emp[i].iEmpNum,
emp[i].dblSalary
);
}
fclose(fp);
fp=fopen("Data.dat","r"); //Same as Open "Data.dat" For Input As #fp
for(unsigned int i=0; i<2; i++) //Same as For i=0 To 1
{
fgets(szBuffer,256,fp); //Same As Line Input #fp, szBuffer
printf("%s",szBuffer); //Same as Print szBuffer
}
fclose(fp); //Same as Close #fp
getchar();
return 0;
}
/* --Output--
=============================================================================
Martin Veneski,1016 Wabash Street,Shamokin,PA,USA,17872,23,123456,45000.00
Raymond Latchkoski,1624 Tioga Street,Shamokin,PA,USA,17872,25,789123,50000.00
*/