You can't use strtok
with two different strings at the same time.
strtok(string, delim)
stores its position in string internally for future calls to strtok (NULL, delim)
. It can only remember one at a time. strtok (tmpMsgBootForce, " ")
says to look through tmpMsgBootForce
and then motdico = strtok (dicoActuel, " ")
overwrites that with dicoActuel
.
What to use instead depends on your compiler. The C standard defines strtok_s
, but that's from the 2011 standard and has proven to be controversial. POSIX defines strtok_r
, most Unix compilers will understand that. Finally, Visual Studio has their own slightly different strtok_s
.
They all work basically the same way. You manually store the position in each string you're iterating through.
Here it is using strtok_r
. next_tmpMsgBootforce
and next_dicoActuel
hold the position for parsing tmpMsgBootForce
and dicoActuel
respectively.
char *next_tmpMsgBootforce;
char *next_dicoActuel;
strcpy(tmpMsgBootForce, msgBootforce);
mot = strtok_r(tmpMsgBootForce, " ", &next_tmpMsgBootforce);
while (mot != NULL) {
motdico = strtok_r(dicoActuel, " ", &next_dicoActuel);
while (motdico != NULL) {
if (strcmp(mot,motdico) == 0) ++i;
motdico = strtok_r(NULL, " ", &next_dicoActuel);
}
mot = strtok_r(NULL," ", &next_tmpMsgBootforce);
}
Because this is all such a mess, I recommend using a library such as GLib to smooth out these incompatibilities and unsafe functions.
As a side note, the strcpy
and strcat
are not safe. If their destination does not have enough space it will try to write outside its memory bounds. As with strtok
the situation to do this safely is a mess. There's the non-standard but ubiquitous strlcpy
and strlcat
. There's the standard but not ubiquitous strcpy_s
and strcat_s
. Thankfully for once Visual Studio follows the standard.
On POSIX systems you can use strdup
to duplicate a string. It will handle the memory allocation for you.
char *tmpMsgBootForce = strdup(msgBootForce);
The caveat is you have to free
this memory at the end of the function.
Doing a strcat
safely gets complicated. Let's simplify this by splitting it into two functions. One to do the searching.
int theSearching(
const char *msgBootforce,
const char *dicoActuel
) {
int i = 0;
char *next_tmpMsgBootforce;
char *next_dicoActuel;
char *tmpMsgBootForce = strdup(msgBootforce);
char *tmpDicoActuel = strdup(dicoActuel);
char *mot = strtok_r(tmpMsgBootForce, " ", &next_tmpMsgBootforce);
while (mot != NULL) {
char *motdico = strtok_r(tmpDicoActuel, " ", &next_dicoActuel);
while (motdico != NULL) {
if (strcmp(mot,motdico) == 0) {
++i;
}
motdico = strtok_r(NULL, " ", &next_dicoActuel);
}
mot = strtok_r(NULL," ", &next_tmpMsgBootforce);
}
return i;
}
And one to do the appending. This function ensures there's enough space for the concatenation.
char *tryAppend( char *dest, const char *src, int *maxCorrepondance, const int numFound ) {
char *new_dest = dest;
if (numFound > *maxCorrepondance) {
*(maxCorrepondance) = numFound;
// Allocate enough memory for the concatenation.
// Don't forget space for the null byte.
new_dest = realloc( dest, strlen(dest) + strlen(src) + 1 );
strcat( new_dest, src);
}
// Return a pointer to the reallocated memory,
// or just the old one if no reallocation was necessary.
return new_dest;
}
Then use them together.
int numFound = theSearching(msgBootforce, dicoActuel);
bonResultatBootforce = tryAppend(bonResultatBootforce, msgBootforce, &maxCorrepondance, numFound);