Datenaustausch zwischen Funktionen (Greedy-Algorithmus)
-
Zunächst mal musst du nicht alle Variablen in der Paramterliste definieren.
Laufvariablen von Schleifen haben da sehr, sehr selten etwas zu suchen.Dann solltest du auch bessere Namen wählen. c ist sowas von nichtssagend.
Meist wird damit ein einzelner char benannt.i für die Laufvariable ist ok. Dann aber bitte lokal.
Noch loakler. Die kannst du im der Schleifenkopf definieren.
Und fang bei 0 an zu zählen.Zudem solltest du die maximale Größe der Arrays auch mit an die Funktion übergeben. (Wenn die gleich groß sind, reicht ein Wert)
Zu deinem Fehler:
Das *i++ in der for-Schleife macht nicht das, was du möchtest.
Das verändert i (also den Zeiger) und nicht *i (den Wert, auf den i zeigt)for (int i = 0; i < *anzahl; i++)
-
Nochmal zu den Variablennamen:
du schreibstdouble w[MAXITEMS], // Gewichte p[MAXITEMS]; // Profit, dessen Summe maximal werden soll
Warum nennst du die Variablen nicht genau so, wie die Kommentare dahinter? Also:
double weights[MAXITEMS]; double profits[MAXITEMS];
Dann kannst du da wohl auch auf den Kommentar verzichten, wenn die Variable gleich gut benannt ist.
Und for-Schleifen so (beachte insbesondere das "int i" - das ist eine wirklich nur in der Schleife verfügbare Variable - du sollst hier nicht irgendein i von anderswo recyclen):
for (int i = 0; i < anzahl; ++i){ ... }
PS: Komischer Lehrer, der in C++ Arrays gleich am Anfang beibringt - auf Arrays kann man erstmal ganz verzichten, wenn man gleich vector<> lehren würde.
-
Vielen Dank DirkB!
Ich nehme mir deine Anregungen zu Herzen. Das mit der sinnfreien Übergabe von Laufvariablen sehe ich ein, das habe ich nun zunächst mal lokal in der Funktion definiert. Die Initialisierung in Schleifen prüfe ich später dann nochmal, wenn das Programm an sich insgesamt ohne globale Variablen läuft.
Außerdem überprüfe ich dann noch die Namen meiner Variablen. Solche Hinweise sind wirklich nützlich, ich arbeite bei wirtschaftswissenschaftlichen Rechnungen häufig mit "c" welche für irgendeine Kapazitätsrestriktion steht und habe das einfach so in den Code übernommen.
Die maximale Größe der Arrays habe ich nun als globale Konstante im Programm - ich denke das ist absolut in Ordnung, da mit "const" definierte Variablen ohnehin unveränderlich sind, nachdem sie anfangs initialisiert wurden.
Jedenfalls habe ich den Arrays nun mit "MAXITEMS" die maximale Größe beim Funktionsaufruf mitgegeben.Und vielen Dank, das war der Fehler! Wenn der Zeiger natürlich plötzlich in irgendwie geartete Werte springt kann das ja nicht funktionieren.
Wunderbar! Ich denke, mit dem Wissen das ich hier mitnehmen konnte kann ich nun auch problemlos mit den nächsten zwei Funktionen fortfahren! Wenn ich den Programmablauf durchdenke sollte der Rest genau so abzuarbeiten sein.
Nochmal vielen Dank für die Hilfe! Ich melde mich hier nur nochmal dann, wenn Fehler auftreten und ich diese mithilfe meiner Unterlagen oder mit Dokumentationen selber nicht nachvollziehen kann
Edit:
@wob: Na da bin ich aber noch gespannt, wann das Thema "vector" im Unterricht aufkommt. Wenn ich lese, dass Arrays damit unnötig werden, dann joa. Mal sehen, wie er uns das dann auftischt.Wie ich oben schon zu Dirk geschrieben habe sollte ich mir wirklich noch Gedanken über klar definierte Variablennamen machen. Ich empfand die Nutzung von Variablennamen mit einem Buchstaben als "schick" und "schlank". Bevor ich diese Übungsaufgabe abgebe werde ich das nochmal ändern.
Und gut, ihr habt mich auch von der Sinnhaftigkeit überzeugt Laufvariablen nur in Schleifen zu nutzen und nicht herum zu tragen. Wird geändert
-
PS: in deinem Fall natürlich *anzahl in der for-Schleife, aber eigentlich ist ein pointer auf ein int eher ungewöhnlich in dieser Situation.
Und eine Funktion mit 6 (!) Parametern hat schon grenzwertig viele Parameter. Weniger ist oft mehr - bei vielen Parametern wird der Code schnell unübersichtlich. Aber gut, wenn ihr noch keine structs kennt...
-
Ja ich denke mal das ist nur so, weil der Dozent mit den Strukturen noch einen Moment abwarten möchte.
Bei mir tauchte nun leider neue Fehlermeldung auf:
1>Rucksack-Problem.obj : error LNK2001: Nicht aufgelöstes externes Symbol ""void __cdecl berechnung(int *)" (?berechnung@@YAXPAH@Z)".
Ich habe doch außer die Include-Dateien nichts Externes eingebunden, wie kann es da dann zu so einem Fehler kommen? Im Internet stößt man wenn man nach diesem Fehler sucht nur auf Probleme in der objektbezogenen C++ Programmierung.
Edit: Okay, habe den Fehler bereits behoben. Ich habe nochmal meinen Prototypen "berechnung", den Funktionsaufruf und die darin aufgerufenen Variablen überprüft und nochmal ergänzt. Auch, wenn ich nicht weiß warum, hat sich das Problem dadurch erübrigt.
-
Gibt es einen Grund warum du dich mit den Zeigern quälst? Stattdessen wären Referenzen hier wesentlich einfacher zu nutzen. Damit würdest du dir einige Dereferenzierungen sparen, da sich Referenzen wie "normale" Variablen verhalten.
Noch ein Tipp: Du solltest beim Öffnen der Datei prüfen, ob ein Fehler aufgetreten ist und darauf reagieren.
bool Dateneingabe() { std::ifstream ifs; ifs.open(...); if (!ifs.is_open()) return false; // ... return true; } // In main() oder wo auch immer if (!Dateneingabe()) { // Error return 1; } Weiterarbeiten();
-
Guten Morgen!
Zu deiner Frage gfhf..., die Möglichkeit Referenzvariablen zu nutzen habe ich vor den Zeigern in Betracht gezogen. Leider erhalte ich beim kompilieren sofort einen kryptischen Fehler, den ich beim recherchieren nur bei Fragen zur objektbezogenen C++ Programmierung, z.B. Spieleprogrammierung, finde.
error LNK2001: Nicht aufgelöstes externes Symbol void __cdecl ?@@YAXHHH@Z)".
Dabei beziehe ich doch, außer bei den #Include-Dateien, keine externen Dateien mit ein. Deswegen habe ich mich dann mit Zeigern beschäftigt und das Programm gestern auch fertigstellen können, obwohl es nun derzeit durch die Übergabe von teilweise 6-7 Parametern beim Funktionsaufruf sehr unübersichtlich wird (ist aber nun leider die Vorgabe). Nun ja, das ist der Grund, warum ich keine Referenzvariablen genutzt habe: weil der Compiler dabei einfach rumspinnt.
Ich kann mir vorstellen, dass ich in einer nächsten Übungsaufgabe diese Sachen dann wie hier mehrfach vorgeschlagen in Strukturen zusammenfassen soll.
-
Xalion schrieb:
weil der Compiler dabei einfach rumspinnt.
Quatsch.
Der Compiler macht keine Fehler.
Du machst die Fehler. Wenn du den Compiler nicht bedienen kannst, sprich - nicht programmieren kannst - kann der Compiler nichts dafür.
Wenn du Unsinns-Lehrpraktiken deiner Deppen-Professoren das Wort redest, kannst du zwar letztendlich auch nichts dafür, lernst aber eben zuerst mal Unsinn.
Und es ist schizophren etwas zu lernen, wovon man vorher schon weiß, dass das Unsinn ist. Und in dieser Unsinns-Lernphase rumzujammern ist dann bloß noch naiv.
-
Xalion schrieb:
Guten Morgen!
Zu deiner Frage gfhf..., die Möglichkeit Referenzvariablen zu nutzen habe ich vor den Zeigern in Betracht gezogen. Leider erhalte ich beim kompilieren sofort einen kryptischen Fehler, den ich beim recherchieren nur bei Fragen zur objektbezogenen C++ Programmierung, z.B. Spieleprogrammierung, finde.
error LNK2001: Nicht aufgelöstes externes Symbol void __cdecl ?@@YAXHHH@Z)".
Dabei beziehe ich doch, außer bei den #Include-Dateien, keine externen Dateien mit ein. Deswegen habe ich mich dann mit Zeigern beschäftigt und das Programm gestern auch fertigstellen können, obwohl es nun derzeit durch die Übergabe von teilweise 6-7 Parametern beim Funktionsaufruf sehr unübersichtlich wird (ist aber nun leider die Vorgabe). Nun ja, das ist der Grund, warum ich keine Referenzvariablen genutzt habe: weil der Compiler dabei einfach rumspinnt.
Ich kann mir vorstellen, dass ich in einer nächsten Übungsaufgabe diese Sachen dann wie hier mehrfach vorgeschlagen in Strukturen zusammenfassen soll.
Vielleicht kannst du ja ein kleines Beispielprogramm zeigen, dass diesen Fehler aber noch beinhält. Mit Zeigern wirst du langfristig aufjedenfall Fehler machen. Insofern sollte man es vermeiden damit zu hantieren, wenn es nicht nötig ist.
-
Und es ist schizophren etwas zu lernen, wovon man vorher schon weiß, dass das Unsinn ist.
Nein. Es ist (leider) nötig. Weil nur so der Deppen-Prof die Punkte vergibt.
Idealerweise lernt man den Unsinn, und behält klar im Hinterkopf "das ist Unsinn", während man die richtigen Methoden lernt.