strstr()的字符串问题

时间:2018-02-05 20:39:02

标签: c visual-studio

我需要计算一个较小的字符串在strstr()的较大字符串中的次数, 我知道当使用strstr()时,它会将指针放在较大字符串中找到较小字符串的位置。但是我不知道应该写什么样的循环来检查这个较大的字符串在这个较大的字符串中显示多少次?所以在这种情况下,正确的答案是3。

我的代码:

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

int count_substr(const char *str, const char *sub) {
    int i = 0;
    int res;
    res = strstr(str, sub);
    if (res) {
        i++;
    }
    else {
        i = i;
    }
    return i;

}
int main(void) {
    char lol[] = "one two one twotwo three";
    char asd[] = "two";
    int ret;
    ret = count_substr(lol, asd);
    printf("%d", ret);


}

3 个答案:

答案 0 :(得分:2)

您可以像这样使用while循环:

int count_substr(const char *str, const char *sub) {
    int cnt = 0;
    char *found;

    while(found = strstr(str, sub))
    {
        cnt++;
        str = found + 1;
    }

    return cnt;
}

有趣的是:

str = found + 1;

因为您对找到的子字符串之前的字符不感兴趣,所以 可以安全地忽略它们并将str推进到找到后的下一个字符 子。当没有找到子字符串时,strstr最终会返回NULLstr[0] == 0到达字符串末尾之后。

修改

我把它放在答案中,因为评论部分远非受限制 更长的评论。

found是指向char的指针。它是否指向单个char对象 或者到字节序列的开头或字符串的开头,取决于 上下文。这里的上下文是found被赋值为返回值 函数strstr

  

man strstr

#include <string.h>

char *strstr(const char *haystack, const char *needle);
     

<强>描述

     

strstr()函数查找字符串needle中第一次出现的子串haystack。   不比较终止空字节('\0')。

     

返回值

     

[此函数返回]指向所定位子字符串开头的指针,如果找不到子字符串,则返回NULL

成功strstr返回指向子字符串所在源位置的指针 找到。因此found会返回指向"two one twotwo three"的指针。

found + 1是指针算术,它与将返回的&(found[1])相同 指向序列中下一个char的指针。 found + 1会指出 "wo one twotwo three"和此指针将分配给str,以便{ str指向找到的子字符串后的 next 字符。

如果我不这样做 那个,我会创建一个无限循环,因为strstr会保留 一遍又一遍地返回相同的子串。

因此,下次执行strstr(str, sub)时,found会指向 "twotwo three"found + 1将返回指向"wotwo three"的指针,并且 等等。

如果找不到子字符串,它将返回NULL循环结束。在 那一点found也指向NULL无关紧要。

答案 1 :(得分:1)

函数strstr()返回char指针,而不是int,因此要赋予其返回值的变量应为char *类型。您可以使用此值循环一个字符串并查找其中的子字符串数量; while循环就足够了:

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

int count_substr(const char *str, const char *sub)
{
    int i = 0;
    size_t sub_len = strlen(sub);
    const char *res = strstr(str, sub);
    while (res)
    {
        i++;
        str = res + sub_len;
        res = strstr(str, sub);
    }
    return i;
}

int main(void) 
{
    char lol[] = "one two one twotwo three";
    char asd[] = "two";
    int ret = count_substr(lol, asd);
    printf("ret: %d\n", ret);
    return 0;
}

答案 2 :(得分:0)

res = strstr(str, sub);

变量res应声明为char *res;而不是int res;,因为函数:strstr()会返回char*而不是int。此错误导致编译器输出警告消息。您应该在发布问题之前看到该警告并进行了更正。

这是什么:

i = i;

应该完成?

以下提议的代码:

  1. 记录了为什么要包含每个头文件
  2. 正确计算字符串中包含子字符串的次数,包括任何重叠的子字符串。
  3. 适当地包括缩进,水平间距,垂直间距等,以便于阅读和理解
  4. 使用有意义的变量名称
  5. 现在,建议的代码:

    #include <stdio.h>   // printf()
    #include <string.h>  // strstr()
    
    // prototypes
    int count_substr( const char *str, const char *sub );
    
    
    int main(void)
    {
        char lol[] = "one two one twotwo three";
        char asd[] = "two";
    
        int ret = count_substr( lol, asd );
        printf( "%d\n", ret );   // '\n' so immediately displayed on terminal
    }
    
    
    int count_substr( const char *str, const char *sub )
    {
        int count = 0;
        int index = 0;
        char *oldres = NULL;
        char *newres = NULL;
    
        do
        {
            newres = strstr( &str[index], sub );
            index++;
    
            if( newres != oldres && newres )
                count++;
    
            oldres = newres;
        } while( oldres );
    
        return count;
    }