
frobber
Mitglieder-
Gesamte Inhalte
6 -
Benutzer seit
-
Letzter Besuch
-
Gibts Turbo C++ überhaupt noch? Das hab ich schon sehr lange nicht mehr gesehen. Tut jetzt aber auch nichts zur Sache. Dein Problem ist nicht ganz einfach und recht aufwändig in der Implementierung. Es kommt halt drauf an wie weit man das treiben will. Wie _n4p_ schon gesagt hat gibt es auch freie Bibliotheken, die sich mit dem Thema XML beschäftigen. Die Einarbeitung in solche Bibliotheken ist aber nicht zu unterschätzen, aber es lohnt sich durchaus, wenn du etwas Zeit hast. Es kommt jetzt hauptsächlich darauf an, wie fit du in C/C++ bist und wieviel Zeit du hast. Ich würde mal den Fakt, dass es sich um eine XML Datei handelt aussen vor lassen. Hier geht es hauptsächlich darum, dass du ein paar Funktionen zum parsen der verschiedenen Tags findest. Ich hab leider nur wenig Zeit, möchte dir aber einen möglichen Ansatz zeigen. Zuerst musst du mal ein paar sinnvolle Strukturen finden, also zum Beispiel: // datum struct sDate { unsigned char Day; // 1...31 unsigned char Month; // 1...12 unsigned Year; // 0...?? unsigned char Weekday;// 0..6 (0-Montag, ... , 6-Sonntag) }; // eine einzelne Losung struct sLosung { sDate Date; std::string Losungstext; std::string Losungsvers; std::string Lehrtext; std::string Lehrtextvers; }; // alle eingelesenen Losungen std::vector<sLosung> Losungen; Ich würde zuerst alle Losungen aus der Datei einlesen und in einem Array speichern. Eine spätere Suche wird so sehr viel einfacher. Das ist nicht sehr kompliziert. Du brauchst also eine/mehrere Funktion(en), die die Datei zeilenweise einliest und nach bestimmten Tags sucht und diese auswertet (parsen). Ich würde in etwa folgendes tun: - finde das Tag <Losungen> (das Root-Tag einer Losung) - lese alle Zeilen bis </Losungen> jetzt haben wir alle relevanten Daten einer einzelnen Losung - finde das Tag <Datum> und lese bis </Datum> - parse das eingelesene Datum - finde das Tag <WTAG> und lese bis </WTAG> - parse den eingelesenen Wochentag ... Du siehst sicherlich wo das lang geht. Zu jeder fertig eingelesenen und geparsten Losung erstellst du eine Struktur, wie oben gezeigt und speicherst sie einem Array. Das ganze wiederholst du so lange, bis alle Losungen eingelesen sind und strukturiert in einem Array vorliegen. Anschließend brauchst du nur noch eine Funktion, die dir zu einem bestimmten Datum die entsprechende Losung aus dem Array raussucht. Ich hoffe das hilft dir etwas auf die Sprünge. Gruß Frobber
-
Ein kurzes Beispiel, wie die XML Datei aussieht wäre hilfreich. Spielt in einer XML Datei mit 365 Einträgen das Jahr eine Rolle? Ich gehe mal davon aus, dass jedem Tag ein Vers mit 7-8 Zeilen zugeordnet ist?
-
Mehrere Libs vollständig an eine dll linken
frobber antwortete auf Reudiger Fuchs's Thema in C++: Compiler, IDEs, APIs
Diese Einschätzung ist soweit korrekt, nur das nicht libA.cpp benötigt wird, sondern der Linker in LibA.lib nach der entsprechenden Funktion sucht. Nein das geht so nicht. Du kannst keine Funktionen aus einer statischen Bibliothek durch eine DLL exportieren. Exportierte Funktionen müssen auch in der DLL definiert werden ansonsten wird der Linker auch nichts unternehmen eine Funktion zu suchen, die nie verwendet oder definiert wird . Ich sehe zwei Möglichkeiten: 1) Du kannst die .cpp Dateien der verschiedenen Bibliotheksprojekte mit in das DLL Projekt einbinden. Wenn dann die Funktionen der statischen Bibliotheken, wie von dir gezeigt mit __declspec(dllexport) deklariert sind, werden sie mit exportiert, da sie ja jetzt Bestandteil des DLL Projektes sind. 2) Du kannst aus der DLL Wrapperfunktionen exportieren, welche die Funktionen der statischen Bibliothek aufrufen. ist wohl aber eher nicht das was du willst. Leider sehe ich keine anderen Möglichkeiten. -
Du denkst dabei wahrscheinlich an eine Änderung der Daten durch dynamisches allokieren mittels 'new' oder 'malloc'. Dadurch ändert sich aber nichts an der größe der Struktur an sich, sondern lediglich quasi semantisch der Inhalt der Struktur. Dem 'sizeof(...)' Operator ist es egal. Bsp.: struct A { unsigned Size; // sizeof(A) char* pData; // dynamisch allokierter Speicher ... }; void foo() { struct A a_dummy; // instance of A unsigned i = sizeof(a_dummy); // i ist 8 a_dummy.pData = (char*)malloc(10); i = sizeof(a_dummy); // ist ist immernoch 8 } Die einmal durch Deklaration definierte Größe einer Struktur kann sich zur Laufzeit nicht ändern. In dem Punkt geb ich dir teilweise Recht, aber das ist eher eine Frage der Plattform, als eine des Compilers. Primitive Datentypen werden zwischen verschiedenen Compilern auf der selben Plattform (im Sinne von Linux, Windows, ARM) in der Regel gleich behandelt. Interessanter ist da eher die Frage nach dem Packing der Strukturen. Da kann man schnell auf Nase fallen. Ja ich würde auch eher deine Lösung wählen, wenn ich nicht genau weiß was mit den Strukturen im Laufe der Entwicklung noch so passiert.
-
Da nach deinen eigenen Angaben die Möglichkeit mit mehreren Funktionen ausfällt, würde ich die Lösung von TDM in Betracht ziehen, also einen zusätzlichen Paramter übergeben welcher die Struktur identifiziert. Ich wollte hier blos nochmal eine Lösung zeigen, die Microsoft oft in iherer API verwendet. Die geben einfach jeder Struktur einen Längenparameter mit und unterscheiden anhand der Länge, um welche Struktur es sich handelt, also: struct A { unsigned Size; // sizeof(A) ... }; struct B { unsigned Size; // sizeof( ... }; Wichtig ist dabei, dass der Längenparameter immer an erster Stelle steht und die verschiedenen Strukturen auch tatsächlich eine unterschiedliche Größe haben, damit sie so überhaupt unterscheidbar sind. Die Auswertung könnte dann in etwa so aussehen: void foo(void* pData) { unsigned size = 0; struct A* pA; struct B* pB; if(pData != 0) { size = *(unsigned*)pData; if(size == sizeof(struct A)) { pA = (struct A*)pData; // ... } else if(size == sizeof(struct ) { pB = (struct B*)pData; //... } ... } } Microsoft verwendet diese Technik, um Strukturen zu unterscheiden, die sich im laufe der Zeit mal verändert haben und um einige Sachen erweitert wurden. Gruß Frobber
-
Ich denke ich habe dein Problem verstanden: Dein Programm scheint ja soweit korrekt zu sein. 1) In der Schule geht ihr so vor, dass ihr das Programm mit VisualStudio Express compiliert und dann mit Hilfe der getrennt zur Verfügung gestellten Konsole startet. Diese Konsole ist nichts weiter, als das die ganz 'normale' Eingabeaufforderung mit ein paar zusätzlichen definierten Umgebungsvariablen, die vom VisualStudio benötigt werden. Beim Aufruf des Programms mit der Konsole gibst du dann alle benötigten Parameter mit an, also "<Programmname> <Parameter1> <Parameter2> ..." . Diese Vorgehensweise ist zwar etwas umständlich, aber völlig ok. 2) Zu Hause nimmst du CodeBlocks und als Compiler den gcc aus der MinGW Umgebung. Soweit so gut. Durch den Befehl 'Build and Run' compilerst du dein Projekt und anschließend wird es sofort gestartet. Hier liegt auch dein Problem. Du hast offensichtlich nicht angegeben mit welchen Parametern dein Programm (automatisch) gestartet werden soll und dein Programm beschwehrt sich anschließend mit Recht darüber, dass es keine hat. Lösung: a) Auch CodeBlocks bietet die Möglichkeit dein Projekt nur zu compileren und nicht automatisch zu starten. Den genauen Menüpunkt hab ich nicht im Kopf. Anschließend startest du die Eingabeaufforderung (Befehl: cmd) und wechselst in das Ausgabeverzeichniss deines Projektes. Dort sollte sich die erstellte EXE deines Programms befinden. Jetzt kannst du wie in der Schule dein Programm mit allen benötigten Parametern aufrufen. Sowohl VisualStudio, als auch CodeBlocks bieten in den Projeteinstellungen einen Menüpunkt 'Debuggen'. Die genaue Bezeichnung bei CodeBlocks ist mir auch hier nicht bekannt, aber das sollte zu finden sein :cool:. Dort kann eingestellt werden, wie das fertig erstellte Programm gestartet werden soll. Dort sind hauptsächlich die Einstellungen für das 'Working Directory' und die 'Command Arguments' wichtig. Der Working Path ist Standarmäßig das Ausgabeverzeichnis des Compilers. Im Punkt Commandline Arguments werden zusätzliche Argumente angegeben, die dein Programm benötigt. Wenn du dort die deine Parameter angibst sollte alles funktionieren. Nachtrag: Der Befehl 'Build and Run' in CodeBlocks, beziehungsweise 'Run' im VisualStudio machen das gleiche, wie du in der Konsole. Sie öffnen eine Konsole und starten dein Programm mit den in den Projekteinstellungen angegebenen Parametern. Ich hoffe das war verständlich Viel Erfolg