D
DFS
You might consider re-writing this avoid using strtok. By using strtok,
you force the string to be copied (twice) and counting word lengths does
not need to copy the string at all.
I read various criticisms of strtok, including it destroys/modifies the
original input string, and isn't thread safe (so there's strtok_r).
But it's handy, and will let you use multiple delimiters in one pass:
char delim[4] = " ,.-";
Regardless, I rewrote it without strtok, and to handle at most 3
delimiters. Seems to work well.
int getMaxWordLength(char *str, char *delim) {
int i=0,j=0,maxWordLen=0;
for(i=0;i<=strlen(str);i++) {
if(str==delim[0] || str==delim[1] || str==delim[2] ||
str=='\0') {
//printf("%d\n",i-j);
if((i-j) > maxWordLen) {
maxWordLen = (i-j);
}
j = i + 1;
}
}
return maxWordLen;
}
But strtok is a little faster (gotta save those nanoseconds);
========================================================================
#define BILLION 1E9
struct timespec start1, end1, start2, end2;
clock_gettime(CLOCK_MONOTONIC, &start1);
i = getMaxWordLength(splitStr, delim);
clock_gettime(CLOCK_MONOTONIC, &end1);
clock_gettime(CLOCK_MONOTONIC, &start2);
i = getMaxWordLength_strtok(splitStr, delim);
clock_gettime(CLOCK_MONOTONIC, &end2);
double et = (end1.tv_sec-start1.tv_sec) + ((end1.tv_nsec-start1.tv_nsec)
/ BILLION);
long net = (BILLION * (end1.tv_sec - start1.tv_sec)) + (end1.tv_nsec -
start1.tv_nsec);
printf( "getMaxWordLength took: %.6f seconds (%li nanoseconds)\n", et,
net );
et = (end2.tv_sec-start2.tv_sec) + ((end2.tv_nsec-start2.tv_nsec) /
BILLION);
net = (BILLION * (end2.tv_sec - start2.tv_sec)) + (end2.tv_nsec -
start2.tv_nsec);
printf( "getMaxWordLength_strtok took: %.6f seconds (%li
nanoseconds)\n", et, net );
getMaxWordLength took: 0.000022 seconds (22143 nanoseconds)
getMaxWordLength_strtok took: 0.000011 seconds (10889 nanoseconds)
========================================================================
//GET LIST OF LONGEST WORDS IN STRING (DON'T STORE REPEATS).
int getLongestWords(char *str, char *longestWords, int maxWordLen,
char *delim) {
char *token, wordCounter[3];
int i = 1;
token = strtok(str, delim);
while(token != NULL)
{
if ((int)strlen(token) == maxWordLen) {
if(strstr(longestWords, token) == 0) {
sprintf(wordCounter, "%d", i);
strcat(longestWords, wordCounter);
strcat(longestWords, ".");
strcat(longestWords, token);
strcat(longestWords, " ");
Why not sprintf(longestWords, "%d. %s ", i, token)?
Thanks for tip! Saved a few lines, and is more readable. Decided not
to number the output words. I also went with strncat.
sprintf(addWord, "%s ", token);
strncat(longestWords, addWord, strlen(addWord));
Then consider using
snprintf which can be told how much room is available in the array (it's
up to you to pass the correct size into the function, but that's not
hard.
I'll look into it.
int main(void)
{
char splitStr[200] = "Look at him working, darningg hishersh socks
in the night when there's nobody there";
char splitStrA[200] = "";
char splitStrB[200] = "";
char delim[2] = " ";
char longestWords[2] = "";
You have 2 bytes (one taken with a null) and you write the whole output
string to it. That scribbles on goodness know what other objects. Make
this array big enough for the intended use (or pass its size to
getLongestWords and use snprintf).
This kind of string-handling and memory mgmt stuff make C less "fun"
than it could be.
As has been said, valgrind turns out not to help much here, but don't
let that stop you using it. It will help out soon enough!
I was doing the chapters in Learn C The Hard Way, and the author Zed
Shaw uses valgrind (pronounced valgrinned if you didn't know) early on.
It's a little hardcore for me at the moment. I barely understand
pointers, and am clueless about heap/stack. I just learned a few weeks
ago what int main(int argc, char *argv[]) means.
[dfs@home files]$ valgrind -v ./strtokens
(I don't think I've ever used -v. It seems to say too much as far as I
am concerned.)
<snip>
Thanks for your feedback and help.