enum als string ausgeben?


  • Administrator

    Konrad Rudolph schrieb:

    Think encapsulation. Mit einem std::tr1::array<char, 3> sollte es doch wunderbar gehen, oder übersehe ich da etwas?

    Ist das std::tr1::array gleich dem boost::array ?
    Dann gibt es nämlich Probleme, allerdings mehr in der Bequemlichkeit.
    boost::array hat keine Konstruktoren, wodurch jegliche implizite Umwandlung unmöglich ist. Desweiteren haben mir noch keine rohen Strings, sondern alle sind noch mit einem '\0' abgeschlossen. Bsp:

    #include <boost/array.hpp>
    
    #include <map>
    #include <string>
    
    int main()
    {
      typedef boost::array<char, 3> Array_t;
      typedef std::map<Array_t, int> FirstMap_t;
      typedef std::map<std::string, int> SecondMap_t;
    
      Array_t tempArray;
      FirstMap_t firstMap;
      SecondMap_t secondMap;
    
      // Zuerst mit dem Array:
      char const* p = "abc";
      tempArray.assign(p, p + 3); // Unter VS noch warnings ...
      firstMap[tempArray] = 0; // zusätzliche Kopie!
    
      // usw.
    
      // Dann mit dem std::string:
      secondMap["abc"] = 0; // irgendwie angenehmer, nicht?
    
      return 0;
    }
    

    Zudem wenn man noch bedenkt, was für Optimierungen der Compiler machen kann, dann würde ich persönlich bei einer std::map eher den std::string nehmen. Alles andere ist Mikrooptimierung, welche allenfalls später durchgeführt werden kann. Kann mir aber schlecht vorstellen, dass es dadurch einen Geschwindigkeitsverlust geben wird.

    Grüssli



  • Dravere schrieb:

    Konrad Rudolph schrieb:

    Think encapsulation. Mit einem std::tr1::array<char, 3> sollte es doch wunderbar gehen, oder übersehe ich da etwas?

    Ist das std::tr1::array gleich dem boost::array ?
    Dann gibt es nämlich Probleme, allerdings mehr in der Bequemlichkeit.
    boost::array hat keine Konstruktoren

    Dafür aber Array-Initializer, die hier evtl. sowieso besser geeignet sind.

    typedef array<char, 3> tlc_t;
    typedef map<tlc_t, char, tlc_comp> tlc_to_aa_t;
    
    tlc_t a = {{ 'a', 'l', 'a' }};
    tlc_t g = {{ 'g', 'l', 'y' }};
    // … etc.
    
    tlc_to_aa_t tr;
    tr[a] = 'a';
    tr[g] = 'g';
    // … etc.
    

    Zudem wenn man noch bedenkt, was für Optimierungen der Compiler machen kann, dann würde ich persönlich bei einer std::map eher den std::string nehmen. Alles andere ist Mikrooptimierung, welche allenfalls später durchgeführt werden kann. Kann mir aber schlecht vorstellen, dass es dadurch einen Geschwindigkeitsverlust geben wird.

    Ha. Na ja. In unserem Bioinformatik-Software-Framework haben wir für alle möglichen Konvertierungen hartcodierte Übersetzungstabellen und die bringen definitiv einen Geschwindigkeitsvorteil. Aber zugegeben, hier sind solche Dinge auch wirklich wichtig.



  • Der Beitrag ist nicht ganz frisch, trotzdem wollte ich meinen Vorschlag auch posten. Ich habe für enum-string Konvertierung ein Perl-Skript geschrieben, das eine Klasse mit vielen überladenen toString-Methoden erzeugt.
    Die C++ Dateien werden nicht mit Perl geparst sondern es wird zuvor die tags-Datei mit dem Tool ctags erzeugt.
    Hier ist das Skript:

    #!/bin/perl
    # Valentin Heinitz, 2010-03-20
    # Script for making C++ class which converts enum to string.
    # Version: 0.01
    # This script is Public Domain. Copy, modify and redistribute it as you want.
    # The software is provided "as is", without warranty of any kind.
    #
    # Call it from Source-code root-directory with command-line:
    # perl enum2string.pl > <ToStringClassFileName.h>
    use strict;
    use warnings;
    #Found enum types will be added to this list
    my @etypes=();
    #Found includes will be added to this list
    my @includes=();
    
    # Pattern for searching enum types and corresponding include-file.
    my $pat="^[^\t]+\t([^\t]+)\t.*enum:([a-zA-Z_][a-zA-Z0-9_]*)";
    my $file = "tags";
    
    system "ctags -R *";
    
    open T, ">tmp" or die "couldn't open tmp\n";
    open F, $file or die "couldn't open $file\n";
    
    #Replacing MS-Windows paths by UNIX paths (for includes)
    while (<F>) {
     $_ =~ s/\\/\//;
     print T "$_";
    }
    close F;
    close T;
    
    $file="tmp";
    
    open F, $file or die "couldn't open $file\n";
    while (<F>) {
      if (my ($m) = m/$pat/){
        $etypes[++$#etypes] = $2;
        $includes[++$#includes] = $1;
        #print "$_\n";
      }
    }
    close F;
    
    #Class name to be generated. Change as you like, or set from argument
    my $clName = 'EnumToString';
    
    #Remove duplicates from enum type list
    my %hlp1 = ();
    my @uniqenums = grep { ! $hlp1{$_} ++ } @etypes;
    
    #Remove duplicates from include list
    my %hlp2 = ();
    my @uniqinc = grep { ! $hlp2{$_} ++ } @includes;
    
    print "#ifndef _H_G__$clName\n";
    print "#define _H_G__$clName\n\n";
    print "#include <iostream>\nusing std::cout;\n";
    
    foreach my $inc (@uniqinc)
    {
      print "#include \"$inc\"\n";
    }
    
    print "\n\n";
    
    print "class $clName {\n";
    print "  EnumToString(); // utility class, no instances\n\n";
    print "public:\n";
    
    foreach my $k (@uniqenums)
    {
      $pat = "^([a-zA-Z0-9_]*)\t.*e\tenum:$k";
      print "  static const char * toString( $k en ) {\n";
      print "    switch( en ) {\n";
      open F, $file or die "couldn't open $file\n";
      while (<F>) {
        if (my ($m) = m/$pat/){
          print "      case $1: return \"$1\";\n";
        }
      }
      close F;
      print "    }\n";
      print "  }\n\n";
    
    }
    
    #Test
    print "static void testEnum2String() {\n";
    foreach my $k (@uniqenums)
    {
      $pat = "^([a-zA-Z0-9_]*)\t.*e\tenum:$k";
      print "  std::cout << \"Enums of $k:\\n\";\n";
      open F, $file or die "couldn't open $file\n";
      while (<F>) {
        if (my ($m) = m/$pat/){
          print "  std::cout <<\"   \"<<  toString( $1 ) <<\" -> \" << $1 <<\"\\n\";\n";
        }
      }
      close F;
    }
    print "  }\n\n";
    
    print "};\n\n";
    print "#endif\n";
    

    Die komplete Beschreibung mit dem Beispielprojekt ist auf meiner Webseite zu finden:
    http://heinitz-it.de/archives/date/2010/03

    Gruß,
    Valentin Heinitz


Anmelden zum Antworten