Auslagerung Funktion mit struct-Kombination in eigenes .cpp-File
-
Liebe Forumspezialisten,
derzeit habe ich den gesamten Programmcode in einem .cpp-File. Mittlerweile wird das schon etwas unübersichtlich und ich möchte diverse Funktionen auslagern. Leider habe ein Problem bei der Auslagerung einer readin-Datei in ein eigenes .cpp-File. Das Auslagern eine Zufallszahlenerzeugungs-Funktion ging ohne Probleme (mit Headerdatei und eigener .cpp Datei).
Bei der readin-Datei übergebe ich eine komplexere Kombination aus structs (myStruct *production) an die Funktion und dabei habe ich es bis jetzt noch nicht geschafft die Dateiei „Read_Data.h“ und „Readin.cpp“ richtig zu definieren.
Könnt ihr mir bitte anhand des unten angeführten und reduzierten Beispiels sagen, wie die externen Dateien ausgefüllt gehören, sodass ich in meiner Hauptdatei auf die extern ausgelagerte Readin-Datei korrekt zugreifen kann?
#include<iostream> #include<vector> #include<algorithm> #include<fstream> #include<string> #include<Windows.h> #include "Random_numbers.h" #include "Read_Data.h" using namespace std; // Struct struct ProdtoBlock{ int prodnr; int blocknr; }; struct struct_solutions{ vector<vector<int>> production_per_product; vector<vector<int>> setup_route; }; struct myStruct{ vector<vector<int>> demand; … … … vector<ProdtoBlock>prodtoblock; int prodnr; int blocknr; struct_solutions solutions; vector<struct_solutions> save_solutions; vector<vector<int>> production_per_product; vector<vector<int>> setup_route; }; // Globale Variablen int blocki, blockj, products, macroperiods, microperiods; // Funktionen void readData(myStruct *production); int main(){ myStruct production; readData(&production); vector<ProdtoBlock> prodtoblock; vector<struct_solutions> save_solutions; … calculatecost(&production); … return EXIT_SUCCESS; } void readData(myStruct * production) { ifstream in("ABC.txt"); char line[1000]; if(in.fail()) { cout << "Couldnt open ABC.txt"; exit(0); } //1. line in.getline(line, 1000); //2. line (blocks) in.getline(line, 1000, ':'); in >> blocki; blockj = blocki; … … … //8-15. line (Demand-Matrix) for (int k=0; k < products; k++) { vector<int> row; for (int d=0; d < macroperiods; d++) { int input=1; in >> input; row.push_back(input); } (*production).demand.push_back(row); } }Vielen Dank für Eure Hilfe!
Mit freundlichen Grüßen
PaX
-
PaX_1960 schrieb:
Könnt ihr mir bitte anhand des unten angeführten und reduzierten Beispiels sagen, wie die externen Dateien ausgefüllt gehören, sodass ich in meiner Hauptdatei auf die extern ausgelagerte Readin-Datei korrekt zugreifen kann?
Bitte weiter reduzieren, bis es minimal ist und noch das Problem zeigt.
Bitte nicht soweit reduzieren, daß es nicht mehr in den Compiler passt. So … im Code bringen mir nix, die machen nur Fehlermeldungen, die nix mit der Frage zu tun haben.
-
Hallo Volkard,
danke erstmal für deine Antwort. Ich habe das Programm jetzt noch etwas reduziert und so gestaltet, dass du es einfach copy-paste übernehmen kannst. Ich hoffe du kannst damit etwas anfangen.
#include<iostream> #include<vector> #include<algorithm> #include<fstream> #include<string> #include<Windows.h> //#include "Readin.h" using namespace std; // Struct struct ProdtoBlock{ int prodnr; int blocknr; }; struct myStruct{ vector<vector<int>> demand; vector<ProdtoBlock>prodtoblock; int prodnr; int blocknr; }; // Globale Variablen int products, macroperiods; // Funktionen void readData(myStruct *production); int main(){ myStruct production; readData(&production); vector<ProdtoBlock> prodtoblock; //Ausgabe cout << products << " " << macroperiods << endl; for(int k=0; k < products; k++) { for( int d=0; d < macroperiods; d++) { cout << production.demand.at(k).at(d) << "\t"; } cout << endl; } getchar(); getchar(); return EXIT_SUCCESS; } void readData(myStruct * production){ ifstream in("Input.txt"); char line[1000]; if(in.fail()) { cout << "Fehler beim oeffnen von Input.txt"; exit(0); } //1. Zeile Überschrift in.getline(line, 1000); //3.Zeile (Anzahl Produkte) in.getline(line, 1000, ':'); in >> products; //4.Zeile (Anzahl Makro-Perioden) in.getline(line, 1000, ':'); in >> macroperiods; //6-7. Zeile (leere Zeilen) in.getline(line, 1000); in.getline(line, 1000); in.getline(line, 1000); //8-15. Zeile (Demand-Matrix) for (int k=0; k < products; k++) { vector<int> row; for (int d=0; d < macroperiods; d++) { int input=1; in >> input; row.push_back(input); } (*production).demand.push_back(row); } }Die Input.txt lautet:
Input für das Programm
Products: 8
Macro-Periods: 5Demand
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
6 6 6 6 6
7 7 7 7 7
8 8 8 8 8Also die Frage lautet nun: Wie müssten die Dateien Readin.cpp und Readin.h gestaltet sein, sodass die Funktion readData ausgelagert ist.
Vielen Dank für Eure Hilfe,
mit freundlichen Grüßen
PaX
-
Ich versuchs mal.
In die Readin.cpp kommt der Code für readData und die globalen Variablen die dazu gehören.
Dort bindest du auch nur die Header ein, die du für den Code brauchst.In die Readin.h kommen die Deklarationen und Definitionen, die nötig sind, damit du readData (in
main) aufrufen kannst.
Das sind z.B. diestructsund auch der Prototyp von readData
Dort bindest du auch nur die Header ein, die nötig sind.Die globalen Variablen darfst du im Header nur bekannt geben. Dazu schreibst du ein extern davor.
Dasusing namespace std;hat im Header auch nichts zu suchen.Readin.h
#include<vector> // Struct struct ProdtoBlock{ int prodnr; int blocknr; }; struct myStruct{ vector<vector<int>> demand; // anpassen wegen std:: vector<ProdtoBlock>prodtoblock; // anpassen wegen std:: int prodnr; int blocknr; }; // Globale Variablen deklarieren extern int products, macroperiods; // Funktionen void readData(myStruct *production);Readin.cpp
#include <nur das nötige> #include "Readin.h" using namespace std; // muss das sein? // Struct // stehen in Readin.h // Globale Variablen definieren. Hier wird der Speicherplatz belegt int products, macroperiods; // Funktionen // void readData(myStruct *production); das steht auch schon in Readin.h // Andere Funktionen, die du nur hier brauchst kannst du hier deklarieren. Die kommen nicht in den Header void readData(myStruct * production){ dein Code hier }main.cpp
#include <auch nur das nötige> #include "Readin.h" int main(){ myStruct production; // bekannt aus Readin.h readData(&production); // bekannt aus Readin.h ... return EXIT_SUCCESS; }Jede *.cpp Datei wird für sich alleine compiliert. Dazu muss dem Compiler alles bekannt sein, was er dafür braucht.
Dabei werden die Dateien, die bei#includeangegeben sind in den Code mit eingefügt (Textersatzt).
Da wo vorher #include "Readin.h" stand, steht dann der ganze Inhalt von Readin.h (auch wieder mit den eingefügten includes).
-
Hallo DirkB,
vielen Dank für deine kompetente Hilfe. Du hast das wirklich anschaulich und verständlich erklärt.
Ich verwende das (MyStruct *production) auch noch für andere Funktionen im main-Bereich. Das heißt die Struct-Deklarationen werden von Readin.h "eingespielt" und (MyStruct *production) kann auch von anderen Funktionen verwendet werden. (So wie du es beschrieben hast)
Durch Zufall bin ich auf eine andere Variante gekommen und wollte fragen ob das auch zulässig ist:
Readin.cpp und Readin.h bleiben unverändert, jedoch habe ich die Struct-Deklaration im main-File zusätzlich eingefügt. Damit das ganze funktioniert darf jedoch im main-File das #include "Readin.h" NICHT inkludiert werden.Ist das auch eine zulässige Variante wenn ich Struct-Deklaration aus Übersichtlichkeit im main-File lassen möchte, weil eben andere Funktion auch darauf zugreifen? (Die "Deklarationen" finden beim auslagern dann halt doppelt statt...)
Vielen Dank,
mit freundlichen Grüßen
PaX
-
PaX_1960 schrieb:
Ist das auch eine zulässige Variante wenn ich Struct-Deklaration aus Übersichtlichkeit im main-File lassen möchte,
Du baust damit eine mögliche Fehlerquelle ein, wenn du die struct änderst.
Du brauchst dann auch noch die Prototypen aus ReadIn.h und ....Du schreibst den Inhalt von ReadIn.h nochmal in main.c
Aber genau das macht das #include "ReadIn.h" schon automatisch.
Was ist verstehst du unter mehr Übersichtlichkeit?
Nutze deine IDE aus. die kann dir die struct-Member auch anzeigen.Aus Compilersicht ist das zuläassig.
Aus Sicht der Wartbarkeit, Qualitätssicherung und Sicherheit absolut nicht.Durch *MyStruct production wird die Variable (Zeiger) production angelegt.
Wo, wann und wie oft du die verwendest ist egal. Du gibst diese Variable ja an die Funktionen weiter.
Der Compiler muss nur bei der Definition und beim Zugriff darauf wissen, wie MyStruct aufgebaut ist.
Dies passiert mit dem #include "ReadIn.h"
-
Ursprünglich habe ich gedacht dass es übersichtlicher ist wenn die struct-Deklaration im main-File bleibt da sie von mehreren veschiedenen Funktion benötigt wird. Es erschien mir unlogisch die Deklaration einer Funktion (in diesem Fall ReadData) zuzuordnen wenn sie von anderen Funktionen auch benötigt wird...
Aber ich finde deine Argumente durchaus einleuchtend, dass diese Mehrfachdeklaration eher eine Fehlerquelle ist, als eine Hilfe bei der Übersichtlichkeit.Danke jedenfalls für deine Hilfe/Tipps.
Mit freundlichen Grüßen
PaX
-
Die Deklaration muss auch nicht in ReadIn.h stehen, aber in main.cpp sollte sie auf gar keinen Fall.
Du kannst auch ein myStruct.h machen, wo nur diesestructdeklariert wird.
Dies musst du dann aber in ReadIn.cpp einbinden. Und auch in ReadIn.h, da du myStruct in der Paramterliste von readData hast.ReadIn.cpp stellt Funktionen zur Verfügung. Alle Informationen, die der Compiler zur Nutzung dieser Funktionen braucht, kommt in ReadIn.h
Aus ReadIn.cpp rufst du dann wiederum andere Module auf (und nutzt deren Header). Das verzweigt sich dann immer weiter nach unten.
mainsteht da an oberster Stelle.