简体   繁体   English

查找字符串中最长的单词

[英]Finding Longest Word in a String

I am very new in C coding. 我是C编程的新手。 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]);
}

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);
}

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! 除了通过返回指向LongestWord本地声明的数组的指针来调用Undefined Behavior之外,使用gets尽管gets()还是很危险的,永远不要使用它! and writing beyond the end of the Solution array -- you are missing the logic of identifying the longest word. 并在Solution数组的末尾进行书写-您缺少识别最长单词的逻辑。

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 ). 您必须跟踪看到的最长的字符串,只有当当前字符串比迄今为止的最长的字符串长时,才可以复制到有效的内存中,该内存将在函数返回(和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. 您可以使用strtok标记字符串中的所有单词,可以使用strcspnstrspn的组合将strcspn起来,可以使用sscanf和每个单词开头的偏移量,或者我发现最简单的方法是使用一对指针sp (开始指针)和ep (结束指针)对字符串进行处理。

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). 在那里,您只需将sp移到每个单词的第一个字符,然后继续移动ep直到找到空格(或字符串的结尾)。 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) 单词长度是ep - sp ,然后如果它是最长的,则可以简单地使用memcpylength字符复制到最长的单词缓冲区中,然后使用nul-terminate ,(重复操作直到字符用完)

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. 要创建有效的存储,您有两种选择,要么传递足够大小的数组(请参见注释),要么使用malloc (或callocrealloc )在函数中声明一个有效的内存块,然后返回指向该内存块的指针。

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.) 注意:通过使用此方法,您将忽略所有前导,尾随和中间的空格,因此" my little dog has 1 flea . "类的字符串不会出现问题。)

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, eg 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. 您可以使用索引来执行相同的操作,例如string[i]等。这只需要保持每个单词开头的偏移量,然后进行减法以获得长度。 strtok is convenient, but modifies the string being tokenized so it cannot be used with string literals or other constant strings. strtok很方便,但是会修改要标记化的字符串,因此不能与字符串文字或其他常量字符串一起使用。

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. 如果您还有其他问题,请告诉我。

  1. please declare a proper main entry point: int main( int argc, const char* argv[] ) 请声明一个适当的main入口点: 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) 使用fgets而不是gets ,因为gets不会检查字符串的边界(输入120个字符的行时发生了什么)
  3. pass the length of the expected string to LongestWord 将期望字符串的length传递给LongestWord
  4. if available prefer using strnlen to plain strlen , there might be scenario where your string is not properly terminated. 如果可用,则首选使用strnlen plain strlen ,在strnlen情况下,可能无法正确终止字符串。
  5. Better yet use the suggested length parameter to limit your loop and break when a terminating char is encountered. 最好还是使用建议的length参数来限制循环并在遇到终止字符时中断。
  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). 您的Solution是一个堆栈分配的数组,按原样返回它可能取决于您的实现,您最好返回一个堆分配的数组(使用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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM