Dynamische Arrays erzeugen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Dynamische Arrays erzeugen

    Hallo,

    ich versuche gerade einen kleinen ConfigParser für mich zu schreiben.
    Das öffnen,lesen, etc ist auch kein Problem. Ich habe allerdings ein Problem mit der Übergabe der ausgelesenen Daten.

    Also die Config sieht so aus:

    [Part1]
    Button0 = tollesbild.jpg
    Button1 = nochwastolles.jpg

    [Part2]
    Button0 = ani.gif
    Button1 = ani1.gif
    Button2 = ani2.gif
    ...

    Ich habe also verschiedene Sektionen, die die gleichen Schlüsselwörter nutzen.
    Ich dachte mir das ich den Sektionenname auslese (hier also Part1, Part2) und daraus denn je Schlüsselwort ein Array bilde.
    Aussehen sollten denn die Arrays so:
    Part1Buttons = {"tollesbild.jpg","nochwastolles.jpg"};
    Part2Buttons = {"ani.gif","ani1.gif","ani2.gif"};

    Ich habe also das Problem das ich
    a) nicht weiß wie das Array am ende heisst (soll ja "dynamisch benannt" werden)
    b) weiß ich nicht wieviele Elemente pro Array reinkommen.
    c) wieviele Arrays es werden

    Auslesen tut das ganze eine Funktion.

    Gibt es eine Möglichkeit die Arrays dynamisch in der Funktion zu erzeugen, die denn auch noch bestehen bleiben (also sowas wie static), oder gibt es gar besser Lössungen? Hatte mal irgendwo was gelesen, das man sowas über Klassen machen kann.

    Danke:)

    Thomas
    Murphy war ein Optimist.
  • 2 deiner Probleme kannst du auf einmal erschlagen. Wenn du die Datei zweimal durchläufst und beim ersten mal zählst, weißt du beim zweiten mal was du brauchst. Dynamische Arraynamen sind eigentlich unüblich, ich weiß gar nicht ob das in C geht. Am besten machst du dir ein zweidimensionales Array, welches du dann auch in der Größe flexibel gestalten kannst.
    ~ mfg SeBa

    Ich beantworte keine PMs zu Computer-/Programmierproblemen. Bitte wendet euch an das entsprechende Forum.

    [Blockierte Grafik: http://i.creativecommons.org/l/by-sa/3.0/80x15.png]
  • Das mit dem 2 Durchlaufen ist ein guter Tipp. So mache ich das jetzt auch.
    Alle "Sectionnamen" werden jetzt in einen Vector gespeichert.
    Jetzt müsste ich "nur noch" irgendwie diese Sectionnamen in die Variablennamen einbinden können.

    Also quasi:

    Quellcode

    1. int main() {
    2. ...
    3. //Anzahl der Submenu auslesen und einsortieren
    4. vector <string> Skin_menu_table;
    5. Read_SkinConf(Skin_menu_table)
    6. for (int i=0;i<Skin_menu_table.size();i++) {
    7. // hier müsste jetzt sowas wie:
    8. // vector<string> Skin_menu_table[i]buttons;
    9. }
    10. }
    Alles anzeigen


    Ich möchte also aus dem erstem Vector und einem zusätzlichen Bezeichner einen neuen Bezeichner bilden (z.B vector<string> Part1Buttons - Part1 ist im Vector gespeichert (Skin_menu_table) und Buttons ist der zusätzliche Bezeichner)...Ich hoffe Ihr versteht was ich meine:)

    Thomas
    Murphy war ein Optimist.
  • Hi,
    womit du das hinbiegen könntest wäre

    Quellcode

    1. std::map<std::string,std::vector<std::string> >

    den key kannst du dir zusammenbasteln wenn du in deinem Configfile auf nen Part triffst.Dann liest du die Button Strings in nen methodenlokalen vector<string> ein und schiebst dann das pair in die map. :wink:
    Eventuell wäre es noch hilfreich die Parts Bezeichner noch seperat in nem vector zu speichern um später die keys reproduzieren zu können.

    Gruß void
    "Probleme kann man niemals mit derselben Denkweise lösen,
    durch die sie entstanden sind." (A. Einstein)
  • Hm, klingt soweit ganz interessant. Allerdings habe ich noch nie mit std::map gearbeitet. Könntest Du evtl. ein kurzes Codebeispiel bringen?

    Ich dachte es würde so funktionieren:

    Quellcode

    1. ...
    2. std::string test="Part1";
    3. std::map<std::string,std::vector<std::string> > tabelle,buttons;
    4. tabelle[test] = buttons.push_back("inhalt");
    5. ...


    Aber das war mir klar das dieses nicht geht (ging ja auch nicht), sieht irgendwie schon so falsch aus:)
    Es kommt denn leider ein "std_test.cpp:11: error: `push_back' undeclared (first use this function)"

    Thomas

    Edit:

    jetzt klappt, habe es jetzt so gelöst (ist meine kleine Testdatei):

    Quellcode

    1. #include <iostream>
    2. #include <map>
    3. #include <vector>
    4. using namespace std;
    5. typedef map<string,vector<string> > BT;
    6. void BtOutput(string&,BT&);
    7. int main() {
    8. BT buttons;
    9. string id = "part1";
    10. buttons[id].push_back("bild1.jpg");
    11. buttons[id].push_back("bild2.jpg");
    12. buttons[id].push_back("bild3.jpg");
    13. id = "part2";
    14. buttons[id].push_back("bild3.jpg");
    15. buttons[id].push_back("bild4.jpg");
    16. id = "part1";
    17. cout << "\nInhalt Buttons von Part1:\n";
    18. BtOutput(id,buttons);
    19. id = "part2";
    20. cout << "\nInhalt Buttons von Part2:\n";
    21. BtOutput(id,buttons);
    22. return 0;
    23. }
    24. void BtOutput(string& partnb,BT& bttable) {
    25. for (int i=0;i<bttable[partnb].size();i++) {
    26. cout << bttable[partnb][i] << "\n";
    27. }
    28. }
    Alles anzeigen


    Denke mal das ist soweit korrekt, oder?

    Thomas
    Murphy war ein Optimist.
  • Hallo Thomas,
    ich hab dir mal nen minimales Beispiel fertig gemacht.
    Der Code behandelt so gut wie keine Fehler aber darum musst du dich dann schon selber kümmern :wink: .
    Das ganze bezieht sich auf dein Configfile dass du ganz am Anfang dieses Threads gepostet hast.
    [Part1]
    Button0 = tollesbild.jpg
    Button1 = nochwastolles.jpg

    [Part2]
    Button0 = ani.gif
    Button1 = ani1.gif
    Button2 = ani2.gif

    Schau dir den Code mal an und bei Unklarheiten kannst du ja nachfragen.

    Quellcode

    1. #include <iostream>
    2. #include <string>
    3. #include <fstream>
    4. #include <vector>
    5. #include <map>
    6. class config_parser
    7. {
    8. typedef std::vector<std::pair<std::string,std::string> > pair_vec;
    9. typedef std::map<std::string,pair_vec > vec_map_t;
    10. public:
    11. typedef vec_map_t::const_iterator const_iterator;
    12. typedef pair_vec::const_iterator vec_iterator;
    13. void parse(std::ifstream& is)
    14. {
    15. std::string str;
    16. std::getline(is,str);
    17. do
    18. {
    19. if(is_part_start(str))
    20. {
    21. std::string part(str);
    22. pair_vec temp_vec;
    23. while(std::getline(is,str) && !is_part_start(str))
    24. {
    25. std::string name;
    26. std::string value;
    27. std::string::size_type pos = str.find("=");
    28. if(pos != std::string::npos)
    29. {
    30. name = str.substr(0,pos);
    31. value = str.substr(pos+1);
    32. temp_vec.push_back(std::make_pair(name,value));
    33. }
    34. }
    35. _map.insert(std::make_pair(part,temp_vec));
    36. }
    37. else
    38. std::getline(is,str);
    39. }while(is);
    40. }
    41. const_iterator get_begin(){return _map.begin();}
    42. const_iterator get_end(){return _map.end();}
    43. private:
    44. vec_map_t _map;
    45. bool is_part_start(std::string& s)
    46. {
    47. return (s[0]=='[' && s[s.length()-2]==']');
    48. }
    49. };
    50. int main()
    51. {
    52. config_parser parser;
    53. std::ifstream is("test_conf.txt");
    54. if(is)
    55. parser.parse(is);
    56. else
    57. std::cout<<"Konnte Datei nicht oeffnen"<<std::endl;
    58. is.close();
    59. config_parser::const_iterator start = parser.get_begin();
    60. while(start != parser.get_end())
    61. {
    62. std::cout<<"\nName des Blocks:\t"<<start->first<<std::endl;
    63. std::cout<<"------------------------------------------------------------"<<std::endl;
    64. for(config_parser::vec_iterator vit= start->second.begin();vit!=start->second.end();++vit)
    65. std::cout<<"Name des Eintrags:\t"<<vit->first<<"\t\tWert:\t"<<vit->second<<std::endl;
    66. start++;
    67. }
    68. return 0;
    69. }
    Alles anzeigen


    Gruß void
    "Probleme kann man niemals mit derselben Denkweise lösen,
    durch die sie entstanden sind." (A. Einstein)
  • Hallo void,

    Danke für das Beispiel. Mir ist jetzt verständlich die Daten in den Container kommen. Allerdings habe ich die Geschichte "Iteratoren" noch nicht so wirklich verstanden.

    Ich habe mir zwar schon ein, zwei HowTos durchgelesen, aber geschnallt habe ich die immer noch nicht. Gibt's irgendwo ein verständliches?

    Mir ist zwar klar wie ich mittels *.first und *.second an den Inhalt eines Pair komme, allerdings sind das ja die jeweils zuletzt gespeicherten Elemente. Ich denke mal mit den Iteratoren kann man grob gesagt navigieren. Evtl. hast Du ja einen hilfreichen Link :)

    Thomas
    Murphy war ein Optimist.
  • Allerdings habe ich die Geschichte "Iteratoren" noch nicht so wirklich verstanden.

    Wenn es dir wirklich ernst ist mit c++, solltest du dir nen gescheites buch ueber die STL besorgen ... wo dir der einstieg schonend ins gehirn gemeiselt wird.

    iteration ist nen prinzip. Und bedeutet eigentlich element fuer element durchlaufen.
    Iteraotoren sind demnach hilfskonstrukte, die dir das ermoeglichen sollen.

    unter c++ hat man sich stark an die iteration in c gehalten, in c iteriert man ueber zeiger :

    Quellcode

    1. int arr[2000];
    2. // ueber alle werte iterieren
    3. for(int * iter = arr; iter != &arr[2000] ; ++iter )
    4. {
    5. int test = *iter; // zugriff auf den inhalt....
    6. }


    so sieht ne typische iteration in c aus mittels zeiger und adressen.

    in c++ macht mans genau so, nur mit hilfsmittel ....

    Quellcode

    1. std::list<int> list;
    2. for (std::list<int>::iterator iter = list.begin(); iter != list.end(); ++iter)
    3. {
    4. int test = *iter; // zugriff auf den inhalt....
    5. }


    wichtig zu wissen ist :
    - iteratoren dereferenziert ergibt ne referenz auf das element wo er grad steht ....
    - iteratoren koennen verglichen werden
    - haben mindestens nen increment operator (++ iter)
    - die endekennung &arr[2000] und list.end() zeigen auf was ungueltiges undefiniertes (stelle nach dem array) und sind damit keine gueltigen elemente -> duerfen ned dereferenziert werden

    Alles weitere sind eher Besonderheiten und die solltest du aus dem STL Nachschlagewerk deiner Wahl entnehmen ....

    ich persönlich empfehle Die C++ Standardbiblothek, ISBN 3-540-43212-4.
    Als nachschlagewerk, zum einlesen isses eher etwas sehr trocken ^^
    Aber die funktoren und binder werden ganz gut behandelt .... was man zum extensiven benutzen der STL unbedingt braucht ....

    Ciao ...