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"
.
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
.
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;
}
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";
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"
, "",""
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;
}
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;
}
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;
}
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" :)