text[i] 的数据类型是什么?

What is the data type of text[i]?

我正在尝试计算用户使用此自定义函数输入的字符串中的单词数:

int count_words(char* text)
{
   int wc = 0;
   for(int i = 0,k = strlen(text); i<k;i++)
   {
      if(strcmp(" ",text[i]) ==0 || strcmp(".",text[i]) ==0 || strcmp("!",text[i]) ==0 || strcmp("?",text[i]) ==0 || strcmp(",",text[i]) ==0)
      {
          wc++;
      }
   }
    return wc+1;
}

但我不断收到此错误:

re.c:59:21: error: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the address with & [-Werror,-Wint-conversion]
      if(strcmp(" ",text[i]) ==0 || strcmp(".",text[i]) ==0 || strcmp("!",text[i]) ==0 || strcmp("?",text[i]) ==0 || strcmp(",",text[i]) ==0)
                    ^~~~~~~
                    &

re.c:59:48: error: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the address with & [-Werror,-Wint-conversion]
      if(strcmp(" ",text[i]) ==0 || strcmp(".",text[i]) ==0 || strcmp("!",text[i]) ==0 || strcmp("?",text[i]) ==0 || strcmp(",",text[i]) ==0)
                                               ^~~~~~~
                                               &

到底发生了什么?

strcmp 采用 char *(字符串)而不是单个 char。最好使用 strtok` 来计算字符串中的单词数。

这是一个简单的例子

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

int main(void) {

  char arr[] = "Temp hello bye! No way. Yes";
  char *delimeters = " !.";

  char *token = strtok(arr, delimeters);
  int count = 0;

  while (token != NULL) {
    count++;
    token = strtok(NULL, delimeters);
  }
  printf("Words = %d", count);

  return 0;
}

您也可以使用 strpbrk 而不是 strtok

函数strcmp声明如下

int strcmp(const char *s1, const char *s2);

如你所见,函数的两个参数都是指针类型const char *

但是在你使用的函数的这个调用中

strcmp(" ",text[i])

第二个参数的类型为 char。所以编译器发出错误信息。

error: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *';

你的函数也有逻辑错误。例如,对于空字符串,它 returns 的字数等于 1.

return wc+1;

并且每个分隔符都算作一个单词。因此,对于仅包含分隔符的字符串,该函数将其解释为包含多个单词。

除此之外,函数 count_words 不应更改传递的字符串。它应该声明为

size_t count_words( const char *text );

函数可以通过下面的演示程序来定义。

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

size_t count_words( const char *text )
{
    const char *separators = " \t.,!?";
    size_t n = 0;
    
    while ( *text )
    {
        text += strspn( text, separators );
        
        if ( *text )
        {
            ++n;
            text += strcspn( text, separators );
        }
    }
    
    return n;
}


int main(void) 
{
    const char *text = "We, beginners, should help each other!";
    
    printf( "There are %zu words in the text \"%s\".", count_words( text ), text );

    return 0;
}

程序输出为

There are 6 words in the text "We, beginners, should help each other!".

一种更通用的方法是当函数的用户可以调用它时自己指定所需的单词分隔符。例如

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

size_t count_words( const char *text, const char *separators )
{
    size_t n = 0;
    
    while ( *text )
    {
        text += strspn( text, separators );
        
        if ( *text )
        {
            ++n;
            text += strcspn( text, separators );
        }
    }
    
    return n;
}

int main(void) 
{
    const char *text = "We, beginners, should help each other!";
    
    printf( "There are %zu words in the string \"%s\".", count_words( text, " \t.,!?" ), text );

    return 0;
}

程序输出同上图

There are 6 words in the text "We, beginners, should help each other!".

strcmp 采用以 NULL '[=11=]' 结尾的字符数组。 对于您的问题,您需要在找到特殊字符时增加字数。 你应该分别检查没有重复的特殊字符。

/*const special_char[] = {' ','.','!','?',','};*/

int count_words(char* text)
{
    uint32_t idx = 0;
    int wc = 0;

    /*if the first char equal one of special char, don't count that as word*/
    for (int i = 1; i < strlen(text); i++)
    {
        /*Special char shouldn't be repeated respectively otherwise, don't count that as word*/
        if (
            ((' ' == text[i]) || ('.' == text[i]) || ('!' == text[i]) || ('?' == text[i]) || (',' == text[i]))
            && 
            ((' ' != text[i - 1]) && ('.' != text[i - 1]) && ('!' != text[i - 1]) && ('?' != text[i - 1]) && (',' != text[i - 1]))
        )
        {
            wc++;
        }
    }

    /*For the last word*/
    wc++;

    return wc;
}