【问题标题】:Using strchr() to count occurrences of a character in a string使用 strchr() 计算字符串中字符的出现次数
【发布时间】:2014-06-10 07:24:29
【问题描述】:

我的学期快结束了,我正在写一个函数来查找字符串中某个字符的编号,给定老师分配的函数原型。我知道我一定是在做一些愚蠢的事情,但是这段代码要么被锁定,要么在我的函数中无限循环。

这是一项任务,所以我不是在寻找任何人为我做作业,而只是指出我错在哪里以及原因,以便我了解如何解决它。如果您愿意提供任何帮助,我将不胜感激。

这是我写的代码:

#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

【问题讨论】:

  • 必须使用strchr吗?我会对所有元素进行直接迭代。
  • 现在把它改成 strchr(pTemp, c) 你一直从原始字符串的开头开始
  • 考虑使用const-正确性:虽然由于历史原因,C 字符串文字属于char[] 类型,但它们实际上是不可变的。
  • 你只需要热爱那些教育作业...
  • 他们有教育意义的。

标签: c string count character strchr


【解决方案1】:

您的循环总是从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 越来越接近。但是,我需要弄清楚在找到字符后如何进一步迭代,因为我得到了很多重复计数。谢谢你让我靠近。
  • 您是否记得在我的第一个块之前放置char* pTemp = pString; 而不是char* pTemp;? :) 我实际上在发布之前测试了该块......
  • @DavidPetersonH​​arvey -- 我之前粘贴了错误的版本,抱歉。 :(
  • 哦,约翰,太棒了!它只需要一点点改变。我将 count++ 和 pTemp++ 放在 if 语句下的一个块中,因此它仅在实际找到字符时才递增。这阻止了它在找到第一个字符之前自动计算额外的时间。完美的!谢谢!感谢这里的每一个人,我更了解它是如何工作的!
  • 当且仅当 pTemp 不为空时,我们进入 while..loop 的主体。这意味着我们找到了字符,所以我们增加了计数。因为我们想寻找下一个字符,我们增加 pTemp 以指向我们刚刚找到的那个字符之后的字符......然后 while..loop 的顶部继续搜索它,并在下一次调用 strchr( ) 在我们刚刚找到的字符之后开始一个字符。如果它找到另一个,我们再次进入while循环的主体,如果没有,我们不重新进入它。
【解决方案2】:

你总是从头开始。难怪你永远不会结束。

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

【讨论】:

  • 我很想这样做,但本章都是关于字符串函数的。 (叹气)
  • 更好更快的方法!
【解决方案3】:

strchr 返回一个指针,指向 pString 中字符 c 的第一次出现。

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

你可能想在这里做一些指针运算来解决你的问题;)

【讨论】:

    【解决方案4】:

    strchr() 总是在同一个地方寻找,它不会在字符串中前进......

    试试这个修改traverse使用字符串的长度,和一个简单的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;
    

    【讨论】:

    • 为什么要使用 strlen()?这增加了对字符串的额外迭代,只是为了得到它的长度。完全删除变量len,而不是i&lt;len 使用pString[i]!='\0'(因为所有strlen 所做的都是寻找尾随的NUL)。
    • @JohnH - 使用strlen() 只是一种方法。它有效,你的也有效。我不是想打破这里的陆地速度记录,只是回答这个问题。 :)(见编辑)
    • 谢谢!希望对您有所帮助。
    猜你喜欢
    • 2014-04-24
    • 2012-12-18
    • 2020-02-21
    • 2012-02-12
    • 2020-04-04
    • 2023-02-04
    相关资源
    最近更新 更多