|
|
I can't fly to mars...
You should tell if you are unable to use or if you found bug. And if the latter, what exactly.
PS: I am using this code since 10 years for CSV files and it works great.
Holy sh*t, I am very happy that there are lots of good programmers sharing code (thank you to them) but the looser comments on this very simple but useful function prevents me from posting again ever.
|
|
|
|
|
Hey....I appreciate the effort you are bringing to the table.
I don't think it's wise to be too critical of anything, especially
if it's free........
Thanks for your help, work, and effort......
Thanks,
Carl
|
|
|
|
|
1. Backslashes are removed when they are used as Magic character. Eg:
CString strSub;
CString strLine = "the,quick,D:\\apps\\utilities";
int iLen = strLine.GetLength();
GetSubString(strSub, strLine, iLen, 0, ',', '\\');
// strSub == the --> ok
GetSubString(strSub, strLine, iLen, 1, ',', '\\');
// strSub == quick --> ok
GetSubString(strSub, strLine, iLen, 2, ',', '\\');
// strSub == D:appsutilities --> it should only be D:\apps\utilities
2. When bug no. 1 is fixed, how do you solve this problem:
CString strSub;
CString strLine = "the,quick,D:\\apps\\utilities\\,brown\\,fox,jumps,c:\\temp\\";
int iLen = strLine.GetLength();
GetSubString(strSub, strLine, iLen, 0, ',', '\\');
// strSub == the --> ok
GetSubString(strSub, strLine, iLen, 1, ',', '\\');
// strSub == quick --> ok
GetSubString(strSub, strLine, iLen, 2, ',', '\\');
// strSub == D:\apps\utilities,brown,fox --> it should only be D:\apps\utilities
// how could this be solve?
GetSubString(strSub, strLine, iLen, 3, ',', '\\');
// strSub == brown,fox --> ok
GetSubString(strSub, strLine, iLen, 4, ',', '\\'); // MOD 1
// strSub == jumps --> ok
GetSubString(strSub, strLine, iLen, 5, ',', '\\'); // MOD 1
// strSub == c:\temp\ --> ok
|
|
|
|
|
Hi,
the behaviour you noticed is not a bug, its a feature.
'Magic' characters should be removed when the string is split.
That means, if you choose ',' as separator and '\\' as magic,
you have to 'escape' them by the magic character, when they occur in the string to split.
First, you need to know what you want.
... (deleted some example and explanation)...
You just really need to know what you want.
What string should be in your CSV file ?
What result do you WANT to get by splitting your string ?
If you can answer these 2 questions, you know why I wrote 'not a bug'.
Regards, Rainer
|
|
|
|
|
I often switch between CString and char * as convenient. In fact I generally spec const char * as a parameter so I can easily use either as in the following.
This is my standard approach. This one parses for "|". In another project I had a version for CSV. Note the overload for using a string resource.
//
// FXParseString
// -------------
//
// Parses out a substring from a compound string where the substrings
// are separated by the "|" character.
//
// e.g. "string one|string two|string three"
//
// Parameters
// ----------
//
// sz - Compound string
// iIdx - index of substring
//
// Return Value
// ------------
//
// CString containing the substring
//
CString FXParseString( const char *sz, int iIdx )
{
int iStart = 0;
int iLen = strlen( sz );
int iCount = 0;
for( int i = 0; i < iLen; i++ )
{
if( sz[ i ] == '|' )
{
iCount++;
if( iCount > iIdx )
return CString( &sz[ iStart ], i - iStart ); // ** GOT THE SUBSTRING **
else
iStart = i + 1;
}
}
if( iCount == iIdx )
return CString( &sz[ iStart ], iLen - iStart ); // ** LAST SUBSTRING **
else
return CString( "" ); // ** NOT FOUND: RETURN NULL STRING **
}
//
// FXParseString - overloaded
// -------------
//
// As above for a string resource
//
CString FXParseString( UINT nID, int iIdx )
{
CString s;
s.LoadString( nID );
return FXParseString( s, iIdx );
}
|
|
|
|
|
One could always use AfxExtractSubString() as already suggested - but this extremely simple function implementation has the advantage of only returning the characters between a startkey and an endkey.
BOOL CUSTOM_CLASS ExtractSubString(CString &csRet, LPCTSTR szFull, LPCTSTR StartKey, LPCTSTR EndKey, int iIndex)
{
// only returns the characters
// between the two keys, not the starting point of the first key.
// e.g.
// ExtractSubString(csRet, "@AAthis is a variable@~}@ABthis is anothervariable@~}", "@AA", "@~}");
// csRet = "this is a variable"
csRet = _T("");
CString csSearch = szFull;
int iLen = strlen(StartKey);
int iFind = -1;
while(iIndex-->=0)
{
iFind = csSearch.Find(StartKey, iFind+1);
if(iFind != -1 && iIndex < 0)
{
int iEnd = csSearch.Find(EndKey, iFind+1);
if(iEnd != -1)
{
csRet = csSearch.Mid(iFind+iLen, iEnd-iFind-iLen);
return TRUE;
}
}
}
return FALSE;
}
"Life begins at 140"
|
|
|
|
|
Hi,
this is a good tip, but would not have solved my problem.
If your 'EndKey' is within the substring you want to extract, this function fails. You have no chance to determine if some data is the 'EndKey' or simply some data.
Imagine a user exports some data into a CSV file. data 1 is "hi", data 2 is "bla", data 3 is "Hi, welcome !".
Because commas (or any other character) are the separators, no comma can be within a data field.
When you build the CSV string, you can 'mask' commas by a magic character, to avoid them to be interpreted later as separators instead of data.
This can be easily done with CString::Replace(",", "\\,").
The CVS file then contains a string "hi,bla,Hi\,welcome".
When you then use GetSubstring on this string, using ',' as separator and '\\' as magic, you get the original data.
Regards, Rainer
|
|
|
|
|
MFC already supports extracting substrings from other strings. The function is named "AfxExtractSubString" and is not documented. You can find it in the file "WINSTR.CPP". It is used inside the MFC in several places.
Best regards
Holger Persch
|
|
|
|
|
Yup, but this cannot be used, if commas exist in the data (substrings) you want to extract.
Regards, Rainer
|
|
|
|
|
Why not this?
CString full;
CString sub;
int position;
char seperator = ',';
for (int position = 0; AfxSubstring(sub, full, pos, seperator); ++pos)
{
// do something with sub
}
|
|
|
|
|
Why not this?
CString full;
CString sub;
int position;
char seperator = ',';
for (int position = 0; AfxSubstring(sub, full, pos, seperator); ++position)
{
// do something with sub
}
|
|
|
|
|
'- only 1 line of documentation accompanying the code'
Ok, may be using it is too simple to write a book around it.
It just extends AfxGetSubString to allow separator characters used within the substrings.
'- the article is not well formated'
How do YOU define well formatted ?
'the function is not well abstracted or designed'
-no comment-
'- exactly how is this optimized to be fast?'
Try to do the job with MFC CString functions and you will notice.
'- what is the purpose of using CString at all?'
Because DoDataExchange uses CString. It would be nonsense to convert x-times between CString and char*.
Regards, Rainer
|
|
|
|
|
|
..as fast as it is possible (I hope) when using CString.
|
|
|
|
|