Vérifier que la sous-chaîne existe dans une chaîne en C

170

J'essaie de vérifier si une chaîne contient une sous-chaîne en C comme:

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

Quel est quelque chose à utiliser à la place de string::findC ++?

aucun
la source
7
Vous voulez: char * strstr (const char * s1, const char * s2) - localise la première occurrence de la chaîne s2 dans la chaîne s1.
JonH
@JonH Je pensais que cela ne fonctionne que pour les caractères. J'accepterai l'une des réponses ci-dessous, merci ..
aucune
vous mélangez cela avec strchr.
JonH
@JonH ahh c'est vrai, ça a du sens maintenant. vous êtes super, merci encore ..
aucun

Réponses:

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

Notez que strstrrenvoie un pointeur vers le début du mot dans sentsi le mot wordest trouvé.

nneonneo
la source
1
Vous pouvez également supprimer le "! = NULL", je pense que strstr renvoie 0 ou 1
Simon MILHAU
44
strstrrenvoie un pointeur; J'aime être explicite lorsque je teste des pointeurs.
nneonneo
3
... et falseest0
Jack
8
Commentaire pour ma future référence; strcasestrfait la même chose mais ignore la casse.
amonett
2
@NgoThanhNhan Vous pouvez voir l'implémentation de strstrdans la glibc ici: github.com/lattera/glibc/blob/master/string/strstr.c . Elle est beaucoup plus optimisée qu'une implémentation naïve - et probablement plus rapide qu'une simple fonction auto-définie. Néanmoins, en cas de doute, référence.
nneonneo
12

Essayez d'utiliser des pointeurs ...

#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);
}
JusteVirtuellement
la source
8

Vous pouvez essayer celui-ci à la fois pour rechercher la présence de la sous-chaîne et pour l'extraire et l'imprimer:

#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;
}
jeevan
la source
Le test if(strcmp((ret=strstr(mainstring,substring)),substring))est incorrect: il ne correspond que substrings'il s'agit d'un suffixe de mainstring. Le reste de la fonction est une manière alambiquée d'écrire printf("and the sub string is:::%s\n", substring);.
chqrlie
5

Ce code implémente la logique du fonctionnement de la recherche (l'une des méthodes) sans utiliser de fonction prête à l'emploi:

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;
}
Ashok Mazumder
la source
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la raison et / ou la manière dont ce code répond à la question améliore sa valeur à long terme.
JAL
3

Et voici comment signaler la position du premier caractère de la sous-chaîne trouvée:

Remplacez cette ligne dans le code ci-dessus:

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

avec:

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

Ma propre solution humble (sensible à la casse):

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

Résultats

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

Testé sur ATmega328P (avr8-gnu-toolchain-3.5.4.1709);)

Damian K.
la source
1

La même chose sera obtenue avec ce code plus simple: Pourquoi les utiliser:

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

Mais la partie délicate serait de signaler à quelle position dans la chaîne d'origine la sous-chaîne commence ...

Derlo
la source
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");

    }
}
Neetesh Singh
la source
1

Je crois avoir la réponse la plus simple. Vous n'avez pas besoin de la bibliothèque string.h dans ce programme, ni de la bibliothèque stdbool.h. L'utilisation simple de pointeurs et d'arithmétique de pointeurs vous aidera à devenir un meilleur programmeur C.

Renvoyez simplement 0 pour False (aucune sous-chaîne trouvée), ou 1 pour True (oui, une sous-chaîne "sub" se trouve dans la chaîne globale "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;
}
user9679882
la source
1
Qu'en est-il du dépassement de tampon?
Cacahuete Frito
Comment se produirait un débordement de tampon ici?
user9679882
Pour commencer, vous ne connaissez pas la taille du tampon. Imaginez ce code «simple»: les char a[3] = "asd"; char b[2] = "as"; is_substr(a, b);chaînes d'entrée ne sont pas terminées par NUL, vous surchargez donc le tableau.
Cacahuete Frito
Si l'un des tampons est de taille 0 (les tableaux de taille 0 n'existent pas, mais c'est possible, et aussi légal du point de vue de l'utilisateur de la fonction):char a[4] = "asd"; char b[3]= "as"; is_substr(a+4, b);
Cacahuete Frito
Et c'est la raison qui strnstr()existe (au moins sur libbsd)
Cacahuete Frito
1

Utilisation de C - Pas de fonctions intégrées

string_contains () fait tout le gros du travail et retourne 1 index basé. Le repos sont des codes de conducteur et d'assistance.

Attribuez un pointeur à la chaîne principale et à la sous-chaîne, incrémentez le pointeur de sous-chaîne lors de la mise en correspondance, arrêtez la boucle lorsque le pointeur de sous-chaîne est égal à la longueur de la sous-chaîne.

read_line () - Un petit code bonus pour lire l'entrée de l'utilisateur sans prédéfinir la taille de l'entrée que l'utilisateur doit fournir.

#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;
}
Rakshith Murukannappa
la source
-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++;
    }
}
Srijit Nair
la source