Tabellen in c++
-
Guten Tag,
Ich habe bereits gestern in diesem Forum eine Frage gestellt, allerdings im falschen Forum und war wohl etwas auf der falschen Fährte. Darum versuche ich es hier nochmals neu, aber trotzdem vielen Dank an diejenigen, die geantwortet haben.
In google habe ich nicht gefunden, wie man in c++ eine Tabelle erstellt.
Ich meine damit nicht, eine Tabelle auf dem Bildschirm graphisch darzustellen,
sondern eine Menge von Elementen, die sich in einer Bestimmten Spalte in einer bestimmten Zeile befinden. Natürlich mit dem Ziel, auf die Elemente zugreifen zu können, um diese lesen und ändern zu können. Die Anzahl spalten ist unveränderlich, die anzahl Zeilen jedoch dynamisch.
Und ganz entscheidend: Die Tabelle muss abspeicherbar sein, da sie beim erneuter Programverwendung wieder benützt wird.Ein Array kommt dieser Sache schon sehr nahe, allerdings besitzen die verschiedenen Spalten auch verschiedene Datentypen.
Mein (noch nicht funktionierender) Versuch war, einen Struct zeile zu erstellen, der als Zusatzêlement einen Zeiger auf die nächste Zeile enthält.
Dies klappte zunächst gut, aber das Abspeichern scheint mir ganz kompliziert und mir wurde in diesem Forum gesagt, dass ein Profiprogramierer dies nicht so machen würde.Meine Frage nun: Wie löst denn der Profiprogramierer dieses Problem?
Welche (abspeicherbaren)Tabellenoptionen werden üblicherweise in c++ verwendet?
-
Du könntest Deinen
struct zeile{};
in einem
vector<zeile>;
verwalten?
-
hallo Belli,
Vielen Dank für deine Antwort,Leider verstehe ich nicht ganz was du meinst.
Welches Problem löse ich damit?
Wie ich soeben gelesen habe, kann ein vectur nur verwendet werden, wenn alle elemente vom selben Datentyp sind. Da dies nicht der Fall ist, habe ich den Struct erstellt.
-
Ein Array kommt dieser Sache schon sehr nahe, allerdings besitzen die verschiedenen Spalten auch verschiedene Datentypen.
Da liegt also das Problem. Ein einfaches zweidimensionales Array bringt dich hier nicht weit.
Die Anzahl spalten ist unveränderlich, die anzahl Zeilen jedoch dynamisch.
Am Besten nimmst du, wenn die Anzahl der Spalten von vornherein bekannt ist, einfach separate Arrays für die Spalten (und damit Datentypen).
Damit vermeidest du komplizierte Sachen wie "templatizing" der Datentypen (ein besserer Name für diese Technik fällt mir nicht ein; kennt ihr einen?), Variants (
boost::variant
, falls der Zufall es dir erlaubt,QVariant
aus Qt, u. weitere), Type Erasure (boost::any ) & co., zwischen denen du bei einem einzigen, zweidimensionalen Array entscheiden müsstest.
Ich bin noch lange kein Profi-Programmierer, aber so würde ich argumentieren :xmas1:
-
Dies ist ja im wesentlichen dasselbe, was belli zuvor schon geschrieben hat.
Dann habe ich einfach für jede Spalte einen Array, anstatt für jede Zeile einen Struct. Den einzigen Vorteil, den ich daraus sehe ist, dass die Anzahl spalten
fix ist und auch nicht unübersichtlich gross (max ca.12).
Aber das Problem mit der Abspeicherung ist ja deswegen noch nicht gelöst.Wie funktioniert denn dies beispielsweise bei exel?
Ich bin doch nicht der erste, der vor diesem Problem steht.
-
Sag doch konkret, welche Datentypen du für Elemente benötigst. Reicht ein
std::string
nicht?
-
Dann habe ich einfach für jede Spalte einen Array, anstatt für jede Zeile einen Struct. Den einzigen Vorteil, den ich daraus sehe ist, dass die Anzahl spalten
fix ist und auch nicht unübersichtlich gross (max ca.12).Du brauchst überhaupt keine eigene Datenstruktur zu definieren. Je nachdem was du brauchst reicht ein String (
std::string
, kein Zeiger!) oder ein Skalar (int
,float
, ...) als Feldelement.Aber das Problem mit der Abspeicherung ist ja deswegen noch nicht gelöst.
Welches Problem gibt es denn mit einem ganz gewöhnlichen STL-Container (oder allgemein: sequentiellem Array) beim Zugriff auf die Werte
-
sulky schrieb:
Welches Problem löse ich damit?
Das Problem der Datenverwaltung. Du brauchst dann in Deinem struct keinen Zeiger mehr auf die nächste Zeile zu verwalten und der Zugriff auf einzelne Elemente gestaltet sich einfach:
struct zeile { int eins; string zwei; double drei; //usw. }; ... vector<zeile> myVector(5); myVector[0].eins = 4; myVector[1].drei = 2.56; ...
-
typedef struct cell { enum { NUMBER, STRING } type; union { double number; char *string; } data; } cell;
Diese Lösung ist besser als die von Belli. Erstens wird weniger Speicherplatz benötigt und zweitens ist nur EIN Wert möglich, nicht
zwei="2"
unddrei=3.0
gleichzeitig.
-
Hmm, jetzt hab ich mich verraten. Echte Excel-Programmierer verwenden UN.
-
In meinem Beispiel repräsentiert die struct eine ganze Zeile bestehend aus drei Spalten mit verschiedenen Datentypen.
-
excel hacker schrieb:
Diese Lösung ist besser als die von Belli.
Du kannst schon mal keinen
std::string
verwenden, musst dir also mit manueller Speicherverwaltung und den C-String-Funktionen alles zusammenfrickeln. Tolle Lösung.
-
Diese Lösung ist besser als die von Belli.
Deine Lösung ist auf gut Deutsch Blödsinn. Ich habe bereits Variants erwähnt, und die sind hier schon unpassend.
Nexus schrieb:
excel hacker schrieb:
Diese Lösung ist besser als die von Belli.
Du kannst schon mal keinen
std::string
verwenden, musst dir also mit manueller Speicherverwaltung und den C-String-Funktionen alles zusammenfrickeln. Tolle Lösung.Dein Punkt lässt sich ja noch mit hässlichem drumherum lösen (user-provided ctor+dtor). Aber es gibt schlimmere Macken.
Der Benutzer ist auch noch selbst für die Typsicherheit verantwortlich (+ welchen Wert
type
hat) - nervig. Es gibt zudem keine Form von Fehlersignalisierung, wenn mantype
ignoriert und auf einen uninitialisierten Member zugreift ....
-
Könntest du irgendwie aufzeigen wie genau die tabelle aussehen soll?
Sind die Datentypen für die einzelnen Spalten fest? Oder können diese auch "dynamisch" sein.
Wenn die datentypen für die einzelnen spalten fest sind, dann ist dein Ansatz mit der Struct doch korrekt.
Um Zeilen dynamisch zu verhalten kannst du einen Container wie std::vector verwenden:Z.b.
#include <vector> #include <iostream> struct table_line { std::string column1; float column2; int column3; }; void print_line(table_line &line) { std::cout<<line.column1<<", "<<line.column2<<", "<<line.column3<<"\n"; } int main() { std::vector<table_line> table; table_line line; line.column1 = "hallo"; line.column2 = 12.5f; line.column3 = 100; table.push_back(line); print_line(table[0]); table[0].column3 = 200; print_line(table[0]); return 0; }
Ausgabe:
hallo, 12.5, 100
hallo, 12.5, 200Im Grunde der Vorschlag, den auch Belli gebracht hat.
Und wegen speichern und laden der Tabelle.
Hierfür könntest du eine csv Datei erstellen.
Für das einlesen könnte dir dieser Thread helfen: Dateiinhalt - Komma-Separator - Wie elegant auslesen?