C의 문자열에 하위 문자열이 있는지 확인


169

문자열에 C의 하위 문자열이 포함되어 있는지 확인하려고합니다.

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

string::findC ++ 대신 사용할 것이 무엇입니까 ?


7
char * strstr (const char * s1, const char * s2)-문자열 s1에서 문자열 s2의 첫 항목을 찾습니다.
JonH

@ JonH 나는 그것이 문자에 대해서만 작동한다고 생각했다. 아래 답변 중 하나를 수락하겠습니다. 감사합니다.
none

당신은 그것을 섞고 strchr있습니다.
JonH

@JonH 아, 지금 이해가 되네요. 다시 한 번 감사드립니다.
none

답변:


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

참고 strstr로 단어의 시작에 대한 포인터를 반환 sent단어가있는 경우 word발견된다.


1
당신은 또한 "! = NULL"을 제거 할 수 있습니다, 내가 생각하지 않는 strstr 반환 0 또는 1
사이먼 MILHAU

44
strstr포인터를 반환합니다. 나는 포인터를 테스트 할 때 명시 적 인 것을 좋아합니다.
nneonneo

3
... 그리고 false이다0

8
내 미래의 참조에 대한 의견; strcasestr같은 일을하지만 대소 문자를 무시합니다.
amonett

2
@NgoThanhNhan strstrglibc에서 github.com/lattera/glibc/blob/master/string/strstr.c 구현을 볼 수 있습니다 . 순진한 구현보다 훨씬 최적화되어 있으며 간단한 자체 정의 함수보다 빠릅니다. 그럼에도 불구하고, 의심스러운 경우 벤치마킹하십시오.
nneonneo


12

포인터를 사용해보십시오 ...

#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

5

이 코드는 기성 기능을 사용하지 않고 검색이 작동하는 방식 (한 방법 중 하나)의 논리를 구현합니다.

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

그리고 찾은 하위 문자열에서 첫 번째 문자의 위치를보고하는 방법은 다음과 같습니다.

위 코드에서이 줄을 바꾸십시오 :

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

와:

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

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);)에서 테스트


1

이 간단한 코드에서도 마찬가지입니다.

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

그러나 까다로운 부분은 원래 문자열에서 하위 문자열이 시작되는 위치를보고하는 것입니다 ...


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

나는 가장 간단한 대답이 있다고 생각합니다. 이 프로그램에는 string.h 라이브러리 나 stdbool.h 라이브러리가 필요하지 않습니다. 포인터와 포인터 산술을 사용하면 더 나은 C 프로그래머가 될 수 있습니다.

False (하위 문자열을 찾을 수 없음)의 경우 0을, True (예 : 하위 문자열 "sub"가 전체 문자열 "str"내에 있음) 인 경우 1을 반환합니다.

#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
버퍼 오버런은 어떻습니까?
Cacahuete Frito

여기서 버퍼 오버플로는 어떻게 발생합니까?
user9679882

시작하려면 버퍼의 크기를 모릅니다. 이 '간단한'코드를 상상해보십시오. char a[3] = "asd"; char b[2] = "as"; is_substr(a, b);입력 문자열은 NUL로 끝나지 않으므로 배열을 오버런합니다.
Cacahuete Frito

버퍼 중 하나의 크기가 0 인 경우 (크기 0의 배열은 존재하지 않지만, 이것이 가능하며 함수의 사용자 관점에서 합법적 임) :char a[4] = "asd"; char b[3]= "as"; is_substr(a+4, b);
Cacahuete Frito

그리고 그것이 strnstr()존재 하는 이유입니다 (적어도 libbsd에서)
Cacahuete Frito

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

-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++;
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.