Modified source listing for my program using strtok_r in which I make a
local copy of the input string and operate strtok on that
// Program that parses strings of the form:
// Name, SS#, Emp#, Other#::Name, SS#, Emp#, Other#::Name, SS#, Emp#,
Other#
// and extracts the name and other attributes associated with an
employee
#include <stdio.h>
#include <iostream.h>
#include <fstream.h>
#include <list.h>
extern "C" char *strtok_r(char *s1, const char *s2, char **lasts);
#define MAX_DATA_LEN 128
#define EMPLOYEE_DELIMITER_STR ":"
#define ATTR_DELIMITER_STR ","
#define ATTR_DELIMITER_CHAR ','
struct EmployeeInfo
{
char _name[MAX_DATA_LEN];
size_t _attributeCount;
size_t *_attribute;
EmployeeInfo(const char *str):_attributeCount(0), _attribute(NULL)
{
if(!strstr(str,ATTR_DELIMITER_STR))
strcpy(_name, str);
else
{
char *temp1 = new char[strlen(str) + 1];
strcpy(temp1, str);
char *temp2 = temp1;
char* holdingBuf[1];
strcpy(_name, strtok_r(temp1, (const char *) ATTR_DELIMITER_STR,
holdingBuf));
temp1 += (strlen(temp1) + 1);
_attributeCount = numChars(temp1, ATTR_DELIMITER_CHAR) + 1;
_attribute = new size_t[_attributeCount];
memset(_attribute, '\0', _attributeCount*sizeof(*_attribute));
char* stringWithTokens = temp1;
char* token;
int i;
for(i =0;(token = strtok_r(stringWithTokens, (const char *)
ATTR_DELIMITER_STR, holdingBuf)) != NULL;
i++)
{
stringWithTokens = NULL;
_attribute = atoi(token);
}
_attributeCount = i;
delete [] temp2;
}
}
virtual ~EmployeeInfo()
{
if(_attributeCount) delete [] _attribute;
}
void toString()
{
cout << "\nEmployee Name: " << _name << endl;
for(size_t i = 0; i < _attributeCount; i++)
cout << "Attribute " << i << ": " << _attribute << endl;
}
protected:
static size_t numChars(const char* str, const char delimiter)
{
size_t retVal = 0;
char ch;
for(size_t i = 0; ch = str; i++)
{
if(ch == delimiter)
retVal++;
}
return retVal;
}
};
void
parseNameString(const char* nameString)
{
char *temp1 = new char[strlen(nameString) + 1];
strcpy(temp1, nameString);
char *temp2 = temp1;
char* holdingBuf[1];
list<EmployeeInfo*> empInfoList;
char* stringWithTokens = temp1;
char* token;
while((token = strtok_r(stringWithTokens, (const char *)
EMPLOYEE_DELIMITER_STR, holdingBuf)) != NULL)
{
stringWithTokens = NULL;
EmployeeInfo *newInfo = new EmployeeInfo(token);
empInfoList.push_back(newInfo);
}
delete [] temp2;
list<EmployeeInfo*>::iterator itor, endOfList=empInfoList.end();
for(itor = empInfoList.begin(); itor != endOfList; itor++)
{
EmployeeInfo* thisInfo = *itor;
thisInfo->toString();
}
for(itor = empInfoList.begin(); itor != endOfList; itor++)
{
EmployeeInfo* thisInfo = *itor;
delete thisInfo;
}
}
int
main(int argc, char* argv[])
{
if(argc < 2)
{
cerr << "usage: " << argv[0] << " <inputfile>. Exiting ...." <<
endl;
exit(-1);
}
ifstream inFile(argv[1]);
if(!inFile)
{
cerr << "Error reading file " << argv[1] << " Exiting ...." <<
endl;
exit(-2);
}
char inputStr[MAX_DATA_LEN + 1];
/*
while(inFile >> inputStr)
{
cout << "** Parsing string " << inputStr << " **\n\n";
parseNameString(inputStr);
cout << "\n\n\n";
}
*/
while(inFile.getline(inputStr, MAX_DATA_LEN))
{
cout << "** Parsing string " << inputStr << " **\n\n";
parseNameString(inputStr);
cout << "\n\n\n";
}
exit(0);
}