Parsing Tab Delimited Text in C++ using variadic functions
A classic problem within any programming language is parsing a tab delimited line of text. Some languages do this very well; traditionally C++ does not in that functions such as scanf while superficially allowing this to be done, has a number of specific problems eg handling blank columns, ie two successive tabs with no text in between
The variadic functions in C++ provides a new way of solving this problem. I have created a parse function using variadic functions which parses a tab delimited string in a buffer and puts the results into a set of variables which can be either strings or integers, as determined by the variable types. It does not modify the contents of the buffer.
parse(buffer,string1,string2,int1,int2,string3,...);
The code sets integers associated with blank columns to 0 and strings associated with blank to zero length strings. If the line does not contain sufficient tab separated items of data then the remaining values are set to the blank column values. The structure is easy to extent to use different separators and take different actions in the case of empty columns.
// For handling integers
void parseval(const char * start,int & value,int len)
{
if (len)
value = atoi(start);
else
value = 0;
}
// For handling strings
void parseval(const char * start,string & value,int len)
{
value.assign(start,len);
}
// A dummy method which is called when there are no further columns to process
void parse (const char * start) {}
// The function itself, which is called recursively, each time peeling off and processing one entry
// from the tab delimited line. Once the string is exhausted the start pointer is left on the terminating null and this
// calls the parseval method with the length set to zero, simulating an empty column
template <typename First,typename... Rest>
void parse (const char * start,First & first,Rest& ... rest)
{
if (start)
{
// Look for the next delimiter.
size_t len = strcspn(start,"\t");
parseval(start,first,len);
// move the curser
start += len;
// If we have not reached the end of the string move to the next entry.
if (*start) start++;
}
else
parseval(start,first,0);
parse(start,rest...);
}
The following shows an example of how it can be used
string string1, string2, string3;
int int1, int2;
while (!feof(fin)) {
fgets(buffer, BUFFLEN, fin);
parse(buffer,string1,string2,int1,int2,string3);
... Process values
}
Note that C++ 2011 variadic templates are not supported in Visual C++ 2012, but are supported if the November 2012 CTP compiler is installed and selected
http://www.microsoft.com/en-us/download/details.aspx?id=35515