1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
// cl C_Parse.cpp /O1 /Os /MT /EHsc /D "_CRT_SECURE_NO_WARNINGS"
#include <cstdlib>
#include <cstdio> // 122,368 Bytes With Microsoft Libraries
#include <string> // 4,608 Bytes With TCLib.lib
size_t iParseCount(const wchar_t* pString, wchar_t cDelimiter)
{
int iCtr=0; //reflects # of strings delimited by delimiter.
const wchar_t* p;
p=pString;
while(*p)
{
if(*p==cDelimiter)
iCtr++;
p++;
}
return ++iCtr;
}
void Parse(wchar_t** pStrings, const wchar_t* pDelimitedString, wchar_t cDelimiter, int iParseCount)
{
wchar_t* pBuffer=NULL; // In Parse() we receive a wchar_t** (pointer to pointer)
const wchar_t* c; // buffer large enough to hold pointers to iParseCount
wchar_t* p; // number of strings delimited by cDelimiter. The logic
size_t i=0; // used here is to create a secondary buffer as large as
// the string passed in the 2nd parameter, i.e.,
pBuffer=(wchar_t*)malloc // pDelimiterString, then work through the pDelimitedString
( // buffer with a while loop copying characters from
wcslen(pDelimitedString)*2+2 // pDelimitedString to our new buffer - pBuffer, one
); // character at a time. When a delimiter is hit as
if(pBuffer) // specified by cDelimiter, place a null byte in pBuffer
{ // instead of the delimiter so as to null terminate that
pBuffer[0]=0; // string. The end result of this process of running through
p=pBuffer; // pDelimitedString and substituting nulls in place of
c=pDelimitedString; // the delimiter in pBuffer is to create an array of null
while(*c) // terminated strings in pBuffer. The final part of the
{ // algorithm simply needs to collect all those strings
if(*c==cDelimiter) // from pBuffer, and place pointers to them in our wchar_t**
*p=0; // pStrings buffer. Of course, an individual memory alloc-
else // ation with malloc will be needed for each delimited string.
*p=*c; // Then the temporary pBuffer must be released here. All the
p++, c++; // memory allocations for everything will have to be unwound
} // in main().
*p=0, p=pBuffer;
for(int i=0; i<iParseCount; i++)
{
pStrings[i]=(wchar_t*)malloc(wcslen(p)*2+2);
wcscpy(pStrings[i],p);
p=p+wcslen(pStrings[i])+2;
}
free(pBuffer);
}
}
void LTrim(wchar_t* pStr)
{
size_t iCt=0, iLen=0;
iLen=wcslen(pStr);
for(size_t i=0; i<iLen; i++)
{
if(pStr[i]==32 || pStr[i]==9)
iCt++;
else
break;
}
if(iCt)
{
for(size_t i=iCt; i<=iLen; i++)
pStr[i-iCt]=pStr[i];
}
}
int main()
{
wchar_t szString[]=L"Zero . One . Two . Three . Four . Five";
wchar_t** pStrs=NULL;
size_t iStrings;
iStrings=iParseCount(szString, L'.'); // First have to allocate pStrs buffer, which is a pointer
pStrs=(wchar_t**)malloc(iStrings*sizeof(wchar_t*)); // to pointer buffer (wchar_t**) to hold six wchar_t* pointers
if(pStrs) // to the individual strings to be parsed, i.e., "Zero", "One",
{ // etc. Then call Parse() function passing in the pStrs **
Parse(pStrs,szString,L'.',iStrings); // buffer, the delimiter character, and the result of ParseCount.
for(size_t i=0;i<iStrings; i++) // After Parse() successfully terminates, display trimmed strings.
{ // Note that the Parse() function receives the pStr wchar_t**
LTrim(pStrs[i]); // buffer, but must make individual memory allocations for the
wprintf(L"%s\t%Iu\n",pStrs[i],wcslen(pStrs[i])); // six strings, and place those pointers in that 24/48 byte
} // buffer. Here, back in main(), we'll have to release the
for(size_t i=0;i<iStrings; i++) // memory for the six string pointers, then the memory for the
free(pStrs[i]); // pStrs wchar_t** buffer. In C++ with Parse() as a member of
free(pStrs); // my String Class, a simple delete [] pStrs call will release
} // the pointer to pointer buffer, but first call destructors on
getchar(); // the individual Strings. So memory release is all done in
// one shot.
return 0;
}
|