-5

I have a problem with the following program.

The main function calls the function returnArrayOfWords(arrS1, &ptrArray1) twice. On the first call, the array is parsed perfectly, and afterward the pointer always points to the first word. On the other hand, after the second call, the pointer of the first array points to the second word, the third word, or sometimes the first word, but it should always point to the first word -- nowhere else.

Why does the function misbehave when called for the second time?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void returnArrayOfWords (char *str4Parsing, char *arrayParsed[])
{
    char seps[] = " ,\t\n"; // separators
    char *token1 = NULL;
    char *next_token1 = NULL;
    int i = 0;

    // Establish string and get the first token:
    token1 = strtok_s( str4Parsing, seps, &next_token1);

    // While there are tokens in "str4Parsing" 
    while (token1 != NULL)
    {
        // Get next token:
        if (token1 != NULL)
        {
            arrayParsed[i] = token1;
            printf( " %s\n", token1 );
            token1 = strtok_s( NULL, seps, &next_token1);
            i++;
        }
    }
}


//int main1 ()
int main ()
{
    int i, j, n = 80; /*max number of words in string*/
    char arrS1[80], arrS2[80];
    const char *w1, *w2; /*pointers*/
    char *ptrArray1, *ptrArray2;
    int currLength1 = 0, currLength2 = 0 ;
    int sizeArr1 = 0, sizeArr2 = 0;
    int maxLength = 0;
    char wordMaxLength ;

    printf("Type your first string: "); 
    fgets(arrS1, 80, stdin);
    returnArrayOfWords(arrS1, &ptrArray1);
    sizeArr1 = sizeof(ptrArray1) / sizeof(ptrArray1[0]);

    printf("Type your second string: ");
    fgets(arrS2, 80, stdin);
    returnArrayOfWords(arrS2, &ptrArray2);
    sizeArr2 = sizeof(ptrArray2) / sizeof(ptrArray2[0]);

    for (i = 0; i < sizeArr1; i++)
    {
        // to find the largest word in the array
        w1 = &ptrArray1[i];
        currLength1 = strlen(w1);
        for (j = 0; j < sizeArr2; j++)
        {
            w2 = &ptrArray2[j];
            currLength2 = strlen(w2);

            if (strcoll(w1, w2) == 0)
            // compares the strings
            {
                if (currLength2 >= maxLength)
                // in the 0th element -> the length of the longest word 
                {
                    maxLength = currLength2;
                    wordMaxLength = ptrArray2[j];
                }
            }
        }
    }

    printf("The largest word is: %s", wordMaxLength);
    return 0;
}

EDIT:

Here's the latest version of the code, everything here works fine, managed to fix it myself. I'm just posting it in case somebody needs it as a solution:

         #include <stdio.h>
         #include <string.h>
         #include <stdlib.h>
         #include <stddef.h>
         #include <ctype.h>

      #define n 80 /*max number of words in string*/

      /* Arrays and pointers */

      int returnArrayOfWords (char *str4Parsing, char *arrayParsed[])  
  {
// returns the length of array
int elArr = 0, na = 0;
char *delim = " .,;-\t\n";      /* word delimiters   */
char *next_token1 = NULL;
char *ap = str4Parsing;          /* pointer to str4Parsing */
for (ap = strtok_s (str4Parsing, delim, &next_token1); ap; ap = strtok_s( NULL, delim, &next_token1))
{
    arrayParsed[na++] = ap;
    elArr++;
}

return elArr;
}


void printArr(char *arr[])
{
int i;
for ( i = 0; i < n; i++)
{
    printf("Element %d is %s \n", i, arr[i]);
}
}


void findLargestWord(char *ptrArray1[], int sizeArr1, char *ptrArray2[], int       sizeArr2)
{
size_t maxLength = 0;
char *wordMaxLength = NULL ;
int i = 0, j = 0;
char *w1 = NULL, *w2 = NULL; /*pointers*/
size_t currLength1 = 0, currLength2 = 0 ;

for (i = 0; i < sizeArr1; i++)
    {
    // to find the largest word in the array
    w1 = (ptrArray1[i]); // value of address (ptrArray1 + i)
    currLength1 = strlen(w1);
    //printf("The word from the first string is: %s and its length is : %d     \n", w1, currLength1); // check point

    for (j = 0; j < sizeArr2; j++)
        {
        w2 = (ptrArray2[j]); // value of address (ptrArray2 + j)
        currLength2 = strlen(w2);
        //printf("The word from the second string is : %s and its length is  : %d \n", w2, currLength2); // check point

        if (strcoll(w1, w2) == 0 && currLength1 == currLength2)
            // compares the strings
            {
            if (currLength2 >= maxLength)
                // in the variable maxLength -> the length of the longest word 
                {
                    maxLength = currLength2;
                    wordMaxLength = w2;
                    //printf("The largest word for now is : %s and its   length is : %d \n", wordMaxLength, maxLength); // check point
                }
            }
        }
    }
printf("The largest word is: %s \n", wordMaxLength);
printf("Its length is: %d \n", maxLength);
 }


   void typeArray (char *arrS1)
 {  
  int err = 0;
if (!fgets (arrS1, n, stdin)) {  /* validate 'arrS1' */
    fprintf (stderr, "Error: invalid input for string.\n");
    err = 1;
}

while (err == 1) 
{
    if (!fgets (arrS1, n, stdin)) {  /* validate 'arrS1' */
        fprintf (stderr, "Error: invalid input for string.\n");
        err = 1;
    }
}
}


   int main(void)
 {
   char arrS1[n], arrS2[n];
char *ptrArray1[n] = {NULL}, *ptrArray2[n] = {NULL};
int sizeArr1 = 0, sizeArr2 = 0;

printf("Type your first string: "); 
typeArray (arrS1);
sizeArr1 = returnArrayOfWords (arrS1, ptrArray1); // sizeArr1 = number of    elements in array 1

printf("Type your second string: ");
typeArray (arrS2);
sizeArr2 = returnArrayOfWords (arrS2, ptrArray2); // sizeArr2 = number of elements in array 2

findLargestWord(ptrArray1, sizeArr1, ptrArray2, sizeArr2);

return 0;
}
  • Thank you all in advance for the help! – Kauder Hexenban Jun 01 '16 at 19:46
  • 6
    Did you do your indentation with a shotgun? Also, I like `while ((token1 != NULL)) { if (token1 != NULL)`, for the tricky cases where you need to be **absolutely sure** `token1` in non-NULL. – EOF Jun 01 '16 at 19:47
  • 2
    Have you invented "inverse formatting style"? – Weather Vane Jun 01 '16 at 19:48
  • did u try stepping through the code with a debugger? – pm100 Jun 01 '16 at 19:48
  • 1
    `sizeof(ptrArray1)` is the size of the pointer, not of an array – bolov Jun 01 '16 at 19:50
  • 1
    The pointer arrays `char *ptrArray1, *ptrArray2;` that you pass are unintialised pointers to random memory. Might work, probably not.You must allocate memory for an array of token pointers. But as stated above, you don't know how many elements the function used. – Weather Vane Jun 01 '16 at 19:54
  • `void returnArrayOfWords()` --> `int returnArrayOfWords() { ... return i; }` – Weather Vane Jun 01 '16 at 20:01
  • Where do you allocate memory for the arrays? There is a lot to learn first about pointers and dynamic memory and arrays. A pointer is not an array! – too honest for this site Jun 01 '16 at 20:10
  • `strcoll` does not find the longest string. It compares them lexographically with respect to locale (whatever that means). – Weather Vane Jun 01 '16 at 20:30
  • It looks like the intent is that `returnArrayOfWords()` should allocate the array and assign that to `*arrayParsed`. It should be declared `char **arrayParsed` to make this clearer. – Barmar Jun 01 '16 at 20:30
  • Thank you all for the help, especially to those who left some positive comments ;) – Kauder Hexenban Jun 05 '16 at 13:29

1 Answers1

0

There are numerous errors in the program although it compiled without any warnings. Chiefly the pointer types for your array, and the memory allocated. Secondly the function does not know how many words is allowed, and does not return how many were read - your method did not work at all (as in comments). Thirdly the string comparisons: you did not state the goals clearly, but in comment you want the "biggest string". strcoll does not do that - it's a lexical comparison, so I changed that section to find the longest string for the two sentences you enter. See comments, I made a large number of changes.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int returnArrayOfWords (char *str4Parsing, char *arrayParsed[], int maxtokens)  // added max
{
    char seps[] = " ,\t\n"; // separators
    char *token1 = NULL;
    char *next_token1 = NULL;
    int i = 0;

    // Establish string and get the first token:
    token1 = strtok_s( str4Parsing, seps, &next_token1);

    // While there are tokens in "str4Parsing" 
    while (token1 != NULL)
    {
        if(i >= maxtokens)
            return i;                                   // ignore the rest
        arrayParsed[i] = token1;
        printf( " %s\n", token1 );
        token1 = strtok_s( NULL, seps, &next_token1);
        i++;
    }
    return i;
}

int main (void)                                         // correct signature
{
    int i, j, n = 80; /*max number of words in string*/
    char arrS1[80], arrS2[80];
    //const char *w1, *w2; /*pointers*/                 // deleted
    char **ptrArray1, **ptrArray2;                      // changed type
    int currLength1 = 0, currLength2 = 0 ;
    int sizeArr1 = 0, sizeArr2 = 0;
    int maxLength = 0;
    char *wordMaxLength;                                // changed to pointer

    ptrArray1 = malloc(n * sizeof (char*));             // allocate mem for pointer array
    if (ptrArray1 == NULL)
        return 1;
    ptrArray2 = malloc(n * sizeof (char*));             // allocate mem for pointer array
    if (ptrArray2 == NULL)
        return 1;

    printf("Type your first string: "); 
    fgets(arrS1, 80, stdin);
    sizeArr1 = returnArrayOfWords(arrS1, ptrArray1, n); // indirection error, added max words, get actual num

    printf("Type your second string: ");
    fgets(arrS2, 80, stdin);
    sizeArr2 = returnArrayOfWords(arrS2, ptrArray2, n); // indirection error, added max words, get actual num

    for (i = 0; i < sizeArr1; i++)                      // this section rewritten
    {
        // to find the largest word in the array
        currLength1 = strlen(ptrArray1[i]);
        if(currLength1 > maxLength) 
        {
            maxLength = currLength1;
            wordMaxLength = ptrArray1[i];               // changed definition to pointer
        }
    }

    for (j = 0; j < sizeArr2; j++)
    {
        // to find the largest word in the array
        currLength2 = strlen(ptrArray2[j]);
        if(currLength2 > maxLength) 
        {
            maxLength = currLength2;
            wordMaxLength = ptrArray2[j];               // changed definition to pointer
        }
    }

    printf("The largest word is: %s", wordMaxLength);

    free(ptrArray1);                                    // added
    free(ptrArray2);
    return 0;
}

Program session:

Type your first string: one two three four
 one
 two
 three
 four
Type your second string: apple banana pear
 apple
 banana
 pear
The largest word is: banana
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • Thank you for answering. Your code works well, but I was originally searching for the longest common word in the two strings. Example: string 1 = pear banana apple; string 2 = banana grapes cucumber; The longest common word = banana. Could you help me out with this one? – Kauder Hexenban Jun 05 '16 at 10:03
  • I apologize I never gave you a "I accept this answer", I was new to the site and didn't know much about it. I made sure I fixed it now. Thank you again for the answer and have a great day! :) – Kauder Hexenban Jun 30 '17 at 07:14