2012-01-10 7 views
1

Existe-t-il un moyen de créer un hachage de hachages en C++?Comment créer un hachage de hachages en C++?

Effectivement j'essaye de faire ce que tu peux faire en Perl mais seulement en C++. Voici un exemple de code Perl je voudrais voir se produire en C++

%hash = (
gameobject1 => { 
    position => { 
     x_loc => 43, 
     y_loc => 59, 
    } 
    rect_size => { 
     width => 5, 
     height => 3, 
    } 
    collidable => 1, 
    sounds => { 
     attack => "player_attack.ogg", 
     jump => "player_jump1.ogg", 
     jump_random => [qw/player_jump1.ogg player_jump2.ogg player_jump3.ogg/] 
    } 

}, 
gameobject2 => { 
    position => { 
     x_loc => 24, 
     y_loc => 72, 
    } 
    rect_size => { 
     width => 2, 
     height => 4, 
    } 
    sounds => { 
     attack => "goblin_attack.ogg", 
    } 
     items => [qw/sword helmet boots/] 
}, 
); 

La chose à noter est le hash avec en GameObjects peuvent exister ou non ... par exemple la position peut exister dans gameobject1 mais ne peut pas exister pour gameobject35.

Des idées?

+0

J'ai remplacé "c/C++" dans votre question par "C++", car C et C++ sont des langages différents. Veuillez me corriger si mon hypothèse était fausse et que vous êtes plutôt intéressé par une solution C. –

+0

J'étais un peu pour l'un ou pour l'autre qui a toujours eu du sens :) C++ fonctionne – vternal3

Répondre

4

Perl hash vous permettent d'utiliser quoi que ce soit pour les valeurs. C++ étant un langage typé statiquement, il ne vous laissera pas faire cela: vous devez spécifier exactement le type que vous voulez que les valeurs dans le hachage (en C++ jargon, la carte) aient.

est ici solution avec C++ 11 et coup de pouce, avec une forte frappe jeté :)

#include <map> 
#include <vector> 
#include <string> 
#include <boost/optional.hpp> 

// Coordinates are always like this, aren't they? 
struct coords { 
    int x_loc; 
    int y_loc; 
}; 

// Dimensions are always like this, aren't they? 
struct dims { 
    int width; 
    int height; 
}; 

// Sound maps: each string key maps to a vector of filenames 
typedef std::map<std::string, std::vector<std::string>> sound_map; 
// Item lists: looks like it's just a collection of strings 
typedef std::vector<std::string> item_list; 

// Fancy names to improve readability 
enum collidability : bool { 
    collidable = true, 
    not_collidable = false 
}; 

// A structure to describe a game object 
struct game_object { 
    // An optional position 
    boost::optional<coords> position; 
    // An optional rectangle size 
    boost::optional<dims> rect_size; 
    // Assuming "false" can mean the same as "no collidable key" 
    bool collidable; 
    // Assuming an "empty map" can mean the same as "no map" 
    sound_map sounds; 
    // Assuming an "empty vector" can mean the same as "no vector" 
    item_list items; 
    // If any of the above assumptions is wrong, 
    // sprinkle boost::optional liberally :) 
}; 

// Finally, values for our "hash" 
std::map<std::string, game_object> hash { 
    { "game_object1", 
     { 
     coords { 43, 59 }, 
     dims { 5, 3 }, 
     collidable, // remember those fancy names? 
     sound_map { 
      { "attack", { "player_attack.ogg" } }, 
      { "jump", { "player_attack.ogg" } }, 
      { "jump_random", { "player_jump1.ogg", "player_jump2.ogg", "player_jump3.ogg" } } 
     }, 
     item_list {} 
    } }, 
    { "game_object2", 
     { 
     coords { 24, 72 }, 
     dims { 2, 4 }, 
     not_collidable, 
     sound_map { 
      { "attack", { "goblin_attack.ogg" } } 
     }, 
     item_list { "sword", "helmet", "boots" } 
    } }, 
    { "game_object25", 
     { 
     boost::none, // no position 
     dims { 2, 4 }, 
     not_collidable, 
     sound_map { 
      { "attack", { "goblin_attack.ogg" } } 
     }, 
     item_list { "sword", "helmet", "boots" } 
    } } 
}; 

Si vous voulez vraiment quelque chose comme un hachage Perl de Perl HASHES, vous pouvez utiliser std::map<std::string, boost::any> pour obtenir le possibilité de stocker quoi que ce soit sur la carte. Cependant, cela vous oblige à tester les types de chaque valeur avant de l'obtenir de la carte. Si seulement un certain ensemble de types est possible, vous pouvez utiliser quelque chose de plus fortement typé que boost::any, comme boost::variant.

+0

Avez-vous essayé de compiler ceci? J'obtiens des erreurs à 'hash {': erreur C2470: 'hash': ressemble à une définition de fonction, mais il n'y a pas de liste de paramètres; sauter le corps apparent et également à 'dims {2, 4},' et 'sound_map { {" attaque ", {" player_attack.ogg "}},' – vternal3

+0

@ vternal3: oui, cela compile bien sur GCC 4.7 . Comme je l'ai mentionné dans la réponse, cela utilise des fonctionnalités C++ 11, donc vous avez besoin d'un compilateur assez récent pour cela. –

+0

Je tiens vraiment à vous remercier pour votre aide avec cela! Tu gères – vternal3

2

Utilisez std :: map?

Quelque chose comme:

#include <map> 
#include <string> 
class GameObject; 
typedef std::map<std::string, GameObject> object_map_t; 
typedef std::map<std::string, object_map_t> map_of_object_maps_t; 
+0

Ceci est une bonne traduction littérale, mais il pourrait avoir de très mauvaises performances. J'envisagerais une représentation si possible. –

+0

Sa question était de savoir comment créer un hachage de hachages. Mais je suis d'accord, utiliser des classes avec des propriétés serait un meilleur moyen. – Naddiseo

2

Cet exemple peut vous aider à comprendre la mise en œuvre:

#include <map> 
#include <string> 
#include <iostream> 
using namespace std; 

void main() { 

    map<string, map<string, int>> hash; 
    hash["A"]["A"] = 1; 
    hash["A"]["B"] = 2; 
    hash["B"]["A"] = 4; 
    hash["B"]["B"] = 8; 

    for(map<string, int>::iterator i = hash["B"].begin(); i != hash["B+"].end(); i++) { 
     cout << i->first << " - " << i->second << "\n"; 
    } 
} 

... :) Vive

Questions connexes