【问题标题】:C - check if string is a substring of another stringC - 检查字符串是否是另一个字符串的子字符串
【发布时间】:2011-02-07 03:24:12
【问题描述】:

我需要编写一个程序,它接受两个字符串作为参数,并检查第二个字符串是否是第一个字符串的子字符串。我需要在不使用任何特殊库函数的情况下做到这一点。我创建了这个实现,但我认为只要两个字符串中有一个相同的字母,它就会始终返回 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;
}

【问题讨论】:

  • 如果您“需要在不使用任何特殊库函数的情况下执行此操作”,则不应使用 strchr 和 strcmp。实际上 strcmp 就是你的问题所在。
  • @stmax:这些只是普通库函数。他们没有什么特别的:)
  • @Daniel:如果strchr()strcmp()是普通的,那么strstr()也是...
  • @Jonathan Leffler:当然。我确实指出,实际上没有“特殊”库函数——只是库函数,句号。

标签: c string substring


【解决方案1】:

您编写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 )ret 中找到sub 的下一个字符的位置,然后前进ret,使其从该字符开始。

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

显然,这种逻辑并没有按照您的意愿行事。它实际上要做的是确定子字符串是否等于字符串s,或者在字符串send 处找到并且不包含重复的字母。

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

  1. s 中查找sub 的第一个字符的位置。如果没有找到,返回 false。
  2. 更新s,让它从这个位置开始
  3. 假设sub的长度是n,测试s的第一个n字符是否匹配sub(注意不要跑到s的末尾)。如果是,则返回 true。否则,将s 前进一个字符并循环。

请注意,您永远不应该在sub 中搜索除第一个以外的任何字符。想法是使用sub 的第一个字符在s 中找到sub潜在 起始位置,然后检查子字符串sub 是否确实存在于那里。如果它不存在,您需要丢弃整个 s 直到该点,然后通过尝试找到下一个可能的起始位置重新开始。

【讨论】:

    【解决方案2】:

    好吧,你不应该在my_strstr 中修改retstrcmp 不比较子字符串,它比较字符串。你可能想使用strncmp

    【讨论】:

      【解决方案3】:

      您似乎在 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 也需要一个整数来指定长度。

      【讨论】:

        【解决方案4】:

        ret = strchr( ret, *sub )
        

        第一次遇到,ret == sub。因此,strchr(ret, *sub) 正在搜索 ret 的第一个字符在 ret 中的第一次出现。这将返回ret

        所以,ret 保持不变。

        接下来,

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

        ret 仍然等于sub,所以上面的说法是true

        你会得到1 作为回报。

        【讨论】:

          【解决方案5】:

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

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

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

          使用此细分,只要对子函数的任何调用返回“true”,您将返回“true”,或者如果您到达输入字符串的末尾,您将返回“false”。

          【讨论】:

            【解决方案6】:
            char const *ret = sub;
            
            int r = 0;
            while ( ret = strchr( ret, *sub ) ) {
            

            ret 是存储子数组的地址,在 while 语句strchr(ret,*sub)sub 中的值与ret 中存储的地址进行比较 这是否可行(这个比较是否正确) 请回答任何人...

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-05-11
              • 2013-05-12
              • 1970-01-01
              • 2022-07-01
              • 1970-01-01
              • 2020-10-14
              • 2011-12-16
              相关资源
              最近更新 更多