2010-04-16 5 views
6

En un libro que estoy leyendo no es un trozo de código:¿Cómo puede char * ser una condición en for loop?

string x; 
size_t h=0; 
for(const char* s=x.c_str();*s;++s) 
    h=(h*17)^*s; 

En cuanto a este código, tengo dos preguntas:

  1. cómo puede ser una condición *s? ¿Qué significa eso?

  2. ¿Qué significa "h=(h*17)^*s"?

¡Gracias por la ayuda!

+2

Parece un algoritmo hash. –

Respuesta

16
  1. cómo puede * s ser una condición? ¿Qué significa eso?

significa "mientras que el valor a la que apunta s no es cero." Las cadenas C tienen terminación nula, por lo que el último carácter en la cadena devuelto por c_str() será el carácter nulo (\0, representado por todos los bits cero).

  1. ¿qué significa "h = (h * 17)^* s" significa?

se multiplica por h17 continuación xor s con el valor apuntado por s.

+2

El código dado puede tener un error sutil. El carácter nulo es un carácter válido en std :: strings. La función dada no procesará completamente una cadena si esto es cierto para su entrada. – stonemetal

3
  • *s detecta el carácter de terminación de cadena '\ 0'
  • (h*17)^*s es lo que dice: h multiplicado por 17 y xor-ed con el contenido del carácter apuntado por s. Parece una función de hash simple.
+0

Es tanto C como C++ –

+0

¿desde cuándo tenemos 'cadena' en C? – IVlad

+0

@http: //stackoverflow.com/users/197788/ken-bloom Lo siento, he editado justo antes del comentario;) – baol

1
  1. *s es el carácter que s señala actualmente que, por lo que es un personaje. El bucle for continúa hasta que se convierte en \0, es decir, hasta que termina la cadena.
  2. h se le asigna el valor de h * 17xored con el carácter (valor ascii de) *s.

Here es un buen tutorial sobre punteros.

1

1) *s en la condición comprueba si *s!=NUL

2) h=(h*17)^*s implica multiplicar h por 17 y realizar exclusive-OR operación con el valor apuntado por s.

1

En C y C++, true y false son iguales a cero y cero.Por lo tanto, el código en if (1){ siempre se ejecutará, como lo hará el código en if (-1237830){, pero if (0){ siempre es false.

Del mismo modo, si el valor del puntero es alguna vez 0, la condición es la misma que false, es decir, saldrá del ciclo.

3

En C (o C++), cualquier valor puede usarse como un "booleano". Un valor numérico de 0 o un puntero NULL significa "falso". Cualquier otra cosa significa "verdadero".

Aquí, *s es "el valor del carácter señalado actualmente por s". El ciclo se detiene si ese carácter es un 0 (no el dígito "0", con codificación ASCII 48, pero el byte con codificación ASCII 0). Esto es convencionalmente el marcador "fin de cadena", por lo que el ciclo se detiene cuando llega al final de la cadena.

"^" es el operador XOR bit a bit. La izquierda "*" es una multiplicación simple, mientras que la otra "*" es el operador de desreferencia del puntero (es decir, la cosa que toma el puntero s y mira el valor al que apunta este puntero). "=" es asignación. En resumen, el valor de h se multiplica por 17, luego se XOR con el carácter apuntado por s, y el resultado se convierte en el nuevo valor de h.

3

Como otras respuestas han explicado, la respuesta básica es que cualquier expresión que se evalúe a 0 se interpreta como una condición 'falsa' en C o C++, y *s evaluará a 0 cuando el puntero s alcanza el carácter de terminación nula de la cadena ('\ 0').

Puede utilizar de forma equivalente la expresión *s != 0, y algunos desarrolladores pueden argumentar que esto es lo que se debe utilizar, dando la opinión de que la expresión 'más completa' es más clara. Esté o no de acuerdo con esa opinión, debe ser capaz de comprender el uso de la alternativa definitiva, ya que se usa con mucha frecuencia en el código C/C++. Te encontrarás con estas expresiones mucho, incluso si prefieres usar la comparación más explícita.

La explicación más rigurosa del estándar (por alguna razón me siento obligado a incluir esto en la discusión, aunque en realidad no cambia ni aclara nada. De hecho, probablemente confundirá las cosas innecesariamente para algunas personas - si no te importa entrar en este nivel de trivia, no te perderás absolutamente nada al hacer clic en el botón Atrás ahora mismo ...):

En C, la expresión *s está en lo que el estándar llama 'expresión' -2 'de la declaración for, y este ejemplo de instrucción particular for solo está aprovechando la definición del estándar de la declaración for. La declaración for se clasifica como una 'declaración de iteración', y entre la semántica de cualquier declaración iteración son (6.8.5/4 "declaraciones de iteración"):

Una declaración iteración hace que una declaración llama el cuerpo del ciclo de ser ejecutado repetidamente hasta que la expresión de control compara igual a 0.

Puesto que la 'expresión-2' parte de la declaración for es la expresión de control, esto significa que el bucle for ejecutará repetidamente hasta *s compara igual a 0.

El estándar C++ define las cosas un poco diferente (pero con el mismo resultado). En C++, la declaración for se define en términos de la declaración while, y la parte de condición de la declaración while controla el la iteración (6.5.1/1 "La declaración mientras que"):

hasta que el valor de la condición se convierte false

Anteriormente en el estándar de C++, lo siguiente describe cómo las expresiones se convierten en bool (4,12 "conversiones booleanos"):

Un valor de aritmética, enumeración, puntero o puntero al tipo de miembro se puede convertir a un valor r de tipo bool. Un valor cero, un valor de puntero nulo o un valor de puntero de miembro nulo se convierte en falso; cualquier otro valor se convierte en verdadero

Las palabras similares en el estándar (en ambos idiomas) se aplican a la expresión/condición de control de todas las declaraciones de selección o de iteración. Todo este lenguaje-lawyerese se reduce al hecho de que si una expresión evalúa a 0 es lo mismo que evaluar a falso (en el sentido inglés de la palabra, ya que C no tiene una palabra clave false incorporada).

Y esa es la larga y confusa explicación del concepto simple.