C - 检查string是否是另一个字符串的子串

时间:2010-04-12 18:35:22

标签: c string substring

我需要编写一个程序,它接受两个字符串作为参数,并检查第二个字符串是否是第一个字符串的子字符串。我需要在不使用任何特殊库函数的情况下完成它。我创建了这个实现,但我认为只要两个字符串中有一个相同的字母,它就会返回true。你能帮帮我吗?我不确定我做错了什么:

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

int my_strstr( char const *s, char const *sub ) {
    char const *ret = sub;

    int r = 0;
    while ( ret = strchr( ret, *sub ) ) {
        if ( strcmp( ++ret, sub+1 ) == 0 ){
            r = 1;
        }
        else{
            r = 0;
        }        
    }
    return r;
}

int main(int argc, char **argv){

    if (argc != 3) {
        printf ("Usage: check <string one> <string two>\n");
    }
    int result = my_strstr(argv[1], argv[2]);

    if(result == 1){
        printf("%s is a substring of %s\n", argv[2], argv[1]);
    } else{
        printf("%s is not a substring of %s\n", argv[2], argv[1]);
    }
    return 0;
}

6 个答案:

答案 0 :(得分:3)

您撰写strstr的方法存在根本缺陷。让我们来看看你写的内容:

char const *ret = sub;

int r = 0;
while ( ret = strchr( ret, *sub ) ) {
    if ( strcmp( ++ret, sub+1 ) == 0 ){
        r = 1;
    }
    else{
        r = 0;
    }        
}
return r;

首先,由于您初始化ret以指向sub,因此您将sub与自身进行比较,而不会查看s。但是我们假设您要将ret初始化为s ...

ret = strchr( ret, *sub )sub中找到ret的下一个字符的位置,然后前进ret,以便从该字符开始。

然后,执行strcmp( ++ret, sub+1 ),确定从ret的下一个字符开始的字符串是否等于从sub的下一个字符开始的字符串,然后前进{{ 1}}从下一个字符开始(无论测试是真还是假)。

显然,这种逻辑没有做你想要的。实际做的是确定子字符串是否等于字符串ret,或者是否在字符串s end 处找到,并且不包含重复的字母。

以下是您想要的算法的概要:

  1. s中找到sub的第一个字符的位置。如果没有找到,请返回false。
  2. 更新s以便从此位置开始
  3. 假设s的长度为sub,请测试n的第一个n个字符是否与s匹配(小心不要超过结尾sub s)。如果是这样,返回true。否则,将s提前一个字符并循环。
  4. 请注意,除了第一个之外,您永远不应该在sub中搜索任何字符。我们的想法是使用sub的第一个字符来查找subs潜在起始位置,然后检查子字符串sub实际存在于那里。如果它不在那里,你想要丢弃整个s直到那一点,然后通过试图找到下一个潜在的起始位置重新开始。

答案 1 :(得分:1)

好吧,你不应该修改ret中的my_strstr。并且strcmp不比较子字符串,它比较字符串。您可能想要使用strncmp

答案 2 :(得分:0)

看起来你正在char * sub中搜索char * sub:

int my_strstr( char const *s, char const *sub ) {
char const *ret = sub;

你不应该设置ret到s?

strcmp也比较字符串,而不是子字符串,因此strcmp(“abcde”,“abc”)返回false。你可能想要strncmp,它也需要一个指定长度的整数。

答案 3 :(得分:0)

何时

ret = strchr( ret, *sub )
首先遇到

ret == sub。因此,strchr(ret, *sub)正在搜索 ret ret的第一个字符的第一个匹配项。哪个会返回ret

因此,ret保持不变。

接下来,

strcmp( ++ret, sub+1 ) == 0 

ret仍然等于sub,因此上述声明为 true

你得到1作为回报。

答案 4 :(得分:0)

以不同的方式打破这项任务可能会有所帮助。该任务有两个关键部分:1)找到潜在子串匹配的起点和2)测试该起点是否确实是匹配的子串。因此,将其实现为两个功能。

首先,创建一个函数,确定两个字符串是否完全相同。这应该相对容易编码,只需将第一个字母与第一个字母进行比较,将第二个字母与第二个字母进行比较,等等。如果发现两个不匹配,则返回false。如果将其设置为其中一个字符串的末尾,则返回true。如果您被允许使用strncmp,那么这只是(strncmp(a, b, strlen(b)) == 0)(假设b始终是较短的字符串)。

其次,创建一个循环遍历字符串的函数,查找某个字母。每当它找到该字母时,它会调用一个函数并将指针传递给字符串中的那个字母。换句话说,如果你调用了my_function("This is a sample string", 's'),那么函数应该遍历字符串,找到字母's'的所有四个实例,并使用指向字符串中该字母的指针来调用函数。在这种情况下,您将调用的函数是上一段中描述的函数。

使用此细分,只要对子函数的任何调用返回“true”,您将返回“true”,否则如果将其设置为输入字符串的末尾,则返回“false”。< / p>

答案 5 :(得分:0)

char const *ret = sub;

int r = 0;
while ( ret = strchr( ret, *sub ) ) {

ret正在存储子数组的地址  声明strchr(ret,*sub)sub中的值与ret中存储的地址进行比较 这是否有效(这种比较是对还是不对) 请回答任何人......