Compresión de Cadena Insensible en C

Tengo dos códigos postales char* que quiero comparar, ignorando el caso. ¿Hay una función para hacer esto?

¿O debo pasar por cada uso de la función tolower y luego hacer la comparación?

Alguna idea de cómo reactjsrá esta función con los números en la cadena

Gracias

No hay ninguna función que haga esto en el estándar C. Los sistemas Unix que cumplen con POSIX deben tener strcasecmp en el encabezado strings.h ; Los sistemas de Microsoft tienen stricmp . Para estar en el lado portátil, escriba el suyo:

 int strcicmp(char const *a, char const *b) { for (;; a++, b++) { int d = tolower((unsigned char)*a) - tolower((unsigned char)*b); if (d != 0 || !*a) return d; } } 

Pero tenga en cuenta que ninguna de estas soluciones funcionará con cadenas UTF-8, solo ASCII.

Eche un vistazo a strcasecmp () en strings.h .

Yo usaría stricmp() . Compara dos cadenas sin importar el caso.

Tenga en cuenta que, en algunos casos, convertir la cadena a minúsculas puede ser más rápido.

He encontrado un método incorporado llamado desde el cual contiene funciones de cadena adicionales al encabezado estándar.

Aquí están las firmas relevantes:

 int strcasecmp(const char *, const char *); int strncasecmp(const char *, const char *, size_t); 

También encontré que es sinónimo en xnu kernel (osfmk / device / subrs.c) y está implementado en el siguiente código, por lo que no esperaría tener ningún cambio de comportamiento en número en comparación con la función strcmp original.

 tolower(unsigned char ch) { if (ch >= 'A' && ch <= 'Z') ch = 'a' + (ch - 'A'); return ch; } int strcasecmp(const char *s1, const char *s2) { const unsigned char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; while (tolower(*us1) == tolower(*us2++)) if (*us1++ == '\0') return (0); return (tolower(*us1) - tolower(*--us2)); } 
 static int ignoreCaseComp (const char *str1, const char *str2, int length) { int k; for (k = 0; k < length; k++) { if ((str1[k] | 32) != (str2[k] | 32)) break; } if (k != length) return 1; return 0; } 

Referencia

Puede hacerse una idea, cómo implementar uno eficiente, si no tiene ninguno en la biblioteca, desde aquí

Utiliza una tabla para todos los 256 caracteres.

  • en esa tabla para todos los caracteres, excepto letras, usó sus códigos ASCII.
  • para códigos de letras mayúsculas: los códigos de la lista de tablas de símbolos de mayúsculas y minúsculas.

entonces solo necesitamos atravesar una cadena y comparar nuestras celdas de tabla para un chars dado:

 const char *cm = charmap, *us1 = (const char *)s1, *us2 = (const char *)s2; while (cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return (0); return (cm[*us1] - cm[*--us2]); 

Otros peligros a tener en cuenta cuando se compara con las mayúsculas y minúsculas:


Comparando como menor o como mayúscula? (problema bastante común)

Ambos a continuación devolverán 0 con strcicmpL("A", "a") y strcicmpU("A", "a") .
Sin embargo, strcicmpL("A", "_") y strcicmpU("A", "_") pueden devolver diferentes resultados firmados ya que '_' encuentra a menudo entre las letras mayúsculas y minúsculas.

Esto afecta el orden de clasificación cuando se usa con qsort(..., ..., ..., strcicmp) . Las funciones no estándar de la biblioteca C, como las comúnmente disponibles stricmp() o strcasecmp() tienden a estar bien definidas y favorecen la comparación en minúsculas. Sin embargo, existen variaciones.

 int strcicmpL(char const *a, char const *b) { while (*a) { int d = tolower(*a) - tolower(*b); if (d) { return d; } a++; b++; } return 0; } int strcicmpU(char const *a, char const *b) { while (*a) { int d = toupper(*a) - toupper(*b); if (d) { return d; } a++; b++; } return 0; } 

char puede tener un valor negativo. (no raro)

touppper(int) y tolower(int) se especifican para los valores de unsigned char y el EOF negativo. Además, strcmp() devuelve los resultados como si cada char se convirtiera en unsigned char , independientemente de que char esté firmado o no .

 tolower(*a); // Potential UB tolower((unsigned char) *a); // Correct 

Locale (menos común)

Aunque los juegos de caracteres que usan el código ASCII (0-127) son omnipresentes, los códigos restantes tienden a tener problemas específicos de la configuración regional . Entonces, strcasecmp("\xE4", "a") puede devolver un 0 en un sistema y no cero en otro.


Unicode (el camino del futuro)

Si una solución necesita manejar más que ASCII considere un unicode_strcicmp() . Como C lib no proporciona esa función, se recomienda una función precodificada de alguna biblioteca alternativa. Escribir tu propio unicode_strcicmp() es una tarea desalentadora.


¿Todas las letras mapean una inferior a una superior? (pedante)

[AZ] mapea uno a uno con [az], sin embargo, varios locales asignan varios caracteres en minúscula a uno superior y viceversa. Además, algunos caracteres en mayúsculas pueden carecer de un minúscula equivalente y, nuevamente, viceversa.

Esto obliga al código a encubrir tanto a través de tolower() como tolower() .

 int d = tolower(toupper(*a)) - tolower(toupper(*b)); 

De nuevo, posibles resultados diferentes para clasificar si el código tolower(toupper(*a)) vs. toupper(tolower(*a)) .


Portabilidad

@SEGUNDO. Nadolson recomienda evitar rodar su propio strcicmp() y esto es razonable, excepto cuando el código necesita una funcionalidad portátil equivalente alta.

A continuación se muestra un enfoque que incluso se realizó más rápido que algunas funciones proporcionadas por el sistema. Hace una sola comparación por ciclo en lugar de dos utilizando 2 tablas diferentes que difieren con '\0' . Tus resultados pueden variar

 static unsigned char low1[UCHAR_MAX + 1] = { 0, 1, 2, 3, ... '@', 'a', 'b', 'c', ... 'z', `[`, ... // @ABC... Z[... '`', 'a', 'b', 'c', ... 'z', `{`, ... // `abc... z{... } static unsigned char low2[UCHAR_MAX + 1] = { // v--- Not zero, but A which matches none in `low1[]` 'A', 1, 2, 3, ... '@', 'a', 'b', 'c', ... 'z', `[`, ... '`', 'a', 'b', 'c', ... 'z', `{`, ... } int strcicmp_ch(char const *a, char const *b) { // compare using tables that differ slightly. while (low1[(unsigned char)*a] == low2[(unsigned char)*b]) { a++; b++; } // Either strings differ or null character detected. // Perform subtraction using same table. return (low1[(unsigned char)*a] - low1[(unsigned char)*b]); } 
 int strcmpInsensitive(char* a, char* b) { return strcmp(lowerCaseWord(a), lowerCaseWord(b)); } char* lowerCaseWord(char* a) { char *b=new char[strlen(a)]; for (int i = 0; i < strlen(a); i++) { b[i] = tolower(a[i]); } return b; } 

buena suerte

La función Edit-lowerCaseWord obtiene una variable char * con, y devuelve el valor minúsculo de este char *. Por ejemplo, "AbCdE" para el valor de char *, devolverá "abcde".

Básicamente lo que hace es tomar las dos variables char *, después de ser transferidas a minúsculas, y hacer uso de la función strcmp en ellas.

Por ejemplo, si llamamos a la función strcmpInsensitive para los valores de "AbCdE" y "ABCDE", primero devolverá ambos valores en minúsculas ("abcde") y luego ejecutará la función strcmp en ellos.