Expected primary expression before a & token
-
Hallo, ich habe ein Problem in einem von mir geschrieben C++ Übungs-/Lern-Programm gemäß des Wortlautes im Betreff und würde mich freuen wenn es hier jemanden gibt, der mir weiterhelfen kann.
Das eigentliche Programm:
#include <iostream> #include <stdlib.h> #include "date.h" #include "bio.h" using namespace std; Date b_date, today; int main() { cout << "Hallo!" << endl; cout << "Dieses Programm berechnet den Biorythmus" << endl; cout << "einer Person aus ihrem Geburtsdatum" << endl; cout << "und dem aktuellen Datum." << endl; Marke: cout << "Wann ist die Person geboren?\t" << endl; b_date.get_date(b_date); b_date.days = b_date.get_days(b_date); cout << "Welches Datum ist heute?\t" << endl; today.get_date(today); today.days = today.get_days(today); if(b_date.days > today.days) { cout << "Die Person ist leider noch gar nicht geboren worden." << endl; cout << "Bitte wiederholen Sie Ihre Eingabe." << endl; goto Marke; } else { cout << "Der berechnete Biorythmus lautet wie folgt:" << endl; cout << "Geistig:\t" << MENTAL(today.days - b_date.days) << "%" << endl; cout << "Körperlich:\t" << PHYSICAL(today.days - b_date.days) << "%" << endl; cout << "Seelisch:\t" << EMOTIONAL(today.days - b_date.days) << "%" << endl; return (EXIT_SUCCESS); } }Der erste Header:
#include <math.h> #ifndef M_PI #define M_PI 3.1415926538979323846 #endif /* * MACROS * L_Y: Anzahl der Schaltjahre * IS_L_Y: Handelt es sich um ein Schaltjahr? * MENTAL, PHYSICAL, EMOTIONAL: * Biorythmus zwischen -100% (down) und 100% (gut) * * PS * Normalerweise gibt es alle 4 Jahre ein Schaltjahr, ausser das Jahr * laesst sich durch 100, aber nicht durch 400 teilen. * * Der Wert von pi ist in <math.h> als M_PI definiert */ #define L_Y(y) ((y) / 4 - (y) / 100 + (y) / 400) //Anzahl Schaltjahre #define IS_L_Y(y) (((((y) % 4) == 0) && (((y) % 100) != 0)) || \ (((y) % 400) == 0)) //Überprüfung auf Schaltjahr #define MENTAL(d) (sin ((d) * 2 * M_PI / 23) * 100) #define PHYSICAL(d) (sin ((d) * 2 * M_PI / 28) * 100) #define EMOTIONAL(d) (sin ((d) * 2 * M_PI / 33) * 100)Der Class-Header:
#include <iostream> #include <exception> #include <string> #include "bio.h" using namespace std; bool valid_date; unsigned char c; class Date { public: unsigned int day, month, year; unsigned long days; void get_date(Date &r); bool is_date(Date &r); unsigned long get_days(Date &r); Date() { day = 0; month = 0; year = 0; days = 0; } }; void Date::get_date (Date &r) //Funktion zum Einlesen des Datums { valid_date = false; while(!valid_date) { cout.flush(); cout << "Bitte Datum (tt.mm.jjjj) eingeben:\t"; cout.flush(); //Puffer leeren cin >> r.day >> c >> r.month >> c >> r.year; //Datum einlesen und valid_date = r.is_date(Date &r); //'weglesen' von Punkten } return; } bool Date::is_date(Date &r) //Funktion zur Überprüfung des Datums auf Richtigkeit { if (r.year < 1) //Keine Jahre vor 1 A.D. { cout << endl; cerr << "Ungueltige Jahresangabe (<0!)" << endl; return false; } if (r.month < 1 || r.month > 12) //Monate nur zwischen 1-12 { cout << endl; cerr << "Ungueltige Monatsangabe (<0 oder >12!)" << endl; return false; } if (r.day < 1 || r.day > 31) //Tage nur zwischen 1-31 { cout << endl; cerr << "Ungueltige Tagesangabe (<0 oder >31!)" << endl; return false; } else { if((r.month == 4 || r.month == 6 || r.month == 9 || r.month == 11) && r.day > 30) //Monat mit nur 30 Tagen { cout << endl; cerr << "Ungueltige Tagesangabe " "(Dieser Monat hat nur 30 Tage!)" << endl; return false; } if(r.month == 2 && r.day > 29 && IS_L_Y(r.year)) //Februar Schaltjahr { cout << endl; cerr << "Ungueltige Tagesangaben" "(Dieser Monat hat nur 29 Tage!)" << endl; return false; } if(r.month == 2 && r.day > 28 && !IS_L_Y(r.year)) //Februar normales Jahr { cout << endl; cerr << "Ungueltige Tagesangabe " "(Dieser Monat hat nur 28 Tage!)" << endl; return false; } return true; } } unsigned long Date::get_days(Date &r) //Funktion zur Umrechnung des Datums in Tage { //seit 1 A.D. static unsigned int d_month; static unsigned long d; static unsigned short months[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30}; d = 365 * (r.year -1); //Tage bis zum Jahresanfang d += L_Y(r.year); //Addition der 'Schalttage' for(unsigned int i = 1; i < r.month; i++) //Addition der Tage aus den abgeschlossenen { //Monaten im laufenden Jahr d_month += months[i-1]; } d += d_month; d += r.day; //Addition der Tage im laufenden Monat if(IS_L_Y(r.year) && r.month > 2) { d++; } return d; }Der Fehler sitzt laut Compiler in Zeile 40 der date.h.
Danke im Vorraus für jede Hilfe.
-
Wenn man in C++ Funktionen aufruft, muss man legiglich den Namen der Variablen angeben, nicht den Typ.
Sprich, lass Date& aus Zeile 40 weg.
Mir ist aber die Funktionsweise deiner Date-Klasse nicht ganz klar. Wieso musst Du isDate(...) nochmal ein Date übergeben? Das, was du übergibst, ist doch die aufgerufene Instanz, diese ist in der Funktion also bereits bekannt.
Außerdem ist es besser, gar nicht erst zuzulassen, dass Date-Objekte mit fehlerhafter Semantik bestehen. Besser direkt bei der Eingabe prüfen. Und wenn Du ein Datum auf Validität testen möchtest, kannst Du dafür eine unabhängige Prüfmethode basteln, die dann aber natürlich die Bestandteile des Datums und kein Date-Objekt selbst erhalten sollte.
-
Nimm den den Datentyp im Aufruf raus und übergib nur &r (statt Date& r).
Ausserdem ist stdlib.h veraltet, du solltest stattdessen cstdlib verwenden.
Warum verwendest du Makros statt Funktionen? Und das label/goto Konstrukt ist auch nicht schön. Ausserdem trennt man üblicherweise Definition und Implementation voneinander, von wenigen Ausnahmen mal abgesehen.
-
Muss aber nur r statt &r sein, die Funktion erwartet ja auch eine Referenz.
-
Eisflamme schrieb:
Wenn man in C++ Funktionen aufruft, muss man legiglich den Namen der Variablen angeben, nicht den Typ.
Sprich, lass Date& aus Zeile 40 weg.
Schon versucht, der Fehler bleibt leider bestehen.
Eisflamme schrieb:
Mir ist aber die Funktionsweise deiner Date-Klasse nicht ganz klar. Wieso musst Du isDate(...) nochmal ein Date übergeben? Das, was du übergibst, ist doch die aufgerufene Instanz, diese ist in der Funktion also bereits bekannt.
Kann sein dass ich hier fehlerhaft programmiere, aber ich bin erst seit etwa einem Monat mit C++ vertraut und mir erschien es so richtig zu sein.
Eisflamme schrieb:
Außerdem ist es besser, gar nicht erst zuzulassen, dass Date-Objekte mit fehlerhafter Semantik bestehen. Besser direkt bei der Eingabe prüfen. Und wenn Du ein Datum auf Validität testen möchtest, kannst Du dafür eine unabhängige Prüfmethode basteln, die dann aber natürlich die Bestandteile des Datums und kein Date-Objekt selbst erhalten sollte.
Ich gebe zu der Code ist leider etwas unübersichtlich, das liegt aber daran, dass das Programm mehrfach in unterschiedlichen Versionen als Übungsaufgabe vorkam, zunächst als reines Anfängerprogramm nur mit Standardtypen zum Abspeichern der Werte, dann mit einer Date-Struktur und jetzt schließlich mit Date-Klasse. Da es sich nur um ein Übungsprogramm handelt, dass eigentlich niemals jemand anders ausser mir lesen müssen sollte, habe ich nicht besonders gut 'aufgeräumt'.
Die Eingabe von Daten erfolgt durch get_date, wobei get_date so oft durchlaufen wird, bis is_date das Datum als richtig absegnet, es wird also direkt bei der Eingabe geprüft.Eisflamme schrieb:
Muss aber nur r statt &r sein, die Funktion erwartet ja auch eine Referenz.
Hat das Problem gelöst, danke auf jeden Fall schonmal, wäre aber nett, wenn es ich noch eine knappe Erläuterung bekommen könnte, damit mir das nicht nochmal passiert.
-
Es heißt Rhythmus, nicht Rythmus oder Rytmus.
Wenn ich ein Programm sehe, das in der zweiten Ausgabe schon so einen Bock schießt, dann habe ich auch kein Vertrauen mehr in dessen weiteren Berechnungen.
-
Vicious Falcon schrieb:
Es heißt Rhythmus, nicht Rythmus oder Rytmus.
Wenn ich ein Programm sehe, das in der zweiten Ausgabe schon so einen Bock schießt, dann habe ich auch kein Vertrauen mehr in dessen weiteren Berechnungen.'...in dessen weitere Berechnungen.' Müsste es hier heissen.
Wenn eine Aussage so unqualifizierte Rechtschreibfehler aufweist, vertraue ich dem Autor irgendwie nicht mehr...
-
Eyeseeyou schrieb:
Vicious Falcon schrieb:
Es heißt Rhythmus, nicht Rythmus oder Rytmus.
Wenn ich ein Programm sehe, das in der zweiten Ausgabe schon so einen Bock schießt, dann habe ich auch kein Vertrauen mehr in dessen weiteren Berechnungen.'...in dessen weitere Berechnungen.' Müsste es hier heissen.
Wenn eine Aussage so unqualifizierte Rechtschreibfehler aufweist, vertraue ich dem Autor irgendwie nicht mehr...

-
Eyeseeyou schrieb:
Eisflamme schrieb:
Wenn man in C++ Funktionen aufruft, muss man legiglich den Namen der Variablen angeben, nicht den Typ.
Sprich, lass Date& aus Zeile 40 weg.
Schon versucht, der Fehler bleibt leider bestehen.
Das kann eigentlich nicht sein. Wenn du Eisflammes Rat befolgst, eliminierst du damit einen Compiler-Fehler. Somit musst du eine Fehlermeldung weniger sehen. Wenn dem nicht so ist, hast du irgendwas falsch gemacht. Also:
Statt
Date& rübergibst du nurr. Klappt?Abgesehen davon habe die anderen Recht, diese Referenz ist absolut unnötig und sollte lieber ganz weggelassen werden.
-
_matze schrieb:
Statt
Date& rübergibst du nurr. Klappt?Jo klappt, hatte mich zunächst verlesen und nur
Dateweggelassen, was noch nicht ausgereicht hat, jetzt ist wie verlangt nur noch einrin der Übergabe und schon läufts.
Nur ist mir wie gesagt noch nicht endgültig klar, was an der Stelle nun falsch war
-
Eyeseeyou schrieb:
_matze schrieb:
Statt
Date& rübergibst du nurr. Klappt?Jo klappt, hatte mich zunächst verlesen und nur
Dateweggelassen, was noch nicht ausgereicht hat, jetzt ist wie verlangt nur noch einrin der Übergabe und schon läufts.
Nur ist mir wie gesagt noch nicht endgültig klar, was an der Stelle nun falsch war
Ganz einfach: du musst bei der Übergabe von Variablen an eine Funktion/Methode nur den Bezeichner der Variable angeben, nicht noch zusätzlich den Typ (der Typ ist in dem Fall Date&, also eine Referenz vom Typ Date). Anders ist es bei der Deklaration/Definition der Funktion, hier musst du natürlich auch den Typ angeben (bei der Deklaration reicht sogar der Typ). Beispiel:
//Deklaration (Bekanntmachung) der Funktion bzw. Funktionsprototyp void myFunc(int); //hier ist sogar nur der Typ nötig, ich mache es aber nie so und finde es lesbarer, auch hier den Variablenbezeichner zu notieren //Definition der Funktion void myFunc(int par1) { //hier müssen selbstverständlich Typ und Bezeichner notiert werden //mach irgendwas... } //Aufruf, irgendwo im Code int i=123; myFunc(i); //Aufruf hier nur mit dem Variablennamen, eine Typangabe ist nicht nötig und nicht erlaubt
-
Vicious Falcon schrieb:
Es heißt Rhythmus, nicht Rythmus oder Rytmus.
Wenn ich ein Programm sehe, das in der zweiten Ausgabe schon so einen Bock schießt, dann habe ich auch kein Vertrauen mehr in dessen weiteren Berechnungen.Das Programm berechnet Biorhythmen. Wer solchem Blödsinn Glauben schenkt, den schrecken auch Rechtschreibfehler in der Ausgabe nicht ab.
-
Danke _matze für die Erklärung

Und was der Buchautor sich für seine Übungsprogramme überlegt ist doch egal, und wenn er mich die DNS-Stränge meiner Nachfahren berechnen ließe, wäre es mir auch recht, also regt euch doch nicht alle über die Biorhythmen auf

-
Eyeseeyou:
Ich weiß ja nicht, wo du die Übung her hast. Tutorial, Buch? Ein Buch ist sehr empfehlenswert. Tutorials auch, wenn sie gut sind, aber ich kenne gerade keine.Jedenfalls solltest Du versuchen bei Klassen objektorientierter zu denken. Eine Instanz der Klasse Date ist ein Datum. Da kannst Du direkt logisch ein paar Dinge erschließen:
-> Methoden auf eine Instanz betreffen auch dieses Datum
-> Methoden auf eine Instanz, welche ein Datum zusätzlich als Argument haben, arbeiten mit zwei Daten (die aufgerufene Instanz sowie die übergebene Instanz)
-> Wenn dieses Date-Objekt ein Datum darstellt, dann sollte das natürlich auch konsistent sein, d.h. ein gültiges Datum sein; andernfalls stellt Date ja nicht wirklich ein Datumsobjekt dar sondern Käsekuchen
usw.Das hat nicht unbedingt mit aufgeräumt zu tun, das sind m.E. Logik/Verständnisfehler, darum besser ein gutes Tutorial oder Buch als das, was du gerade nutzt.