c++ stl map iterator

Cómo iterar sobre un mapa STL lleno de cadenas en C++



string find c++ (8)

  1. No escriba un método toString() . Esto no es Java. Implementa el operador de flujo para tu clase.

  2. Prefiere usar los algoritmos estándar antes que escribir tu propio bucle. En esta situación, std::for_each() proporciona una interfaz agradable para lo que desea hacer.

  3. Si debe usar un bucle, pero no tiene la intención de cambiar los datos, prefiera const_iterator sobre el iterator . De esta forma, si accidentalmente intentas cambiar los valores, el compilador te advertirá.

Entonces:

std::ostream& operator<<(std::ostream& str,something const& data) { data.print(str) return str; } void something::print(std::ostream& str) const { std::for_each(table.begin(),table.end(),PrintData(str)); }

Luego, cuando desee imprimirlo, simplemente transmita el objeto:

int main() { something bob; std::cout << bob; }

Si realmente necesita una representación de cadena del objeto, puede usar lexical_cast .

int main() { something bob; std::string rope = boost::lexical_cast<std::string>(bob); }

Los detalles que necesitan ser completados

class somthing { typedef std::map<std::string,std::string> DataMap; struct PrintData { PrintData(std::ostream& str): m_str(str) {} void operator()(DataMap::value_type const& data) const { m_str << value.first << "=" << value.second << "/n"; } private: std::ostream& m_str; }; DataMap table; public: void something::print(std::ostream& str); };

Tengo el siguiente problema relacionado con iterar sobre una matriz asociativa de cadenas definidas usando std :: map.

-- snip -- class something { //... private: std::map<std::string, std::string> table; //... }

En el constructor comparto la tabla con pares de claves de cadena asociadas a datos de cadena. En otro lugar tengo un método toString que devuelve un objeto de cadena que contiene todas las claves y datos asociados contenidos en el objeto de tabla (como clave = formato de datos).

std::string something::toString() { std::map<std::string, std::string>::iterator iter; std::string* strToReturn = new std::string(""); for (iter = table.begin(); iter != table.end(); iter++) { strToReturn->append(iter->first()); strToReturn->append(''=''); strToRetunr->append(iter->second()); //.... } //... }

Cuando intento compilar, obtengo lo siguiente

error: "error: no hay coincidencia para la llamada a ''(std :: basic_string, std :: allocator>) ()''".

¿Alguien podría explicarme qué falta, qué estoy haciendo mal? Solo encontré algo de discusión sobre un problema similar en el caso de hash_map donde el usuario tiene que definir una función hash para poder usar hash_map con los objetos std :: string. ¿Podría ser algo similar también en mi caso?

¡Gracias!


Cambia tus llamadas de adición para decir

...append(iter->first)

y

... append(iter->second)

Además, la línea

std::string* strToReturn = new std::string("");

asigna una cadena en el montón. Si tiene la intención de devolver un puntero a esta cadena asignada dinámicamente, la devolución debe cambiarse a std :: string *.

Alternativamente, si no desea preocuparse por administrar ese objeto en el montón, cambie la declaración local a

std::string strToReturn("");

y cambie las llamadas ''agregar'' para usar la sintaxis de referencia ...

strToReturn.append(...)

en lugar de

strToReturn->append(...)

Tenga en cuenta que esto construirá la cadena en la pila y luego la copiará en la variable de retorno. Esto tiene implicaciones de rendimiento.


Otra optimización valiosa es el miembro c_str () de las clases de cadena STL, que devuelve una cadena terminada nula e inmutable que se puede pasar como un LPCTSTR , por ejemplo, a una función personalizada que espera un LPCTSTR. Aunque no he rastreado el destructor para confirmarlo, sospecho que la clase de cadena se ocupa de la memoria en la que crea la copia.


Su problema principal es que está llamando a un método llamado first() en el iterador. Lo que se supone que debes hacer es usar la propiedad llamada first :

...append(iter->first) rather than ...append(iter->first())

Como una cuestión de estilo, no deberías estar usando new para crear esa cadena.

std::string something::toString() { std::map<std::string, std::string>::iterator iter; std::string strToReturn; //This is no longer on the heap for (iter = table.begin(); iter != table.end(); ++iter) { strToReturn.append(iter->first); //Not a method call strToReturn.append("="); strToReturn.append(iter->second); //.... // Make sure you don''t modify table here or the iterators will not work as you expect } //... return strToReturn; }

editar: facildelembrar señaló (en los comentarios) que en C ++ moderno ahora puede reescribir el ciclo

for (auto& item: table) { ... }


Tenga en cuenta que el resultado de desreferenciar un std :: map :: iterator es un std::pair . Los valores de first y second no son funciones, son variables.

Cambio:

iter->first()

a

iter->first

iter->second con iter->second .


Utilizar:

std::map<std::string, std::string>::const_iterator

en lugar:

std::map<std::string, std::string>::iterator


en c ++ 11 puedes usar

for ( auto iter : table ) { key=iter->first(); value=iter->second(); }


iter->first y iter->second son variables, está intentando llamarlas como métodos.