Cómo comparar dos cadenas C para igualdad, usando una matriz de caracteres

Supongo que debe no usar strcmp () o una de sus alternativas mejores (más seguras). Si tiene permitido usarlos, entonces úselos. No intentes reinventar la rueda si puedes evitarla, porque generalmente lo harás mal.

De hecho, strcmp () en sí es posiblemente “incorrecto”, por lo tanto strcmp_s (), strncmp (), etc., intenta solucionar los problemas en el original. Si los creadores de C no pudieron hacer una función que funcione de manera segura en todos los casos, sus probabilidades de hacerlo bien son escasas o nulas.

Entonces, hay algunos problemas aquí.

0) El problema sobre el que preguntó y que Fatih Karaoğlanoğlu ya respondió correctamente: está colocando el ‘?’ operador ternario incorrectamente y necesita moverlo hacia la derecha, fuera del corsé.

1) s1 y s2 son punteros. A menos que haya pasado dos punteros a la misma matriz, s1 y s2 siempre serán diferentes, incluso si las cadenas dentro de esas matrices son idénticas.

Por lo tanto, su función siempre devolverá falso a menos que pase la misma matriz dos veces. Sospecho que esto debería ser if (*s1 != *s2) . O mejor, usaría esa variable i no utilizada, y haría if (s1[i] != s2[i]).

Su función devolverá correctamente false si se pasan dos cadenas terminadas en nulo diferentes.

2) Sin embargo, su función todavía nunca presionará done==true , por lo que nunca regresará correctamente true, ya que la otra prueba también usa el puntero directamente.

Si cambia la prueba a if (*s1 == 0) o if (s1[0] == '\0') , entonces devolverá correctamente verdadero si se pasan dos cadenas idénticas terminadas en nulo.

3) Pero incluso entonces, su función seguirá leyendo en la memoria arbitraria si se pasan dos matrices idénticas sin terminación nula, se pasan dos punteros nulos, se pasan dos matrices vacías …

Esta es la falla que se encuentra en el corazón de strcmp (), que los métodos más modernos intentan “arreglar” al pasar el tamaño de las matrices, etc. El problema es que C no tiene forma de identificar cuánto tiempo array no es una cadena a menos que esté correctamente terminada en nulo.

Otros puntos de estilo (no errores, solo comentarios sobre el estilo):

4) ¿Por qué hacer un bucle? ¿Por qué no hacer un bucle para siempre y simplemente devolver verdadero, en lugar de establecer hecho verdadero? Lo haces devolviendo falso, después de todo.

5) ¿Por qué pasar en matrices, luego usar aritmética de puntero? ¿Qué tiene de malo un bucle for () y la indexación de matrices? (El siguiente código todavía tiene el mismo error que strcmp):

para (i = 0; s1 [i] == s2 [i]; i ++) {
if (s1 [i] == 0) {
volver verdadero;
}
}
falso retorno;

6) Aunque la pregunta se refiere a “cadenas C”, parece que no está usando C aquí, está usando C ++, aunque está usando que proporciona métodos para cadenas de estilo C terminadas en nulo.

Como está usando C ++, podría usar std :: string de . Eso significa que puede usar la propiedad de longitud para evitar el problema strcmp (), algo como:

para (i = 0; (i <s1.length) && (i <s2.length) && (s1 [i] == s2 [i]); i ++) {
if (s1 [i] == 0) {
volver verdadero;
}
}
falso retorno;

Pero en ese caso, es probable que solo estés usando == para la comparación de cadenas:

devuelve s1 == s2;

… lo que haría que toda la función sea redundante.

7) ¿Por qué #incluye y ?

8) Para especificar el carácter nulo al final de una cadena, se considera mejor estilo decir '\0' lugar de 0 , ya que es más explícito sobre lo que quiere decir, a pesar de que los dos son iguales.

9) Llama a is_equal(x, y) una vez, coloca el resultado en una variable test_result y luego vuelve a llamarlo para el ternario. También puede usar el valor en su variable en el ternario:

((test_result == esperado)? “pasar”: “fallar”)

10) Si pensabas que los otros eran tontos, esto podría ser lo peor: en general, realmente me gusta tu uso del espacio en blanco. Creo que la mayoría de los programadores no piensan lo suficiente sobre los espacios en blanco correctos.

Pero coloca espacios alrededor de la mayoría de los operadores, como ==,! =, -, <<, etc. Y en su llamada a testequal, y en su salida de la llamada test_equal, coloca un espacio después de cada coma en una llamada a método. Pero eres inconsistente: en tus otras llamadas a test_equal (x, y) no tienes un espacio después de la coma.

También preferiría ver un espacio antes de abrir llaves, pero es probable que muchas cosas sean solo una preferencia personal: eres consistente en no tenerlo allí, así que está bien 🙂

Si tiene un documento de “estilo de casa”, use el mismo espacio que dicta; de lo contrario, copia a tu maestro, porque eso te dará las mejores calificaciones 🙂

Oh, ¿cómo debería responder esto? ¿Estás preguntando si permites el uso de las funciones string.h? Si es así, suponiendo que tenga 2 cadenas definidas como:

char str1 [] = “Hola mundo”;
char str2 [] = “Hola mundo”;

Luego, para compararlos, por supuesto, debe incluir string.h y luego usar esta línea para compararlos:

unsigned uiCompareResult = strcmp (str1, str2);

Verá que las matrices de caracteres (char) son lo mismo que los punteros de caracteres constantes, que es lo que contiene las cadenas. strcmp se define para tomar 2 punteros de cadena constantes como argumentos y devuelve 0 para igual, -1 para cuando str1 es menor que str2 y (+) 1 para cuando str1 es mayor que str2. Devuelve un entero sin signo o size_t en otra forma de uso.

Si estaba preguntando cómo hacerlo sin la función strcmp, primero preguntaría por qué, porque hay tantas otras funciones para hacerlo, solo está recreando la rueda de una manera de hablar, pero si debe:

#ifndef STRING_H
strcmp sin signo (const char * str1, const char * str2);
strlen sin signo (const char *);

strcmp sin signo (const char * str1, const char * str2)
{
if (strlen (str1) == strlen (str2))
{
unsigned uiLength = strlen (str1), uiLoop = 0;

para (; uiLoop {
if (str1 [uiLoop1] == str2 [uiLoop2])
{
Hacer continuación;
}
si no (str1 [uiLoop]> str2 [uiLoop])
{
volver (1);
}
si no (str1 [uiLoop] {
retorno (-1);
}
}

retorno (0);
}
más si (strlen (str1)> strlen (str2))
{
unsigned uiLength = strlen (str2), uiLoop = 0;

para (; uiLoop {
if (str1 [uiLoop] {
retorno (-1);
}
}

volver (1);
}
si no (strlen (str1) {
unsigned uiLength = strleng (str1), uiLoop = 0;

para (; uiLoop {
if (str1 [uiLoop]> str2 [uiLoop])
{
volver (1);
}
}

retorno (-1);
}
}

strlen sin signo (const char * str)
{
unsigned uiLoop = 0;

for (; str [uiLoop]! = ‘\ 0’; uiLoop ++);

return (uiLoop);
}

#terminara si

int main (const char ** args)
{
char str1 [] = “Hola mundo”;
char str2 [] = “Hola mundo”;
unsigned uiCompareResult = strcmp (str1, str2);

printf (“str1 = \”% s \ “\ r \ n”, str1);
printf (“str2 = \”% s \ “\ r \ n”, str2);

if (uiCompareResult == 0)
{
printf (“Las dos cadenas son iguales. \ r \ n”);
}
más if (uiCompareResult> 0)
{
printf (“La primera cadena es mayor que la segunda. \ r \ n”);
}
si no (uiCompareResult <0)
{
printf (“La primera cadena es menor que la segunda. \ r \ n”);
}

retorno (0);
}

Eso definió 2 funciones: en primer lugar, usa directivas de preprocesador para determinar si se han incluido las funciones de cadena; de lo contrario, crea strlen (devuelve la longitud de la cadena pasada como argumento) y strcmp (compara dos cadenas). No estoy afirmando que el código sea eficiente, pero debería realizar las funciones indicadas. Luego, dentro de una función principal, llamo a la función strcmp pasando matrices de caracteres con la misma cadena: DEBERÍA devolver 0 e imprimir que son lo mismo en la pantalla.

El error más deslumbrante: no pruebe la igualdad en s1 y s2, NUNCA. Especialmente si son punteros. (Por cierto, esas matrices que tienes allí se descomponen en punteros)

¿Por qué? Sencillo. C (y, por extensión, C ++, y la sobrecarga del operador ‘==’ no le ahorrará IIRC) compara los punteros simplemente verificando su dirección. No es a lo que apuntan, sino cuál es la dirección de ellos. Entonces, cuando creas dos matrices de caracteres separadas, están en diferentes partes de tu memoria. (De hecho, para su caso, en la pila) De modo que su código, incluso si funcionara, siempre devolvería falso .

Para arreglar eso, simplemente cambia:

si (s1! = s2)

a

if (* s1! = * s2)

Recuerde, le importa lo que señalan, por lo que ese es su mayor error, aparte del error de sintaxis. (A lo que llegaré en un momento)

Sin embargo, antes de comenzar a verificar a qué apuntan s1 y s2, agregue algunas verificaciones nulas antes de ingresar, como:

if (s1 && s2) // ¡no estamos revisando contenido esta vez!

A continuación, ¿termina el ciclo simplemente probando s1 para cero? ¿Por qué? ¿Qué te hizo s2 para merecer esto? ¿Qué pasa si es la cadena más corta? ¿Y llegaste a su fin? ¡Felicidades, te has hecho realidad pero posiblemente no sean iguales! (Ej: hellothere vs hola)

Esa declaración para la variable ‘i’ no tiene sentido ya que no se usa en su función. Desaste de eso.

Ahora, en su error de sintaxis. El operador ternario debe estar a la derecha del soporte al lado. Eso es todo.

Hay una serie de errores de los cuales la marca amarilla es solo un error de sintaxis donde el signo de interrogación está en el lugar equivocado cuando Faith responde.

Además, si no necesita escribir su propia implementación, use la función strcmp como lo sugiere Martin. La función estándar generalmente se implementa mejor que cualquier cosa que se te ocurra.

Un error lógico está en la primera instrucción if en la que compara los punteros en lugar del contenido de las cadenas.

Personalmente tendría punteros como argumentos de la función. No importa en la práctica, pero los está utilizando como punteros para que el código sea más claro.

Si va a publicar el código fuente, publíquelo como código fuente, es decir, texto sin formato, y no como una imagen. De esta manera, el código fuente se puede copiar.

En cuanto a su pregunta real, se destacan dos cosas: (1) podría reemplazar la función is_equal por strcmp como se demuestra en la función strcmp (): compare dos cadenas. : Función de matriz de caracteres “Tipo de datos” C ++, y (2) es la línea int i = 0; en la función is_equal está destinado a hacer algo? No hay otras referencias en la función a la variable i .

I: Escriba un comentario sobre la función con una cadena de ejemplo de cómo
querer salir a mirar.
II: Divide tus funciones de cadena en trozos manejables.
III: crea una cadena para cada pieza de información calculada, luego concatena al final.
IV: escribir funciones de comillas y comillas para limpiar la confusión.

#define varname (nombre) #name // macro var_to_string

usando std :: string;
usando std :: cout;

/ * Agrega comillas a la representación de cadena
* de value.toString (). plantilla funciona
* para casi todos los tipos básicos.
* /
plantilla (nombre de tipo T)
cita de cadena (T y artículo)
{
cadena citada (artículo);
citado = “\” “+ citado +” \ “”;
retorno citado;
}

// salida de ejemplo: pass isequal (“A”, “B”) true

nulo testequal (bool esperado,
char x [], string & x_name,
char [] y, string & y_name)
{
bool test_result;
string passfail;
string s_is_equal;

test_result = is_equal (x, y);

passfail = (esperado == test_result)? “contraseña errónea”;

s_is_equal = “is_equal (”
<< citado (x_name) << ","
<< citado (y_name) << ") =";

cout << passfail << ""
<< s_es_equal << ""
<< test_result
<< endl;
}

Aunque la pregunta es cómo comparar cadenas, el problema real es que está recibiendo una advertencia y un error del compilador.

Para solucionarlo, cambie el código a esto:

std :: cout << (test_result == esperado? "(pasar)": "(falla)")
<< "is_equal (\" "<< x <<" \ ", \" "<< y <<" \ ") ="
<< std :: boolalpha << test_result << std :: endl;

Toma nota de las diferencias

Una palabra rápida sobre su método is_equal , simplemente lo cambiaré a:

return std :: string (s1) == std :: string (s2):

Prefiero permanecer en la función “is_equal”:

bool is_equal (char s1 [], char s2 []) {

mientras que (* s1) {

if (* s1! = * s2) // incluye el caso * s2 = 0
falso retorno;
más{
++ s1; ++ s2;
}
}

if (* s2 == 0) devuelve verdadero;
más
falso retorno;

}

Entero i no tiene referencia en ninguna parte de la función, así que simplemente bórrelo.

Ha especificado “usando el espacio de nombres std;” Entonces, ¿por qué usar std :: cout << ... etc.

Eliminar “std ::” de su función.

Debería arreglar la ubicación del operador ternario (?) Creo.

esperaba que
esperado)?