so it will look for either ":" or " " , whichever occurs first? correct??
and how do I know if the deliminiter uses the ":" or " "
so it will look for either ":" or " " , whichever occurs first? correct??
and how do I know if the deliminiter uses the ":" or " "
(1) Right.
(2) You don't. (Unless, of course, you make a copy of the original string, subtract the pointer to the original word from the pointer returned from strtok, and use that as an index into your copy to see what the original character was.)
what other alternative is there to parse a string?
Such as? What's so bad with it? Yes, it modifies the input string, and it's not re-entrant (but both of these things are clearly stated in the docs), but otherwise, it does what it says on the label - splits strings into tokens based on the separator string. There is a strtok_r() function that allows re-entrant use.
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
I don't know of any alternative.
The worse possible thing is that it damages the input string. If you want to keep it intact, you can't use strtok or you have to make a copy. Expensive and unnecessary.What's so bad with it?
The second is that it keeps track of the position using a static variable to my knowledge, which is still worse. It loses the meaning of a good function. A good function allows you to specify where to begin the search. Either as an index or as a (const) char* variable.
The documentation is not at fault - the function itself is.Yes, it modifies the input string, and it's not re-entrant (but both of these things are clearly stated in the docs), but otherwise, it does what it says on the label - splits strings into tokens based on the separator string.
I can't find that one in Visual Studio's documentation... Non-standard or is Microsoft simply lacking support?There is a strtok_r() function that allows re-entrant use.
I guess I am too lazy to write a new function to do this, strtok is fine for me
Yes, it would of course be more flexible to copy out the new string, but then you only need THAT if you need to keep the original string intact, so someone else would complain about that - no such thing as pleasing everyone at once.
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
and by the way , I don't need to keep the original string as it is for my purpose right now. so strtok is fine
Non-destructive version:
Added strtokv3. Should do all strtok does and better.Code:#include <stdio.h> #include <string.h> #include <stdint.h> #include <assert.h> const char* strtokv2(const char* strToSearch, const char* strDelimiter); const char* strtokv3(const char* strToSearch, const char* strDelimiter, char* pBuffer, size_t nBufferSize); const char* strtokv2(const char* strToSearch, const char* strDelimiter) { size_t nStrLength = strlen(strToSearch); size_t nDelLength = strlen(strDelimiter); const char* strEnd = strToSearch + nStrLength; const char* p = strToSearch; while (p < strEnd && *p == ' ') p++; while (p++ < strEnd) { if (*p == *strDelimiter) { bool bFound = true; if ((size_t)(strEnd - p) < nDelLength) // Length of remaining string - length of delimiter for (size_t i = 1; i < nDelLength; i++) { if (p[i] != strDelimiter[i]) { bFound = false; break; } } if (bFound) return p; } } return NULL; } const char* strtokv3(const char* strToSearch, const char* strDelimiter, char* pBuffer, size_t nBufferSize) { uint32_t nLength; char* pFound; if (!strToSearch) return NULL; pFound = (char*)strtokv2(strToSearch, strDelimiter); if (!pFound) nLength = strlen(strToSearch) + 1; // +1 for NULL else nLength = (pFound - strToSearch) + 1; // +1 for NULL assert(nBufferSize >= nLength); memcpy(pBuffer, strToSearch, nLength - 1); pBuffer[nLength - 1] = 0; if (pFound) return pFound + 1; else return pFound; } int main (void) { char str[] = "This is a test string"; char mytokenizedstr[50][20] = {0}; int index = 0; const char* pSearchPos = str; while ( (pSearchPos = strtokv3( pSearchPos, " ", mytokenizedstr[index], sizeof(mytokenizedstr[index]) )) != NULL ) index++; for (int i = 0; i < 5; i++) puts(mytokenizedstr[i]); puts(str); return 0; }
Actually, I think I'll save this and recommend it over strtok.
This is the proper way of doing it.
great job Elysia.. you're a master.. thanks though for the code.. I might use it
Yes, it's not a very difficult function to replace. And you have to bear in mind that a lot of standard functions are pretty simple, and may not suit all purposes.
[I'm not sure your code actually works, thelooks wrong to me].Code:if(*p == *strDelimiter)
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
But your test-case uses a single-char string. Try something where the first match is the second (or any other nth, where n >= 2 [delimiter matches for index > 0]) char in the delimiter string - I dont _THINK_ that will work - I haven't tried it myself, but it doesn't look like the you're doing the right thing in that case.
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.