【问题标题】:C Code to count how many letters in a wordC代码计算一个单词中有多少个字母
【发布时间】:2017-10-16 09:29:23
【问题描述】:

我做了简单的代码来计算一个单词中有多少个字母,由于某种原因变量letters不一致,这里是代码

#include <stdio.h>

int main()
{
    char str;
    int slen(char *str)
    {
        int i;
        int letters=0;
        for(i=0;i<30;i++)
        {
            if((str[i]>='A'&&str[i]<='Z')||(str[i]>='a'&&str[i]<='z'))
                letters++;
        }
        return letters;
    }
    printf("%d \n", slen("Word"));
}

这里的变量 letter 打印 22。

【问题讨论】:

  • 你期望什么输出?
  • 你为什么在你的for条件下做&lt;30?这意味着循环将超出字符串本身的末尾并开始计算恰好在内存中的垃圾数据。
  • @STF 它被标记为 C,而不是 C++。
  • 你知道isalpha()吗?
  • 嵌套函数是 GNU 扩展,而不是标准 C。

标签: c string function loops


【解决方案1】:

由于for 循环中的&lt; 30 条件,您的程序会越过"Word" 字符串边界并在该字符串之后开始计算内存中的任何内容。

&lt; 30 替换为&lt; strlen(str)(您将需要#include &lt;string.h&gt;)。

更新:(感谢@J...S(见 cmets))或者你可以重写

for (i=0; i < 30; i++)
{
    if((str[i]>='A'&&str[i]<='Z')||(str[i]>='a'&&str[i]<='z'))
        letters++;
}

while (str != '\0') {
    if ((*str >= 'A' && *str <= 'Z') || (*str >= 'a' && *str <= 'z')) {
        letters++;
    }
    ++str;
}

您也可以使用 isalpha() 之类的东西来代替您的 if 条件。

顺便说一下,使用空格来分隔一行的不同部分。否则真的很难读。谢谢:)

【讨论】:

  • str[i]!='\0' 也可以使用。
【解决方案2】:

函数应该在main()之外声明/定义。

改变这个:

for(i=0;i<30;i++)

到这里:

for(i = 0; i < strlen(str); i++)

因为你想遍历字符串的长度,而不是大于或小于它的实际长度。

在您的情况下,“Word”只有 4 个字母,并且您迭代直到 i &lt; 30 评估为 false,调用未定义行为,因为您将访问超出范围的内存。

把所有东西放在一起,我们得到:

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

int slen(char *str)
{
    int letters=0;
    for(unsigned int i=0;i<strlen(str);i++)
    {
        if((str[i]>='A'&&str[i]<='Z')||(str[i]>='a'&&str[i]<='z'))
        letters++;
    }
    return letters;
}

int main()
{ 
    printf("%d \n", slen("Word"));
}

输出:

4

【讨论】:

  • 如果你使用的是strlen,那么for循环有什么用呢?
  • @AniruddhAgarwal - 因为代码并不是要计算字符数,strlen 就是这样做的。它正在计算字母的数量。所以你需要遍历整个字符串,因此同时使用for 循环和strlen
  • 我认为作者问的是如何计算一个单词中的字符,strlen 做他想做的事
  • 没有@AniruddhAgarwal。他想数字母。字符串可以包含字母数字字符。
  • 好的好的,我知道了。
【解决方案3】:

你想要这个:

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


// declaring slen outside main (not using non standard GNU extension)

int slen(char *str) 
{
  int i;
  int letters = 0;
  int length = strlen(str);  // using strlen, in order not to go beyond the end
                             // of the string


  for (i = 0; i < length; i++) {
    if ((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z'))
      letters++;
  }

  return letters;
}

int main()
{
   printf("%d \n", slen("Word123"));
}

此处的预期输出为 4(“Word”的 4 个字母,不包括数字 1、2 和 3)。

略微优化的版本:

int slen(char *str) 
{
  int letters = 0;

  for (int i = 0; ; i++) {
    char c = str[i];
    if (c == 0)
      break;

    if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
      letters++;
  }

  return letters;
}

甚至更好地使用来自ctype.hisalpha

#include <ctype.h>
...
int slen(char *str) 
{
  int letters = 0;
  for (int i = 0; ; i++) {
    int c = str[i];    // yes, int is correct, isalpha wants an int    
    if (c == 0)
      break;

    if (isalpha(c))
      letters++;
  }

  return letters;
}

【讨论】:

    【解决方案4】:

    对于根据 C 标准的初学者,不带参数的函数 main 应声明为

    int main( void )
    

    尽管根据 C 标准,一些编译器可以有自己的语言扩展,但你不能在另一个函数中定义一个函数。

    还要考虑到,拉丁字母在给定字符集中没有必要按顺序相互跟随。例如,在 EBCDIC 集合中,一些字母不是按顺序排列的。字母之间还嵌入了其他符号。

    所以最好使用标头&lt;ctype.h&gt;中声明的标准C函数isalpha

    函数中也没有改变原始字符串。所以应该用限定符const声明。

    目前还不清楚为什么在函数内的这个循环中使用了这个幻数30

    for(i=0;i<30;i++)
    

    考虑到所有这些,程序可能看起来像

    #include <stdio.h>
    #include <ctype.h>
    
    size_t letters_count( const char *s )
    {
        size_t count = 0;
    
        for ( ; *s; ++s )
        {
            if ( isalpha( ( unsigned char )*s ) ) ++count;
        }
    
        return count;
    }
    
    #define N   100
    
    int main(void) 
    {
        char s[N];
    
        printf( "Enter a statement: " );
    
        fgets( s, sizeof( s ), stdin );
    
        printf( "The statement contains %zu letters\n", letters_count( s ) );
    
        return 0;
    }
    

    它的输出可能看起来像

    Enter a statement: Hello TheErolley
    The statement contains 15 letters
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-03
      • 2022-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-11
      相关资源
      最近更新 更多