NT ME
NT ME

Reputation: 1

Finding Longest Word in a String

I am very new in C coding. I have written my code to find the longest word in a string. my code does not show any error but it prints a word with strange characters that is not in the string. Can you tell me what is wrong with my code? Thank you

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

char LongestWord (char GivenString[100]);

int main()
{
    char input[100];
    char DesiredWord[20];

    printf("please give a string:\n");
    gets(input);
       DesiredWord[20]=LongestWord(input);

    printf("longest Word is:%s\n",DesiredWord);

    return 0;
}

char LongestWord (char GivenString[100]){
    //It is a predefined function, by using this function we can clear the data from console (Monitor).
    //clrscr()
    int position1=0;
    int position2=0;
    int longest=0;
    int word=0;
    int Lenght=strlen(GivenString);
    char Solution[20];
    int p=0;

    for (int i=1; i<=Lenght; i++){
        if (GivenString[i-1]!=' '){
            word=word++;
    }
        if(GivenString[i-1]=' '){
            if (word>longest){
                //longest stores the length of longer word
                longest=word;
                position2=i-1;
                position1=i-longest;
                word=0;
                }
            }
        }
        for (int j=position1; j<=position2; j++){
                Solution[p]=GivenString[j];
                p=p++;
        }
return (Solution[20]);
}

Upvotes: 0

Views: 767

Answers (3)

dvhh
dvhh

Reputation: 4750

  1. please declare a proper main entry point: int main( int argc, const char* argv[] )
  2. Use fgets instead of gets, as gets does not check the bound of your string ( what happened when you enter a 120 chars line)
  3. pass the length of the expected string to LongestWord
  4. if available prefer using strnlen to plain strlen, there might be scenario where your string is not properly terminated.
  5. Better yet use the suggested length parameter to limit your loop and break when a terminating char is encountered.
  6. your Solution is a stack allocated array, returning it as it is might depend on your implementation, you might be better returning a heap allocated array (using malloc).

Suggested changes

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

char* getLongestWord(char* input, size_t input_length, size_t *result_length);

int main( int argc, const char* argv[] ) 
{
    const size_t max_length = 100;
    char input[max_length]; // consider using LINE_MAX from limits.h
    printf("please give a string:\n");
    if ( fgets( input, max_length, stdin ) == NULL ) return EXIT_FAILURE; // some failure happened with fgets.
    size_t longestWord_length = 0;
    char* longestWord = getLongestWord(input, max_length , &longestWord_length);
    printf("longest Word is %.*s\n",longestWord_length, longestWord );
    return EXIT_SUCCESS;
}

char* getLongestWord(char* input, size_t input_length, size_t *result_length) {
    char* result = NULL;
    size_t length = 0;

    size_t word_start = 0, word_end = 0;

    for(int i = 0; i < input_length; ++i) {
        if( (input[i] == ' ') || (input[i] == 0) ) {
            if( i == 0 ) { // first space
                word_start = 1;
                continue;
            }
            word_end = i-1;
            size_t word_length = word_end - word_start+1;
            if( word_length <= length ) {
                word_start  = i + 1; // next word start
                continue;
            }
            // new max length
            length = word_length;
            result = &input[word_start];

            word_start  = i + 1; // next word start
        }
        if( input[i] == 0 ) break; // end of string
    }
    *result_length = length;
    return result;
}

Upvotes: 0

David C. Rankin
David C. Rankin

Reputation: 84541

Aside from invoking Undefined Behavior by returning a pointer to a locally declared array in LongestWord, using gets despite gets() is so dangerous it should never be used! and writing beyond the end of the Solution array -- you are missing the logic of identifying the longest word.

To identify the longest word, you must obtain the length of each word as you work you way down the string. You must keep track of what the longest string seen, and only if the current string is longer than the longest seen so far do you copy to valid memory that will survive the function return (and nul-terminate).

There are a number of ways to do this. You can use strtok to tokenize all words in the string, you can use a combination of strcspn and strspn to bracket the words, you can use sscanf and an offset to the beginning of each word, or what I find easiest is just to use a pair of pointers sp (start-pointer) and ep (end-pointer) to work down the string.

There you just move sp to the first character in each word and keep moving ep until you find a space (or end of string). The word length is ep - sp and then if it is the longest, you can simply use memcpy to copy length characters to your longest word buffer and nul-terminate, (repeat until you run out of characters)

To create valid storage, you have two-choices, either pass an array of sufficient size (see comment), or declare a valid block of memory within your function using malloc (or calloc or realloc) and return a pointer to that block of memory.

An example passing an array of sufficient size to hold the longest word could be:

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

#define MAXW  256    /* longest word buffer size */
#define MAXC 1024    /* input string buffer size */

size_t longestword (char *longest, const char *str)
{
    int in = 0;             /* flag reading (in/out) of word */ 
    size_t max = 0;         /* word max length */
    const char  *sp = str,  /* start-pointer for bracketing words */
                *ep = str;  /* end-pointer for bracketing words */

    *longest = 0;           /* initialize longest as empty-string */

    for (;;) {                          /* loop over each char in str */
        if (isspace (*ep) || !*ep) {    /* is it a space or end? */
            if (in) {                   /* are we in a word? */
                size_t len = ep - sp;   /* if so, get word length */
                if (len > max) {        /* is it longest? */
                    max = len;          /* if so, set max to len */
                    memcpy (longest, sp, len);  /* copy len chars to longest */
                    longest[len] = 0;   /* nul-terminate longest */
                }
                in = 0;     /* it's a space, no longer in word */
            }
            if (!*ep)       /* if end of string - done */
                break;
        }
        else {              /* not a space! */
            if (!in) {      /* if we are not in a word */
                sp = ep;    /* set start-pointer to current */
                in = 1;     /* set in flag */
            }
        }
        ep++;       /* increment end-pointer to next char */
    }

    return max;     /* return max length */
}

int main (void) {

    char str[MAXC] = "",    /* storage for input string */
        word[MAXW] = "";   /* storage for longest word */
    size_t max = 0;         /* longest word length */

    fputs ("enter string: ", stdout);   /* prompt */
    if (!fgets (str, MAXC, stdin)) {    /* validate input */
        fputs ("(user canceled input)\n", stderr);
        return 1;
    }

    if ((max = longestword (word, str)))    /* get length and longest word */
        printf ("longest word: %s  (%zu-chars)\n", word, max);
}

(note: by using this method you ignore all leading, trailing and intervening whitespace, so strings like " my little dog has 1 flea . " do not present problems.)

Example Use/Output

$ ./bin/longest_word
enter string: my dog has fleas
longest word: fleas  (5-chars)

$ ./bin/longest_word
enter string:   my   little dog   has 1 flea  .
longest word: little  (6-chars)

There are many, many ways to do this. This is one of the most basic, using pointers. You could do the same thing using indexes, e.g. string[i], etc.. That just requires you maintain an offset to the start of each word and then do the subtraction to get the length. strtok is convenient, but modifies the string being tokenized so it cannot be used with string literals or other constant strings.

Best way to learn is work the problem 3-different ways, and pick the one that you find the most intuitive. Let me know if you have further questions.

Upvotes: 0

Navidk
Navidk

Reputation: 642

This should work:

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

void LongestWord(char string[100])
{
    char word[20],max[20],min[20],c;
    int i = 0, j = 0, flag = 0;
     for (i = 0; i < strlen(string); i++)
    {
        while (i < strlen(string) && string[i]!=32 && string[i]!=0)
        {
            word[j++] = string[i++];
        }
        if (j != 0)
        {
            word[j] = '\0';
            if (!flag)
            {
                flag = !flag;
                strcpy(max, word);
            }
            if (strlen(word) > strlen(max))
            {
                strcpy(max, word);
            }
            j = 0;
        }
    }
    printf("The largest word is '%s' .\n", max);

}


int main()
{
   char string[100];
    printf("Enter string: ");
    gets(string);
    LongestWord(string);
}

Upvotes: 1

Related Questions