web-dev-qa-db-fra.com

fonction strstr () qui ignore les majuscules et les minuscules

J'ai deux cordes. Disons `

str1="One Two Three";

et 

str2="two";

J'aimerais savoir s'il existe une fonction qui vérifie la correspondance de la deuxième chaîne dans la première et me renvoie un pointeur sur la première occurrence, quelque chose comme strstr(), mais qui ne traite pas la même lettre, ni supérieure ni supérieure. en minuscule, sous forme de deux caractères différents. 

Pour mon exemple, la fonction devrait trouver une correspondance pour str2 dans la première chaîne, malgré la majuscule "T", de "Two".

8
eOf

De la page de manuel pour strstr:

STRSTR(3)           Linux Programmer's Manual           STRSTR(3)

NAME
       strstr, strcasestr - locate a substring

SYNOPSIS
       #include 

       char *strstr(const char *haystack, const char *needle);

       #define _GNU_SOURCE

       #include 

       char *strcasestr(const char *haystack, const char *needle);

DESCRIPTION
       The  strstr()  function  finds the first occurrence of the substring needle in
       the string haystack.  The terminating '\0' characters are not compared.

       The strcasestr() function is like strstr(3), but  ignores  the  case  of  both
       arguments.

RETURN VALUE
       These functions return a pointer to the beginning of the substring, or NULL if
       the substring is not found.


Donc, ce que vous recherchez, c'est strcasestr.

29
Nathan Fellman

Bien que les bibliothèques C de certains compilateurs incluent des extensions avec des versions des fonctions de chaîne standard ne tenant pas compte de la casse, telles que strcasestr() de GNU, la dénomination de telles fonctions n'est pas normalisée, même lorsqu'elle est incluse.

Une façon de surmonter le manque d'implémentation standard consiste bien entendu à implémenter la vôtre:

char* stristr( const char* str1, const char* str2 )
{
    const char* p1 = str1 ;
    const char* p2 = str2 ;
    const char* r = *p2 == 0 ? str1 : 0 ;

    while( *p1 != 0 && *p2 != 0 )
    {
        if( tolower( (unsigned char)*p1 ) == tolower( (unsigned char)*p2 ) )
        {
            if( r == 0 )
            {
                r = p1 ;
            }

            p2++ ;
        }
        else
        {
            p2 = str2 ;
            if( r != 0 )
            {
                p1 = r + 1 ;
            }

            if( tolower( (unsigned char)*p1 ) == tolower( (unsigned char)*p2 ) )
            {
                r = p1 ;
                p2++ ;
            }
            else
            {
                r = 0 ;
            }
        }

        p1++ ;
    }

    return *p2 == 0 ? (char*)r : 0 ;
}

Le code de test ci-dessous indique:

Two Three
Two Three
NULL
cdefg
CDEFG
CdEfG
NULL
zzzz
NULL

zzzzz
NULL

int main(void) 
{
    char* test = stristr( "One TTwo Three", "two" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "One Two Three", "two" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "One wot Three", "two" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "abcdefg", "cde" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "ABCDEFG", "cde" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "AbCdEfG", "cde" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "1234567", "cde" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "zzzz", "zz" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "zz", "zzzzz" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "", "" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "zzzzz", "" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr( "", "zzzz" ) ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    test = stristr("AAABCDX","AABC") ;
    printf( "%s\n", test == 0 ? "NULL" : test  ) ;

    return 0;
}
9
Clifford

Si vous êtes sur Windows, vous pouvez utiliser StrStrI . Cela fonctionne de la même manière que la GNU strcasestr ou l’autre code stristr implémenté manuellement dans les autres réponses ici.

Par exemple.:

const char needle[] = "and";
const char haystack[] = "me and you";

const char* pAnd = StrStrIA(haystack, needle); // explicitly call ascii version as windows defaults to wchar
printf("%s\n", pAnd); // Prints "and you";
8
Orion Edwards

Après accepter la réponse

Inspiré par @Clifford et @Weather Vane , je pensais essayer de mettre en place une solution utilisant uniquement les fonctions de bibliothèque standard.

char* stristr3(const char* haystack, const char* needle) {
  do {
    const char* h = haystack;
    const char* n = needle;
    while (tolower((unsigned char) *h) == tolower((unsigned char ) *n) && *n) {
      h++;
      n++;
    }
    if (*n == 0) {
      return (char *) haystack;
    }
  } while (*haystack++);
  return 0;
}

Un peu difficile de faire correspondre les cas de coin de strstr() avec des entrées comme "x","", "","x", "",""

4
chux

Voici une version légèrement plus efficace, qui n'appelle pas tolower() deux fois par caractère dans la chaîne haystack:

#include <ctype.h>

char *stristr4(const char *haystack, const char *needle) {
    int c = tolower((unsigned char)*needle);
    if (c == '\0')
        return (char *)haystack;
    for (; *haystack; haystack++) {
        if (tolower((unsigned char)*haystack) == c) {
            for (size_t i = 0;;) {
                if (needle[++i] == '\0')
                    return (char *)haystack;
                if (tolower((unsigned char)haystack[i]) != tolower((unsigned char)needle[i]))
                    break;
            }
        }
    }
    return NULL;
}
2
chqrlie

Mise en œuvre de stristr()

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

char *stristr (const char *str, const char *strSearch) {
    char *sors, *subs, *res = NULL;
    if ((sors = strdup (str)) != NULL) {
        if ((subs = strdup (strSearch)) != NULL) {
            res = strstr (strlwr (sors), strlwr (subs));
            if (res != NULL)
                res = str + (res - sors);
            free (subs);
        }
        free (sors);
    }
    return res;
}

int main()
{
    char *str1 = "One Two Three";
    char *str2 = "two";
    char *sptr = stristr(str1, str2);
    if (sptr)
        printf ("Substring is at index %d\n", sptr - str1);
    return 0;
}
1
Weather Vane

Essayez ceci function:

char* stristr(const char* String, const char* Pattern)
{
      char *pptr, *sptr, *start;

      for (start = (char *)String; *start; start++)
      {
            /* find start of pattern in string */
            for ( ; (*start && (toupper(*start) != toupper(*Pattern))); start++)
                  ;
            if (!*start)
                  return 0;

            pptr = (char*)Pattern;
            sptr = (char*)start;

            while (toupper(*sptr) == toupper(*pptr))
            {
                  sptr++;
                  pptr++;
                  /* if end of pattern then pattern was found */
                  if (!*pptr)
                        return (start);
            }
      }
      return 0;
}
0
Mohammadreza Panahi

Le meilleur moyen de résoudre ce problème sans écrire de fonction consiste à convertir d'abord la chaîne en minuscule/majuscule à l'aide de "tolower"/"toupper", puis à utiliser "strstr" :)

0
Abhinav Gupta