使用strchr()在字符串中计算一个字符的出现次数

3
我即将完成课程学期,正在编写一个函数来查找字符串中某个字符的数量,根据老师分配的函数原型。我知道我一定做错了什么,但是我的代码要么锁死,要么在我的函数中无限循环。
这是一个作业,所以我不是想让任何人替我完成作业,而是指出我的错误和原因,以便我了解如何解决它。我会感激您提供的任何帮助。
这是我编写的代码:
#include <stdio.h>
#include <string.h>

int charCounter(char* pString, char c);

int main(void)
{
    char* inpString = "Thequickbrownfoxjumpedoverthelazydog.";
    int charToCount;
    int eCount;

    eCount = 0;
    charToCount = 'e';
    eCount = charCounter(inpString, charToCount);
    printf("\nThe letter %c was found %d times.", charToCount, eCount);

    return 0;
} // end main

int charCounter(char* pString, char c)
{
    int count = 0;
    char* pTemp;

    do
    {
        pTemp = strchr(pString, c);
        count++;
    }
    while(pTemp != NULL);

    return count;
} // end countCharacter

2
你必须使用 strchr 吗?我会直接迭代所有元素。 - Deduplicator
2
现在将其更改为strchr(pTemp, c),这样您就不必每次都从原始字符串的开头开始了。 - Gábor Buella
1
考虑采用“const”正确性:尽管由于历史原因,C字符串字面量的类型为“char []”,但它们实际上是不可变的。 - Deduplicator
1
你只需要热爱那些教育性的作业... - Deduplicator
1
@DavidPetersonHarvey - 这里的共识(尽管实现方式略有不同)似乎是你需要迭代字符串,查看字符串数组的每个char元素,以确定该元素是否等于你的cstrchr()不能轻易地为您完成这项工作。(每次不必过度操作您的字符串) - ryyker
显示剩余5条评论
4个回答

5
你的循环始终从 pString 的开头开始查找,并且一遍又一遍地找到第一个“e”。
如果你声明 char* pTemp = pString;,那么可以以稍微不同的方式进行迭代(抱歉之前贴错了版本!):
char* pTemp = pString;

while(pTemp != NULL)                                                                                                    
{                                                                                                                       
    pTemp = strchr(pTemp, c);                                                                                                           
    if( pTemp ) {
        pTemp++;
        count++;
    }                                                                                                
}

这会使pTemp指向刚刚在查找下一个字符之前找到的字符后面。

直接执行以下操作会更容易:

char* pTemp = pString;
while( *pTemp )
    if( *pTemp++ == c) count++;

好的,在考虑了一下之后,即使你已经让这个工作起来了,我还是将内部循环改成了我更满意的形式:

while( (pTemp = strchr(pTemp, c)) != NULL) {                                                                                                                       
   count++;                                                                                                             
   pTemp++;
}

我喜欢你的第二个建议,但这一章节都是关于函数的使用。第一个答案会导致分段错误并且转储核心,但迭代pString可以更接近解决问题。然而,我需要找出如何在找到字符后进一步迭代,因为我得到了很多重复计数。感谢让我更接近解决问题。 - David Peterson Harvey
是的,它仍然对我不起作用。当其他方法都失败时,我甚至尝试复制和粘贴您的代码,以防我犯了一些愚蠢的小错误。如果有区别的话,我正在Ubuntu机器上编译。 - David Peterson Harvey
1
@DavidPetersonHarvey -- 我之前粘贴了错误的版本,很抱歉。:( - JohnH
1
哦,约翰,太棒了!只需要一个小改动。我将count++与pTemp++放在if语句下的一个块中,这样它只有在实际找到字符时才会递增。这防止了它在找到第一个字符之前自动计数多余的时间。完美!谢谢!感谢这里的每个人,我现在更好地理解了它的工作原理! - David Peterson Harvey
1
只有在pTemp不为空的情况下,我们才进入while循环体。这意味着我们找到了该字符,因此我们增加计数。由于我们接下来要查找下一个字符,所以将pTemp增加到刚刚找到的字符之后...然后while循环的顶部使用strchr()的下一个调用搜索它,从刚刚找到的字符之后开始。如果找到另一个字符,我们再次进入while循环体,否则我们不会重新进入。 - JohnH
显示剩余3条评论

3
你总是从头开始重启。难怪你永远无法完成。
char* pTemp; // Init here = pString
do {
    pTemp = strchr(pString, c); // pString? Really? Should be pTemp
    count++;
} while(pTemp != NULL); // pTemp != NULL is verbose for pTemp here

不过,最好避免使用库函数,直接循环所有元素。

只是跟上时代的步伐:

size_t count(const char* s, char c) {
    size_t r = 0;
    for (; *s; ++s)
        r += *s == c;
    return r;
}

如果您坚持使用strchr()函数:
size_t count(const char* s, char c) {
    size_t r = 0;
    while ((s = strchr(s, c)))
        ++r;
    return r;
}

我很想这样做,但这一章节都是关于字符串函数的。(叹气) - David Peterson Harvey
远比之前更好、更快的方法! - Dandymon

1

strchr()总是在同一个位置查找,它不会在字符串中前进...

尝试使用字符串长度和简单的char比较来修改遍历字符串:

int i, len = strlen(pString);
count = 0;
for(i=0;i<len;i++)
{
    if(pString[i] == c) count++; //increment count only if c found
}

return count;  

不使用 strlen()(以回复评论)

i=-1, count = 0;
while(pString[++i])
{
   if(pString[i] == c) count++;
}  
return count;

2
为什么要使用strlen()?这会在字符串中增加一个额外的迭代,只是为了获取它的长度。完全删除变量“len”,并且不再使用“i<len”,而是使用“pString[i]!='\0'”(因为所有的“strlen”都是在查找尾随的NUL)。 - JohnH
1
@JohnH - 使用 strlen() 只是其中一种方法。它可行,您的方法也可以。我不是在这里试图打破陆地速度记录,只是回答问题。 :)(请参见编辑) - ryyker
1
谢谢!希望能有所帮助。 - ryyker

1

strchr在pString中返回字符c的第一个出现位置的指针。

因此,如果您在每个循环中都给出指向字符串开头的指针,则如果字符c存在,pTemp将始终具有相同的值且永远不会为NULL。这就是为什么您会遇到无限循环的原因。

您可能需要进行一些指针算术运算来解决此问题;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接