Kiểm tra chuỗi con tồn tại trong một chuỗi trong C


169

Tôi đang cố kiểm tra xem một chuỗi có chứa một chuỗi con trong C như không:

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

Cái gì để sử dụng thay vì string::findtrong C ++?


7
Bạn muốn: char * strstr (const char * s1, const char * s2) - định vị lần xuất hiện đầu tiên của chuỗi s2 trong chuỗi s1.
JonH

@JonH Tôi nghĩ rằng chỉ hoạt động cho ký tự. Tôi sẽ chấp nhận một trong những câu trả lời dưới đây, cảm ơn ..
không có

bạn đang trộn nó lên với strchr.
JonH

@JonH ahh đúng rồi, nó có ý nghĩa bây giờ. bạn thật tuyệt, cảm ơn lần nữa ..
không

Câu trả lời:


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

Lưu ý rằng strstrtrả về một con trỏ đến đầu của từ sentnếu wordtìm thấy từ đó .


1
Bạn cũng có thể xóa "! = NULL", tôi nghĩ strstr trả về 0 hoặc 1
Simon MILHAU

44
strstrtrả về một con trỏ; Tôi thích rõ ràng khi tôi kiểm tra con trỏ.
nneonneo

3
... và false0
Jack

8
Nhận xét để tham khảo trong tương lai của tôi; strcasestrlàm điều tương tự nhưng bỏ qua trường hợp.
amonett

2
@NgoThanhNhan Bạn có thể xem việc triển khai strstrtrong glibc tại đây: github.com/lattera/glibc/blob/master/opes/strstr.c . Nó được tối ưu hóa hơn nhiều so với triển khai ngây thơ - và có thể nhanh hơn chức năng tự xác định đơn giản. Tuy nhiên, khi nghi ngờ, điểm chuẩn.
nneonneo


12

Cố gắng sử dụng con trỏ ...

#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

Bạn có thể thử cái này cho cả việc tìm sự hiện diện của chuỗi con và để trích xuất và in nó:

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

Thử nghiệm if(strcmp((ret=strstr(mainstring,substring)),substring))không chính xác: nó chỉ khớp substringnếu nó là hậu tố của mainstring. Phần còn lại của hàm là một cách viết phức tạp printf("and the sub string is:::%s\n", substring);.
chqrlie

5

Mã này thực hiện logic về cách hoạt động của tìm kiếm (một trong những cách) mà không sử dụng bất kỳ chức năng làm sẵn nào:

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

Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do và / hoặc cách mã này trả lời câu hỏi cải thiện giá trị lâu dài của nó.
JAL

3

Và đây là cách báo cáo vị trí của ký tự đầu tiên trong chuỗi con tìm thấy:

Thay thế dòng này trong mã trên:

printf("%s",substring,"\n");

với:

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

3

Giải pháp khiêm tốn (trường hợp nhạy cảm) của riêng tôi:

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

Các kết quả

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

Đã thử nghiệm trên ATmega328P (avr8-gnu-toolchain-3.5.4.1709);)


1

Điều tương tự sẽ được thực hiện với mã đơn giản hơn này: Tại sao nên sử dụng các mã này:

int main(void)
{

    char mainstring[]="The quick brown fox jumps over the lazy dog";
    char substring[20];
    int i=0;
    puts("enter the sub stirng 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;
}

Nhưng phần khó khăn sẽ là báo cáo tại vị trí nào trong chuỗi gốc, chuỗi con bắt đầu ...


1
My code to find out if substring is exist in string or not 
// input ( first line -->> string , 2nd lin ->>> no. of queries for substring
following n lines -->> string to check if substring or not..

#include <stdio.h>
int len,len1;
int isSubstring(char *s, char *sub,int i,int j)
{

        int ans =0;
         for(;i<len,j<len1;i++,j++)
        {
                if(s[i] != sub[j])
                {
                    ans =1;
                    break;
                }
        }
        if(j == len1 && ans ==0)
        {
            return 1;
        }
        else if(ans==1)
            return 0;
return 0;
}
int main(){
    char s[100001];
    char sub[100001];
    scanf("%s", &s);// Reading input from STDIN
    int no;
    scanf("%d",&no);
    int i ,j;
    i=0;
    j=0;
    int ans =0;
    len = strlen(s);
    while(no--)
    {
        i=0;
        j=0;
        ans=0;
        scanf("%s",&sub);
        len1=strlen(sub);
        int value;
        for(i=0;i<len;i++)
        {
                if(s[i]==sub[j])
                {
                    value = isSubstring(s,sub,i,j);
                    if(value)
                    {
                        printf("Yes\n");
                        ans = 1;
                        break;
                    }
                }
        }
        if(ans==0)
            printf("No\n");

    }
}

1

Tôi tin rằng tôi có câu trả lời đơn giản nhất. Bạn không cần thư viện string.h trong chương trình này, cũng không phải thư viện stdbool.h. Chỉ cần sử dụng con trỏ và số học con trỏ sẽ giúp bạn trở thành một lập trình viên C giỏi hơn.

Chỉ cần trả về 0 cho Sai (không tìm thấy chuỗi con) hoặc 1 cho Đúng (có, một chuỗi con "phụ" được tìm thấy trong chuỗi tổng thể "str"):

#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
Điều gì về tràn bộ đệm?
Cacahuete Frito 18/03/19

Làm thế nào sẽ tràn bộ đệm xảy ra ở đây?
dùng9679882

Để bắt đầu, bạn không biết kích thước của bộ đệm. Hãy tưởng tượng mã 'đơn giản' này: char a[3] = "asd"; char b[2] = "as"; is_substr(a, b);Các chuỗi đầu vào không bị chấm dứt NUL, do đó bạn tràn ngập mảng.
Cacahuete Frito

Nếu bất kỳ bộ đệm nào có kích thước 0 (mảng kích thước 0 không tồn tại, nhưng điều này là có thể, và cũng hợp pháp theo quan điểm của người sử dụng chức năng):char a[4] = "asd"; char b[3]= "as"; is_substr(a+4, b);
Cacahuete Frito 20/03/19

Và đó là lý do strnstr()tồn tại (ít nhất là trên libbsd)
Cacahuete Frito 20/03/19

1

Sử dụng C - Không có chức năng tích hợp

string_contains () thực hiện tất cả các công việc nặng và trả về 1 chỉ số dựa trên. Phần còn lại là mã trình điều khiển và người trợ giúp.

Gán một con trỏ cho chuỗi chính và chuỗi con, tăng con trỏ chuỗi con khi khớp, dừng lặp khi con trỏ chuỗi con bằng với độ dài chuỗi con.

read_line () - Một mã thưởng nhỏ để đọc đầu vào của người dùng mà không xác định trước kích thước của đầu vào mà người dùng nên cung cấp.

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

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

int findSubstr(char *inpText, char *pattern);
int main()
{
    printf("Hello, World!\n");
    char *Text = "This is my sample program";
    char *pattern = "sample";
    int pos = findSubstr(Text, pattern);
    if (pos > -1) {
        printf("Found the substring at position %d \n", pos);
    }
    else
        printf("No match found \n");

    return 0;
}

int findSubstr(char *inpText, char *pattern) {
    int inplen = strlen(inpText);
    while (inpText != NULL) {

        char *remTxt = inpText;
        char *remPat = pattern;

        if (strlen(remTxt) < strlen(remPat)) {
            /* printf ("length issue remTxt %s \nremPath %s \n", remTxt, remPat); */
            return -1;
        }

        while (*remTxt++ == *remPat++) {
            printf("remTxt %s \nremPath %s \n", remTxt, remPat);
            if (*remPat == '\0') {
                printf ("match found \n");
                return inplen - strlen(inpText+1);
            }
            if (remTxt == NULL) {
                return -1;
            }
        }
        remPat = pattern;

        inpText++;
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.