Strings.cpp & Strings.h are available in the attached zip file (as is the file below - Main.cpp).
/*
ProgEx34 -- Back To ProgEx20 And The Problem We Had Re-Constituting comma
delimited file data Into The struct It Came From.
The program below is a 'doctored up' version of ProgEx20 where we ran into
some ugly C string issues which I hope we've finally solved by delving into
the domain of creating a String Class. See my narrative below in the code.
*/
#include <stdio.h>
#include <string.h>
#include "Strings.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];
String strEmp(256);
String* pEmp=NULL;
Employee emp[2];
int iCnt=0;
FILE* fp;
/*
This 1st block of code simply loads the Employee struct array and then
writes the data to a comma delimited text file using fprintf.
*/
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);
/*
In this block of code we first zero out our Employee array emp[]. I usually
use memset() for that, although there is also a ZeroMemory function, but its
not in any of the C Runtime Libraries.
Next we re-open Data.dat and read each line out into our szBuffer char array
using gets (Get String). Note that we declared a simple String object at the
top of main() like so...
String strEmp(256);
You have not seen me do that yet with our String Class which we so laborously
developed in the past several Program Examples. What that is is an example
of constructing a String object with a pre-set buffer size. If you examine
the various String Class Constructor overloads you'll see one that instead of
taking a char or char* or String as the basis for creating (constructing) a
new String, there is one for creating a String with a specific buffer size.
This could come in handy if as the writer of a program you know in advance
the approximate sizes of the String data you'll be dealing with, and rather
than allowing the default String Class behavior of re-allocating and
releasing memory as the Strings encountered shrink or grow, you decide in
advance to just allocate a buffer big enough to handle the largest String you
expect to encounter. So the above String declaration will cause a call to
the String Constructor that takes an integer parameter (size of requested
buffer to allocate).
Next we simply parse the String read out of the file in exactly the same
manner as we did in ProgEx33 where we introduced Parse. Note that I created
a String* (String Pointer) variable named pEmp...
String* pEmp=NULL;
to hold the parsed out Strings. Since the Employee struct contains only
primitive asci character strings of various sizes, we unfortunately need to
use strcpy() to move the bytes in the parsed out Strings into the struct.
That is what most of the code bulk below is doing. You might also note I had
to add another member to our String Class in this example because it was
missing a way to create a floating point double out of a String, and we
needed that for the Salary member of the struct. After the loop is finished
reading the file data back into the array of structs, delete [] is called on
pEmp.
*/
memset(emp,0,sizeof(emp)*2); //zero out 2 emp structs
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
strEmp=szBuffer; //Assign szBuffer To strEmp. Will trigger operator=
strEmp.Print(false); //Print data read from file through String. Already has \n in it
iCnt=strEmp.ParseCount(','); //Find out how many comma delimited Strings
pEmp=new String[iCnt]; //Create a String on the heap for each one
strEmp.Parse(pEmp,','); //Parse the Strings into pEmp[]
strcpy(emp[i].szName,pEmp[0].lpStr()); //This is awkward but the Employee struct does not
strcpy(emp[i].szAddress,pEmp[1].lpStr()); //contain dynamic strings or String objects, so
strcpy(emp[i].szCity,pEmp[2].lpStr()); //strcpy (byte copy type operation) is necessary
strcpy(emp[i].szState,pEmp[3].lpStr()); //to copy bytes into struct.
strcpy(emp[i].szCountry,pEmp[4].lpStr());
strcpy(emp[i].szZipCode,pEmp[5].lpStr());
emp[i].iAge=pEmp[6].iVal();
emp[i].iEmpNum=pEmp[7].iVal();
emp[i].dblSalary=pEmp[8].dblVal();
delete [] pEmp;
}
fclose(fp); //Same as Close #fp
/*
In this block of code we simply iterate through our array of Employee structs
and output the data to the screen with printf. This data was originally put
in the Employee structs in Initialize(), but remember we wrote the structs
out to a comma delimited text file, zeroed out the Employee structs, then
read the data back in. It is that data read back in to the Employee structs
that is being output here and as seen below in the output.
*/
for(unsigned int i=0; i<sizeof(emp)/sizeof(emp[0]); i++) //For i=0 To 1
{
printf //Print #fp, ...
(
"\n%s\n%s\n%s\n%s\n%s\n%s\n%u\n%u\n%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
);
}
getchar();
return 0;
}
/*
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
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
*/