C'de bir dizede alt dize olup olmadığını kontrol edin


170

Bir dize C gibi bir alt dize içerip içermediğini kontrol etmeye çalışıyorum:

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

string::findC ++ yerine kullanılacak bir şey nedir ?


7
İstediğiniz: char * strstr (const char * s1, const char * s2) - s2 dizesinin s1 dizesindeki ilk oluşumunu bulur.
JonH

@JonH Bunun sadece karakterlerde işe yaradığını düşündüm. Aşağıdaki cevaplardan birini kabul edeceğim, teşekkürler ..
hiçbiri

ile karıştırıyorsunuz strchr.
JonH

@JonH ahh doğru, şimdi mantıklı. harikasın, tekrar teşekkürler ..
hiçbiri

Yanıtlar:


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

strstrSözcük sentbulunursa, sözcüğün başına bir işaretçi döndürdüğünü unutmayın word.


1
Ayrıca "! = NULL" kaldırabilirsiniz, strstr 0 veya 1 döndürür düşünüyorum
Simon MILHAU

44
strstrbir işaretçi döndürür; İşaretçiler için test yaparken açık olmayı seviyorum.
nneonneo

3
... ve falsebir0
Jack

8
Gelecekteki referansım için yorum yapın; strcasestraynı şeyi yapar ama davayı görmezden gelir.
amonett

2
@NgoThanhNhan glibc'de uygulanmasını strstrburada görebilirsiniz: github.com/lattera/glibc/blob/master/string/strstr.c . Saf bir uygulamadan çok daha optimize edilmiştir ve muhtemelen basit bir kendinden tanımlı fonksiyondan daha hızlıdır. Yine de, şüpheye düştüğünüzde kıyaslama.
nneonneo


12

İşaretçiler kullanmaya çalışın ...

#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

Bunu hem alt dizenin varlığını bulmak hem de çıkarmak ve yazdırmak için deneyebilirsiniz:

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

Test if(strcmp((ret=strstr(mainstring,substring)),substring))yanlış: yalnızca substringson eki olduğunda eşleşir mainstring. Fonksiyonun geri kalanı yazmanın kıvrımlı bir yoludur printf("and the sub string is:::%s\n", substring);.
chqrlie

5

Bu kod, herhangi bir hazır işlev kullanmadan aramanın nasıl çalıştığının (yollardan biri) mantığını uygular:

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

Bu kod soruyu cevaplayabilirken, bu kodun soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini arttırır.
JAL

3

Ve bulunan alt dizeden ilk karakterin konumunu nasıl bildireceğiniz aşağıda açıklanmıştır:

Bu satırı yukarıdaki kodda değiştirin:

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

ile:

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

3

Kendi mütevazı (büyük / küçük harfe duyarlı) çözümüm:

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

Sonuçlar

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'de test edildi (avr8-gnu-toolchain-3.5.4.1709);)


1

Aynı şey bu daha basit kodla da gerçekleştirilecek: Neden bunları kullanmalısınız:

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

Ancak zor kısım, alt dizenin orijinal dizede hangi konumda başladığını rapor etmek olacaktır ...


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

En basit cevaba sahip olduğuma inanıyorum. Bu programda string.h kütüphanesine veya stdbool.h kütüphanesine ihtiyacınız yoktur. İşaretçileri ve işaretçi aritmetiği kullanmak daha iyi bir C programcısı olmanıza yardımcı olacaktır.

False için 0 (alt dize bulunamadı) veya True için 1 döndürün (evet, "str" ​​genel dizesinde bir alt dize "sub" bulunur):

#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
Arabellek taşması ne olacak?
Cacahuete Frito

Burada arabellek taşması nasıl gerçekleşir?
user9679882

Başlamak için tamponun boyutunu bilmiyorsunuz. Bu 'basit' kodu düşünün: char a[3] = "asd"; char b[2] = "as"; is_substr(a, b);Giriş dizeleri NUL ile sonlandırılmadığından diziyi aşarsınız.
Cacahuete Frito

Tamponlardan herhangi biri 0 boyutundaysa (0 boyutunda diziler mevcut değildir, ancak bu mümkündür ve ayrıca fonksiyonun kullanıcısı açısından char a[4] = "asd"; char b[3]= "as"; is_substr(a+4, b);
yasaldır

Ve işte sebebi strnstr()(en azından libbsd'de)
Cacahuete Frito

1

C Kullanma - Yerleşik işlev yok

string_contains () tüm ağır kaldırma işlemlerini yapar ve 1 tabanlı dizin döndürür. Geri kalanı sürücü ve yardımcı kodlardır.

Ana dizeye ve alt dizeye bir işaretçi atayın, eşleştirirken alt dize işaretçisini artırın, alt dize işaretçisi alt dize uzunluğuna eşit olduğunda döngüyü durdurun.

read_line () - Kullanıcının girmesi gereken giriş boyutunu belirlemeden kullanıcı girişini okumak için küçük bir bonus kodu.

#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++;
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.