Informatiker Board (http://www.informatikerboard.de/board/index.php)
- Themengebiete (http://www.informatikerboard.de/board/board.php?boardid=1)
-- Praktische Informatik (http://www.informatikerboard.de/board/board.php?boardid=6)
--- C++ Sprache (http://www.informatikerboard.de/board/thread.php?threadid=3677)


Geschrieben von as_string am 15.08.2017 um 14:17:

 

Du hast die Datei "CCalenderEntry.h" genannt aber includierst die Datei "CCalendarEntry.h". Mal ist ein "e" im Calender und mal ein "a": Calendar. Ich denke, letzteres ist im Englischen richtig und außerdem ist es so in der Aufgabe auch. Also -> benenne die Header-Datei um!

Außerdem: Wenn Du deinen Fehler hast, dann sag doch bitte auch die Fehlermeldung und nicht nur: Er meldet Fehler!

Gruß
Marco



Geschrieben von Victor am 15.08.2017 um 17:14:

 

Irgendwas scheint mit meiner Ide net zu stimmen auch nach dem umbenennen geht der Fehler nicht weg .

Aber egal.
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
  

void bool set(const CJulianDate& date, const std::string& location,
			const std::string& description){
	if( toGregorianDate(int& year, short& month, short& day) < toGregorianDate(1582, 10, 15)){
		return false;
	}
	else if(toGregorianDate(int& year, short& month, short& day) >=toGregorianDate(1582, 10, 15))){
	m_date = date;
	m_location = location;
	m_description = description;
	return true;
}




Fehler :


Description Resource Path Location Type
No return, in function returning non-void CCalenderEntry.cpp /CJulianDate/CJulianDate line 38 Code Analysis Problem

Stimmt der code also die Idee so?



Geschrieben von as_string am 16.08.2017 um 00:15:

 

Ich glaube, so wird das wirklich nichts... Wie kommt das eigentlich zustande? Bist Du Schüler oder studierst Du? Wenn Du studierst, was genau und woher kommt die Aufgabe?

  1. Du schreibst "void bool set(...". Schon alleine hier sind mindestens zwei Fehler drin. Erstens was ist denn nun der Rückgabewert? Ist es void (also keiner)? Oder ist es bool? Beides gleichzeitig funktioniert ja wohl kaum, oder?
  2. set() soll ja eine Methode der Klasse CCalendarEntry sein. Da sie ja (wie üblich) außerhalb der Klassendefinition definiert wird, musst Du CCalendarEntry::set(...) schreiben!
  3. Dein Vergleich in der if-Anweisung ist doch wohl offensichtlicher Unsinn, auch wieder in mehrfacher Hinsicht: zuerst einmal gibt es die Funktion toGregorianDate() nicht in der Klasse CCalendarEntry, sondern in der Klasse CJulianDate. Aber woher soll der Kompiler wissen, dass Du die meinst? Außerdem wäre das eine Member-Methode von der Klasse, die nicht statisch ist, weshalb Du ja auch noch ein Objekt brauchst, wenn Du sie aufrufen willst. Du könntest sie so nur aufrufen, wenn Du innerhalb der Klasse CJulianDate wärst, hier bist Du jetzt aber in der Klasse CCalendarEntry.
  4. Den Rückgabewert von CJulianDate::toGregorianDate() gibt es nicht, sie ist als void definiert. Wie willst Du denn dann zwei (nicht vorhandene) Rückgabewerte in der if()-Anweisung mit einen Kleiner-Zeichen vergleichen?
  5. Was soll der Aufruf vom ersten toGregorianDate mit den ganzen Argumenten? Du hast doch hier überhaupt kein "year", "month" oder "day" definiert!
  6. warum willst Du überhaupt etwas zu einem Gregorianischen-Kalender-Datum wandeln? Du willst doch einen Datumsvergleich machen, welches früher und welches später ist. Die ganze Aufgabe geht doch jetzt gerade darum, dass Du einen solchen Vergleich am besten mit dem Julianischen Kalender und eben gerade nicht mit dem Gregorianischen!
  7. Die Klasse CJulianDate hat den Operator < doch schon überladen! Das bedeutet, dass Du zwei Objekte vom Typ CJulianDate direkt mit < vergleich kannst. Allerdings nicht mit > oder mit >= etc, weil diese gar nicht definiert sind in CJulianDate.
  8. Du brauchst kein "else if(...)" wenn Du nach dem if (was ein return macht und deshalb die Funktion verlässt) mit allem anderen weiter gehen willst. Wenn das if unwahr ist, wäre doch die else if(...) Bedingung so wie so schon true, was willst Du da also noch vergleichen (zumal der Vergleich ja so wie so Blödsinn ist mit dem "toGregorianDate()"...
  9. Du hast nach dem else if()... eine öffnende geschweifte Klammer, die aber nicht mehr geschlossen wird.

Ich weiß nicht, ob ich noch ein paar Probleme vergessen habe. Das alles kann doch nicht Dein Ernst sein? Es kann doch nicht sein, dass Du eine solche Aufgabe lösen musst, wenn Du offensichtlich von der Materie nicht den Hauch einer Ahnung hast. Wie kann denn so etwas zustande kommen???

Ich habe die Funktion so geschrieben:
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
bool CCalendarEntry::set(const CJulianDate& date, const std::string& location,
			const std::string& description) {
	if(date < CJulianDate(1582, 10, 15))
		return false;
	m_date = date;
	m_location = location;
	m_description = description;
	return true;
}


Gruß
Marco



Geschrieben von Victor am 21.08.2017 um 23:08:

 

Gut habe den Code jetzt soweit nachvollziehen können .

Die Aufgabe geht ein wenig weiter .

Soll ich den Konstruktor so implementieren ?

Header:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:

#ifndef CCALENDAR_H_
#define CCALENDAR_H_
#include <string>
#include<iostream>
using namespace std;

class CCalendar {
	
private:
	CCalendar::CCalendarEntry* m_entries = 0;
	unsigned int m_numberofEntries = 0;
public:
	CCalendar();
	 ~CCalendar();
	 CCalendar& operator+=(const CCalendarEntry& entry);
	 void print( const CJulianDate& from);
	 void print();
};

#endif /* CCALENDAR_H_ */




cpp

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:

#include "CCalendar.h"

CCalendar::CCalendar(int m_numberofEntries, CCalendarEntry* m_entries) {
	
	numberofEntries = m_numberofEntries;
	entries = m_entries;
	

}

CCalendar::~CCalendar() {
	// TODO Auto-generated destructor stub
}





Folgende Fehler werden angezeigt:

Description Resource Path Location Type
Symbol 'numberofEntries' could not be resolved CCalendar.cpp /CCalendar line 12 Semantic Error
make: *** [CCalendar] Fehler 1 CCalendar C/C++ Problem
Type 'CCalendarEntry' could not be resolved CCalendar.cpp /CCalendar line 10 Semantic Error
die Regel für Ziel „CCalendar“ scheiterte makefile /CCalendar/Debug line 44 C/C++ Problem
Nicht definierter Verweis auf `main' CCalendar C/C++ Problem
Member declaration not found CCalendar.cpp /CCalendar line 10 Semantic Error
Type 'CCalendar::CCalendarEntry' could not be resolved CCalendar.h /CCalendar line 17 Semantic Error
Type 'CCalendarEntry' could not be resolved CCalendar.h /CCalendar line 22 Semantic Error
Symbol 'std' could not be resolved CCalendar.h /CCalendar line 12 Semantic Error
Symbol 'entries' could not be resolved CCalendar.cpp /CCalendar line 13 Semantic Error
Type 'CJulianDate' could not be resolved CCalendar.h /CCalendar line 23 Semantic Error

Ich habe in dem Ordner die Dateien von CjulianDate nicht im selben Ordner ,daher werden paar Fehler angezeigt ,aber warum die anderen ?



Geschrieben von as_string am 22.08.2017 um 07:37:

 

Hallo!

Auf den ersten Blick (ich komme erst später dazu, das auch auszuprobieren):
Du hast die Membervariablen "m_..." mit denen übergebenen vertauscht. Die Klasse hat ja die Variablen mit m_ am Anfang. Der Konstruktor bekommt die ohne m_ übergeben und Du weißt diese den Membervariablen zu und nicht umgekehrt, wie Du es gemacht hast.

Gruß
Marco



Geschrieben von Victor am 22.08.2017 um 10:40:

 

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:

#include "CCalendar.h"




CCalendar::CCalendar(int m_numberofEntries, CCalendarEntry* m_entries) {

       m_numberofEntries = numberofEntries;
	   m_entries = entries;


}

CCalendar::~CCalendar() {
	// TODO Auto-generated destructor stub
}





Es werden immer noch Fehler angezeigt?
Warum?



Geschrieben von Victor am 22.08.2017 um 13:49:

 

Wäre der destruktor so in Ordnung ?

Da muss ich ja den Speicher freigeben obwohl gar keiner erstellt wurde

Also habe ich im Konstruktor Speicher angelegt :


code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
#include "CCalendar.h"




CCalendar::CCalendar(int m_numberofEntries, CCalendarEntry* m_entries) {

       m_numberofEntries = numberofEntries;
       m_entries = entries;

m_entries = (CCalendarEntry*)malloc(m_numberofEntries *sizeof(CCalenderEntry));
}

CCalendar::~CCalendar() {
    // TODO Auto-generated destructor stub
    delete m_entries;
}



Passt es so?



Geschrieben von as_string am 22.08.2017 um 18:29:

 

Der Konstruktor soll laut Klassendiagramm gar keine Argumente übergeben bekommen. Der soll auch noch kein Array anlegen und schon gar nicht mit malloc (das ist C und ruft keine Konstruktoren auf), sondern mit new CCalendarEntry[] und delete [].
Du sollst aber im Konstruktor erstmal noch gar nichts machen laut Aufgabenstellung. Bei der c) steht doch explizit, dass so lange noch kein Element hinzugefügt wurde auch noch gar kein Speicher reserviert wurde.
Was Du also machen sollst:
Im Konstruktor gar nichts und der soll auch ohne Argumente sein.
Im Destruktor musst Du schauen, ob schon Speicher reserviert wurde, indem Du die Membervariable m_entries überprüfst, ob dieser Zeiger immer noch null ist.wenn ja, dann brauchst Du nix machen, wenn nicht mehr, dann hast Du schon Speicher belegt und gibst den mit delete [] frei.
Beim Operator += machst Du ein neues Array (mit new) allerdings mit der Größe um eins größer als m_numberOfEntries. Wenn es vorher schon ein Array gab, musst Du die Elemente umkopieren ins neue Array.
Allerdings kommt hier eine Besonderheit. Die Termine sollen ja ihrer chronologischen Reihenfolge nach gespeichert werden. Du musst also vor dem Einfügen eines Elementes aus dem alten Array immer überprüfen, ob das noch vor dem neuen Eintrag liegt. Sobald Du den ersten Eintrag des alten Arrays findest, das einem späteren Zeitpunkt entspricht als der neue Eintrag, musst Du zuerst den neuen Eintrag einfügen und dann erst den alten. Wenn Du am Ende mit dem alten Array durch bist, aber den neuen Eintrag noch nicht eingefügt hast, dann musst Du ihn am Ende einfügen.
Anschließend musst Du das alte Array löschen (wieder mit delete []). Dann zählst Du m_numberOfEntries eins hoch und weißt das neue Array der m_entries Variable zu.

Gruß
Marco



Geschrieben von Victor am 22.08.2017 um 23:42:

 

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
#include "CCalendar.h"




CCalendar::CCalendar() {

       
}

CCalendar::~CCalendar() {
	if( m_entries >=0 ){
	delete m_entries;
	}
}




Nur zum lernen ?
Wie würde ich denn Speicher genau ohne malloc anlegen ?
Wie sieht das genau aus?



Geschrieben von Victor am 23.08.2017 um 00:13:

 

Ich weiss nicht ob es quatsch ist ,aber ich habe es einfach mit einem bubblesort Algorithmus probiert ,aber glaube ich nicht ganz richtig leider:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:

/*
 * CCalendar.cpp
 *
 *  Created on: 21.08.2017
 *      Author: vaio
 */

#include "CCalendar.h"




CCalendar::CCalendar() {

       
}

CCalendar::~CCalendar() {
	if( m_entries >=0 ){
	delete m_entries;
	}
}

Calendar& operator+=(const CCalendarEntry& entry){
	
	
	CCalendarEntry** m_entries = new CCalendar* [m_numberofEntries+1];
	int temp;
	// Alle Elemente durchgehen (letztes ausgenommen)
	for(m_entries  = 0; m_entries  < m_numberofEntries-1; m_entries++)
	{
	    // Position des zurzeit kleinstes Elementes
	    unsigned int min_pos = m_entries;
	 
	    // unsortierten Teil des Feldes durchlaufen
	    // und nach kleinstem Element suchen
	    for( m_entries = m_numberofEntries+1; j < m_numberofEntries; j++)
	        if(feld[j] < feld[min_pos] )
	            min_pos = j;
	 
	    // Elemente vertauschen
	    // Das kleinste Element kommt an das Ende
	    // bereits sortierten Teils des Feldes
	    int temp = feld[numberofEntries];
	    feld[numberofEntries] = feld[min_pos];
	    feld[min_pos] = temp;
	}
}


Passt es ein wenig wenigstens ?



Geschrieben von as_string am 23.08.2017 um 08:04:

 

Ich kanns im Moment wieder nur überfliegen. Später dann mehr.
Da Du ein Array belegst, musst Du es mit "delete[] m_entries;" freigeben. Schau Dir dazu mal z. B. das hier an:
https://de.m.wikibooks.org/wiki/C%2B%2B-Programmierung/_Speicherverwaltung/_Array-new_und_Array-delete
Zum Sortieren hab ich Dir doch schon geschrieben, wie Du das machen sollst. Entweder liest Du nicht wirklich, was ich schreibe, oder Du verstehst den größten Teil nicht. Aber wenn das so wäre, dann frag doch bitte konkret nach!
Wenn Du schon so 10 Termine im Array hast und dann einen hinzufügen sollst, dann kannst Du ja davon ausgehen, dass die 10 alten Termine im alten Array schon sortiert sind. Es wurde ja jeder einzeln eingefügt und Du hast Dich immer darum gekümmert, dass nach dem Einfügen das Array wieder sortiert war.
Jetzt stell Dir vor Du hast eine Liste mit chronologisch schon richtig sortierten Terminen und bekommst einen neuen zum Einsortieren. Da musst Du doch jetzt kein Bubblesort oder sonst einen Sortieralgorithmus machen! Du gehst einfach über das alte, schon sortierte Array und fügst das neue Element an der korrekten Stelle ein. Schon hast Du wieder ein sortiertes Array, fertig. Ich habe Dir doch schon beschrieben, wie Du das machen sollst. Du kannst das dann machen, wenn Du so wie so schon dabei bist das Array umzukopieren.
Letztlich ist das eine kleine Art eines Mergesort, wenn Du unbedingt den Namen eines Sortieralgorithmus verwenden willst...

Gruß
Marco



Geschrieben von Victor am 23.08.2017 um 17:16:

 

Ich versuche es jetzt bisschen zu proggen aber verstehe nicht so richtig wie ich es machen soll Wink
Fällt mir so schwer
[cpp]
Calendar& operator+=(const CCalendarEntry& entry){

CCalendarEntry * oldEntries = m_entries; // das alte Array
CCalenderEntry * newEntries = new CCalendarEntry [m_numberofEntries + 1];
m_entries = newEntries; // m_entries auf das neue Array zeigen lassen
delete [] oldEntries; // das alte Array zerlegen


if(m_entries> CCalendarEntry [m_numberofEntries + 1]){


}



}[/cpp]



Ich will das wenn man dass m_entries grösser ist als das andere Array ,dass das m_entries dann davor steht ?

Aber wie soll ich das machen ?

Ich verpeile gerade total.

Mir fällt das proggen einfach zu schwer traurig



Geschrieben von as_string am 24.08.2017 um 11:42:

 

Hallo!

Naja, für einen Anfang ist das ja schonmal gar nicht sooo schlecht...
Allerdings brauchst Du eigentlich das oldEntries nicht. Lass doch einfach die Membervariable m_entries noch auf das alte Array weiter zeigen, bis Du das alte Array nicht mehr brauchst. Dann kannst Du es mit delete[] m_entries; löschen und die Variable m_entries auf das neue Array zeigen lassen.

Ich würde also so anfangen:
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
CCalendar& CCalendar::operator+=(const CCalendarEntry& entry) {
	CCalendarEntry *newEntries = new CCalendarEntry[m_numberOfEntries + 1]();

// ab hier dann das Umkopieren der alten Entries und richtige Einfügen des neuen Entry
// hier also noch ganz viel Code, der die eigentliche Arbeit erledigt

	if(m_entries != nullptr)
		delete[] m_entries;
	++m_numberOfEntries;
	m_entries = newEntries;
	return *this;
}

Der Mittelteil macht also erst noch die ganze Arbeit. Der Code hier macht quasi nur "die Verwaltung". Bis jetzt wäre das neue Array zwar schon im Speicher angelegt, aber noch nicht mit Werten gefüllt. Bis jetzt würden noch alle alten Kalendereinträge und auch der neue einfach verloren gehen.
Du musst jetzt mit einer Schleife über das alte Array laufen, immer ein Element vom alten in das neue Array kopieren, dabei aber schauen, ob der übergebene entry vor dem als nächstes zu kopierende entry aus dem alten Array liegt. Wenn das der Fall ist, muss einmal der neue entry eingefügt werden und dann erst weiter kopiert werden. Wenn der neue entry am Ende dieser Schleife noch nicht eingefügt wurde, dann muss er an das Ende des neuen Arrays kopiert werden.

Kannst Du mal so eine Schleife versuchen?

Gruß
Marco

PS: Hier noch meine Header-Datei. Ich hab sie allerdings nicht von Eclipse generieren lassen sondern von Hand geschrieben, kann also unterschiedlich aussehen.
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
#ifndef MYCODE_CCALENDAR_H_
#define MYCODE_CCALENDAR_H_

#include "CCalendarEntry.h"
#include "CJulianDate.h"

class CCalendar {
  private:
	CCalendarEntry *m_entries = nullptr;
	unsigned int m_numberOfEntries = 0;

  public:
	CCalendar();
	~CCalendar();

	CCalendar &operator+=(const CCalendarEntry& entry);
	void print() const;
	void print(const CJulianDate& from) const;
};

#endif /* MYCODE_CCALENDAR_H_ */



Geschrieben von Victor am 24.08.2017 um 11:59:

 

Wieso hast du jetzt nullptr erstellt ?

Kannst du mir das erklären ?



Geschrieben von as_string am 24.08.2017 um 13:59:

 

Naja, nullptr sollte man bei modernerem C++ verwenden. Es ist nur ein Schlüsselwort, ich habe da nichts "erstellt".
Du kannst natürlich auch die Zahl 0 oder NULL nehmen, aber beides lässt sich eben dann auch wirklich als Zahl verwenden, wohingegen bei nullptr der Compiler meckert, wenn es nicht als Zeiger verwendet wird. Das fängt dann schon ein paar potentielle Fehler zur Compile-Zeit ab.

Gruß
Marco


Forensoftware: Burning Board, entwickelt von WoltLab GmbH