在C语言中检查一个字符串是否为另一个字符串的子串

236

我正在尝试在 C 语言中检查一个字符串是否包含子字符串,例如:

char *sent = "this is my sample example";
char *word = "sample";
if (/* sentence contains word */) {
    /* .. */
}

在C++中,除了string::find,还有什么可以使用的东西?


8
你需要的是:char *strstr(const char *s1, const char *s2) -- 找到字符串s2在字符串s1中第一次出现的位置。 - JonH
@JonH 我以为这只适用于字符。我会接受下面的答案之一,谢谢。 - none
你把它和 strchr 混淆了。 - JonH
1
@JonH 啊,现在明白了。你真棒,再次感谢。 - none
12个回答

377
if (strstr(sent, word) != NULL) {
    /* ... */
}

请注意,如果在 sent 中找到了单词 wordstrstr 将返回指向该单词开头的指针。


2
你也可以移除“!= NULL”,我认为strstr返回0或1。 - Simon MILHAU
75
strstr 返回一个指针;当我测试指针时,我喜欢表述得更加明确。 - nneonneo
3
“false” 意为“假”,对应的数字是 “0”。 - Jack
19
供将来参考;strcasestr 的作用与 strstr 相同,但它忽略大小写。 - amonett
2
@NgoThanhNhan 你可以在这里看到glibc中strstr的实现:https://github.com/lattera/glibc/blob/master/string/strstr.c。它比朴素的实现要优化得多,可能比一个直接定义的函数更快。然而,当有疑问时,请进行基准测试。 - nneonneo
显示剩余7条评论

39

使用strstr函数就可以实现这个功能。

https://cplusplus.com/reference/cstring/strstr

因此,你可以这样写:

char *sent = "this is my sample example";
char *word = "sample";

char *pch = strstr(sent, word);

if(pch)
{
    ...
}

13

尝试使用指针...

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

int main()
{

  char str[] = "String1 subString1 Strinstrnd subStr ing1subString";
  char sub[] = "subString";

  char *p1, *p2, *p3;
  int i=0,j=0,flag=0;

  p1 = str;
  p2 = sub;

  for(i = 0; i<strlen(str); i++)
  {
    if(*p1 == *p2)
      {
          p3 = p1;
          for(j = 0;j<strlen(sub);j++)
          {
            if(*p3 == *p2)
            {
              p3++;p2++;
            } 
            else
              break;
          }
          p2 = sub;
          if(j == strlen(sub))
          {
             flag = 1;
            printf("\nSubstring found at index : %d\n",i);
          }
      }
    p1++; 
  }
  if(flag==0)
  {
       printf("Substring NOT found");
  }
return (0);
}

8
您可以尝试以下代码来查找子字符串的存在并提取并打印它:
#include <stdio.h>
#include <string.h>

int main(void)
{
    char mainstring[]="The quick brown fox jumps over the lazy dog";
    char substring[20], *ret;
    int i=0;
    puts("enter the sub string to find");
    fgets(substring, sizeof(substring), stdin);
    substring[strlen(substring)-1]='\0';
    ret=strstr(mainstring,substring);
    if(strcmp((ret=strstr(mainstring,substring)),substring))
    {
        printf("substring is present\t");
    }
    printf("and the sub string is:::");

    for(i=0;i<strlen(substring);i++)
    {
            printf("%c",*(ret+i));

    }
    puts("\n");
    return 0;
}

测试if(strcmp((ret=strstr(mainstring,substring)),substring))是不正确的:它只匹配substring如果它是mainstring的后缀。函数的其余部分是一种复杂的方式来编写printf("and the sub string is:::%s\n", substring); - chqrlie

3

以下是我个人谦虚的(区分大小写)解决方案:

uint8_t strContains(char* string, char* toFind)
{
    uint8_t slen = strlen(string);
    uint8_t tFlen = strlen(toFind);
    uint8_t found = 0;

    if( slen >= tFlen )
    {
        for(uint8_t s=0, t=0; s<slen; s++)
        {
            do{

                if( string[s] == toFind[t] )
                {
                    if( ++found == tFlen ) return 1;
                    s++;
                    t++;
                }
                else { s -= found; found=0; t=0; }

              }while(found);
        }
        return 0;
    }
    else return -1;
}

结果

strContains("this is my sample example", "th") // 1
strContains("this is my sample example", "sample") // 1
strContains("this is my sample example", "xam") // 1
strContains("this is my sample example", "ple") // 1
strContains("this is my sample example", "ssample") // 0
strContains("this is my sample example", "samplee") // 0
strContains("this is my sample example", "") // 0
strContains("str", "longer sentence") // -1
strContains("ssssssample", "sample") // 1
strContains("sample", "sample") // 1

在ATmega328P(使用avr8-gnu-toolchain-3.5.4.1709)上进行了测试;)


2

该代码实现了搜索工作原理的逻辑(其中一种方式),而不使用任何现成的函数:

public int findSubString(char[] original, char[] searchString)
{
    int returnCode = 0; //0-not found, -1 -error in imput, 1-found
    int counter = 0;
    int ctr = 0;
    if (original.Length < 1 || (original.Length)<searchString.Length || searchString.Length<1)
    {
        returnCode = -1;
    }

    while (ctr <= (original.Length - searchString.Length) && searchString.Length > 0)
    {
        if ((original[ctr]) == searchString[0])
        {
            counter = 0;
            for (int count = ctr; count < (ctr + searchString.Length); count++)
            {
                if (original[count] == searchString[counter])
                {
                    counter++;
                }
                else
                {
                    counter = 0;
                    break;
                }
            }
            if (counter == (searchString.Length))
            {
                returnCode = 1;
            }
        }
        ctr++;
    }
    return returnCode;
}

虽然这段代码可能回答了问题,但是提供关于为什么和/或如何回答问题的额外上下文可以提高其长期价值。 - JAL
3
公共的?.长度?这肯定不是C语言。 - Jetski S-type
1
我认为这是C#,从Length的命名来看。 - Fox

2
这个更简单的代码可以实现相同的效果:为什么要使用它们:
int main(void)
{

    char mainstring[]="The quick brown fox jumps over the lazy dog";
    char substring[20];
    int i=0;
    puts("enter the sub string to find");
    fgets(substring, sizeof(substring), stdin);
    substring[strlen(substring)-1]='\0';
    if (strstr(mainstring,substring))
    {
            printf("substring is present\t");
    }
    printf("and the sub string is:::");
    printf("%s",substring,"\n");
   return 0;
}

但是棘手的部分在于报告子字符串在原始字符串中的起始位置...


非常感谢您,先生。这个解决方案太简单易懂了。非常感谢。 - user13899130

2
以下是对找到的子字符串第一个字符位置进行报告的方法:
请将上述代码中的这一行替换为:
printf("%s",substring,"\n");

使用:

printf("substring %s was found at position %d \n", substring,((int) (substring - mainstring)));

1
我相信我有最简单的答案。在这个程序中,您不需要使用string.h库或stdbool.h库。只需使用指针和指针算术运算就可以帮助您成为更好的C程序员。
如果未找到子字符串,则只需返回0表示False,如果在整个字符串“str”中找到了子字符串“sub”,则返回1表示True:
#include <stdlib.h>

int is_substr(char *str, char *sub)
{
  int num_matches = 0;
  int sub_size = 0;
  // If there are as many matches as there are characters in sub, then a substring exists.
  while (*sub != '\0') {
    sub_size++;
    sub++;
  }

  sub = sub - sub_size;  // Reset pointer to original place.
  while (*str != '\0') {
    while (*sub == *str && *sub != '\0') {
      num_matches++;
      sub++;
      str++;
    }
    if (num_matches == sub_size) {
      return 1;
    }
    num_matches = 0;  // Reset counter to 0 whenever a difference is found. 
    str++;
  }
  return 0;
}

1
缓冲区溢出怎么办? - alx - recommends codidact
这里会发生缓冲区溢出吗? - django_moose
首先,您不知道缓冲区的大小。 想象一下这个“简单”的代码:char a [3] =“asd”; char b [2] =“as”; is_substr(a,b); 输入字符串没有以NUL结尾,因此您会越界数组。 - alx - recommends codidact
如果任何一个缓冲区的大小为0(大小为0的数组不存在,但这是可能的,并且从函数使用者的角度来看也是合法的):char a[4] = "asd"; char b[3]= "as"; is_substr(a+4, b); - alx - recommends codidact
这就是为什么 strnstr() 存在的原因(至少在 libbsd 上)。 - alx - recommends codidact

1

使用C语言 - 不使用内置函数

string_contains()函数完成了大部分工作,并返回基于1的索引。其余代码是驱动程序和辅助程序。

将指针分配给主字符串和子字符串,当匹配时增加子字符串指针,当子字符串指针等于子字符串长度时停止循环。

read_line() - 一个小型的额外代码,用于读取用户输入而不预定义输入大小。

#include <stdio.h>
#include <stdlib.h>

int string_len(char * string){
  int len = 0;
  while(*string!='\0'){
    len++;
    string++;
  }
  return len;
}

int string_contains(char *string, char *substring){
  int start_index = 0;
  int string_index=0, substring_index=0;
  int substring_len =string_len(substring);
  int s_len = string_len(string);
  while(substring_index<substring_len && string_index<s_len){
    if(*(string+string_index)==*(substring+substring_index)){
      substring_index++;
    }
    string_index++;
    if(substring_index==substring_len){
      return string_index-substring_len+1;
    }
  }

  return 0;

}

#define INPUT_BUFFER 64
char *read_line(){
  int buffer_len = INPUT_BUFFER;
  char *input = malloc(buffer_len*sizeof(char));
  int c, count=0;

  while(1){
    c = getchar();

    if(c==EOF||c=='\n'){
      input[count]='\0';
      return input;
    }else{
      input[count]=c;
      count++;
    }

    if(count==buffer_len){
      buffer_len+=INPUT_BUFFER;
      input = realloc(input, buffer_len*sizeof(char));
    }

  }
}

int main(void) {
  while(1){
    printf("\nEnter the string: ");
    char *string = read_line();
    printf("Enter the sub-string: ");
    char *substring = read_line(); 
    int position = string_contains(string,substring);
    if(position){ 
      printf("Found at position: %d\n", position);
    }else{
      printf("Not Found\n");
    }
  }
  return 0;
}

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