2010-10-11 17 views
6

Bien, estoy tratando de hacer una pequeña clase rápida para trabajar como una especie de tabla hash. Si puedo conseguir que funcione entonces yo debería ser capaz de hacer esto:operador [] = ¿sobrecarga?

StringHash* hash = new StringHash; 
    hash["test"] = "This is a test"; 
    printf(hash["test"]); 

y debe imprimir "Esto es una prueba".

Parece que tengo 2 problemas en este momento. En primer lugar lo hice:

const char* operator[](const char* key) { 
    for(int i = 0; i < hashSize; ++i) { 
    if(strcmp(hkeys[i], key) == 0) {return values[i];} 
    } 
    return NULL; 
} 

Pero cuando trato de buscar un valor que el compilador se queja de que

de error: inválido tipos `StringHash * [const char [5]]' para subíndice

Segundo operador [] = no parece ser la sintaxis correcta aquí. La única otra cosa que pude encontrar fue & operador [], pero no creo que funcione, ya que tengo que codificar el procedimiento de búsqueda ??? (¿No es esa sintaxis la que se usa para devolver una referencia de elemento de matriz?)

¿Es posible que lo que intento hacer aquí sea posible? Cualquier consejo apreciado. :)


Parece haber cierta confusión sobre lo que estoy tratando de hacer. Voy a publicar mi código:

http://pastebin.com/5Na1Xvaz


producto terminado después de toda la ayuda:

http://pastebin.com/gx4gnYy8

Respuesta

2

En primer lugar, me pregunto por qué está escribiendo su propio HashMap cuando hay algunas versiones disponibles, aunque no una estándar.

¿Su tienda hash es const char * punteros o std :: cadenas? (Puede almacenar punteros const char * si es simplemente una tabla de búsqueda de datos almacenados en otro lugar que no va a cambiar su duración).

¿Qué se supone que debe hacer el operador cuando no se encuentra el elemento?

Ahora voy a suponer que las respuestas son: - Sí estamos almacenando const char * punteros, y almacenamos un NULL en una celda vacía - Cuando llevamos a cabo de hash [clave] = Valor queremos asociar llave con valor - Si solo hacemos hash [clave] pero no escribimos, no inserta

Esto se puede hacer con un objeto mágico: cuando asigna un const char * a este objeto, lo inserta o sobrescribe al picadillo. También puede tener una conversión implícita del objeto a const char * para leer.

Esto es bastante complejo y es preferible que se adhiera a la interfaz normal del mapa: el operador [] siempre inserta y utiliza un método diferente solo para buscar.

+0

Hmm ... Creo que entiendo lo que dices. ¿Quieres que escriba una clase con un operador =() y luego tener ese control agregar la entrada a la tabla, sí? Puedo ver que funciona. Sin embargo, lo que me preocupa es que no tenga que almacenar internamente otra matriz que contenga una instancia de esa clase para cada ... Ah, no, espera. Podría simplemente usar esos objetos como valores internos en lugar de const char * y luego hacer que devuelvan la cadena en la búsqueda. Lo tengo. :) – Khat

+0

Dispara. No me dejará hacerlo de esta manera. Sigue tratando de devolver el objeto mágico en lugar de la cadena de caracteres. – Khat

+1

Puede definir una conversión implícita entre el tipo "mágico" y 'const char *'. Sin embargo, usar 'std :: strings' es una solución más robusta. –

6

El error se debe a que hash es un puntero. Cambiar a:

StringHash hash; 
+0

Buena captura. Gracias. No está dando un error de compilación allí ahora. La prueba inicial funciona, así que ahora puedo buscar valores en el hash por sus claves. – Khat

3

hash no es un objeto StringHash. Es un puntero a uno.

Usted puede hacer esto:

(*hash)["test"] = "This is a test";

O puede preguntarse por qué necesita un puntero a ella, en primer lugar,

StringHash hash; 
hash["test" = "This is a test"; 

... o incluso si lo hace , por qué no usaría un puntero inteligente como auto_ptr.

#include <memory> 
std::auto_ptr<StringHash> hash(new StringHash); 
(*hash)["test"] = "This is a test"; 
2

Escribir StringHash hash; en lugar de la cosa new. C++ no es Java. :-)

3

Las otras respuestas se refieren a su primera pregunta. En cuanto a su segundo ...

Si devuelve una referencia, está devolviendo un valor l. Siempre puede asignar a un lvalue.

Sí, es realmente así de simple. Sin embargo, recomiendo leer detenidamente si necesita o no const en varios lugares.

Lo que recuerdo haber leído es que usted debe proporcionar una constconst y una sobrecarga no para operator[], algo así:

MyType const &operator[](int index) const; // This is the array access version (no assignment allowed), which should work on const objects 
MyType &operator[](int index);  // This is the array access or assignment version, which is necessarily non-const. 

Ver this link para más información.

2

El primer error es que has declarado que el hash es un puntero. Los tipos de puntero ya se pueden usar con el operador de índice. Por ejemplo, el puntero [3] es equivalente a * (puntero + 3). No puedes cambiar ese comportamiento. Hacer hash el objeto en sí:

StringHash sh; 

En cuanto al operador [] =, no existe tal cosa. Su operador de índice solo debe devolver una referencia para que la asignación funcione. Aquí está un ejemplo sencillo de cómo esto se vería así:

class Indexable 
{ 
    std::string arr[3]; 
public: 
    std::string & operator[](int index) { 
     return arr[index]; 
    } 
    std::string const& operator[](int index) const { 
     return arr[index]; 
    } 
}; 
2

cinco problemas:

  1. hash es un puntero a una StringHash, hay que eliminar la referencia al uso de los operadores: (*hash)["test"]
  2. Si que desea asignar al elemento, tiene que devolver una referencia al tipo de elemento

    const char *& operator[] (const char* key);

    // ...

    (*hash)["test"] = "This is a test"; // will compile now

  3. null no es una palabra clave en C++. Use 0 o NULL.

  4. operator [] tiene que asignar espacio para un elemento si no se encuentra. Devolver NULL no es una opción. De lo contrario, intentar asignar el resultado de (*hash)["test"] bloqueará su programa.
  5. Utilice std :: map o std :: tr1 :: unordered_map en lugar de escribir su propia clase "rápida".

Y solo para ser un imbécil: ¿Sabes que no es una tabla hash, verdad?

+0

1. Solucionado. ty 2. Estoy tratando de sobrecargar la asignación de elemento porque quiero aplicar strcpy el rval. 3. Noté eso justo después de publicar. Fijo. ty 4. Ver 2. 5. No quiero. :) ¿Por qué no es una tabla hash? – Khat

+0

@ddd: No es una tabla hash porque no calcula los valores hash de las claves para indexar en la matriz. Ver http://en.wikipedia.org/wiki/Hash_table –

+0

Ah. Veo a que te refieres. Una mesa normal, entonces supongo. – Khat

1

¿Puede utilizar boost::unordered_map<std::string, std::string? Entonces no tiene que preocuparse por implementar esto por su cuenta. Puede Usted provenir de diferentes orígenes, pero en C++ de la forma habitual para declarar su picadillo sería::

asumiendo que es un ejercicio de algún tipo por sí mismo

StringHash hash; 

Además de su operator[] podría funcionar para la impresión pero no funcionará para la tarea. Normalmente, los métodos operator[] funcionan devolviendo una referencia no constante o un objeto proxy a los que se pueden asignar los nuevos valores, y el tuyo no. Si pudiera usar std :: string, podría reescribir su método para devolver una referencia no constante a la posición dentro del hash que debe leerse o asignarse.