Einen Array von C++ Objekten mit Argumenten erstellen
-
@Cheerful Coder: Aufruf von was? Was für ein Prototyp?
Sone schrieb:
2. Wir wissen nicht, von welchem Typ
s1ist. (Es ist aber bestimmt einfach eine Instanz vonString, oder?)Müssen wir auch nicht. Mit String meint er bestimmt std::string (schlampige Schreibweise = vorprogrammierte Fehler).
Sone schrieb:
3. String kann jeder Typ sein, der sich mit einem Zeichenketten-Literal initialisieren lässt - oder eben mit dem Typ von
s1(wenns1tatsächlich vom Typ String ist, dann muss der Typ einen Kopierkonstruktor haben).
Aber dazu siehe Punkt 2.Klassen wird er noch nicht kennen, sonst würde er sich nicht mit solchen Fragen rumquälen.
-
Sone schrieb:
1. Das ist kein Aufruf, sondern eine Definition und Initialisierung eines Arrays von
String-Objekten.1. Siehe Titel des Threats, damit weiß ich dann wohl, dass es eine Initialisierung ist...
2. Wir wissen nicht, von welchem Typ
s1ist. (Es ist aber bestimmt einfach eine Instanz vonString, oder?)2. Ja, es ist eine Instanz von String, tut mir leid, dass ich das nicht erwähnt habe
3. String kann jeder Typ sein, der sich mit einem Zeichenketten-Literal initialisieren lässt - oder eben mit dem Typ von
s1(wenns1tatsächlich vom Typ String ist, dann muss der Typ einen Kopierkonstruktor haben).
Aber dazu siehe Punkt 2.4.
Darüber, wie die Definition von Stringaussieht, lässt sich so gut wie keine Angabe machen.Allerdings denke ich, trollolol's Variante könnte da tatsächlich drinstehen.
3. Für mich ist trollolol's Variante leider nicht wirklich ersichtlich, da ich
mich mit dieser Form noch nicht auseinandergesetzt habe, bin noch Anfänger in C++
Ich schicke einfach mal den ganzen Code, vielleicht ist es dann ersichtlicher was ich möchte.Ich komme bei dem Punkt der Initialisierung von String rgb[3] = { String(s1), String("green"), String("blue")}; in Main nicht weiter. Den Rest habe ich erstmal auskommentiert.
Wo ich schonmal dabei bin den ganzen Code zu posten...
Bei der Eingabe scheint er irgendwie ein Memory Problem zu haben, sobald ich mehr oder weniger als 2 Zeichen verwende? Könnt ihr mir dazu
vielleicht auch was sagen?Header.h #ifndef HEADER_H_INCLUDED #define HEADER_H_INCLUDED #include<iostream> class String { private: char *sentence; static const int STRINGMAX = 30; int count; public: String(); ~String(); String(const char *); String(const String &); String & Stringup(); int has(char); String & operator=(const String &); String & operator>(const String &); String & operator<(const String &); String & operator + (const String &); friend String & operator + (const char *, String &); friend std::ostream & operator<<(std::ostream &, const String &); friend std::istream & operator>>(std::istream & is, String & st); }; #endif // HEADER_H_INCLUDEDSource.cpp #include "header.h" #include <iostream> #include <cstring> String::String() { sentence = new char[1]; sentence = NULL; count = 0; } String::~String() { delete [] sentence; } String::String(const char *str) { sentence = new char [String::STRINGMAX]; strcpy(sentence, str); } std::ostream & operator << (std::ostream & os, const String & s) { os << s.sentence; return os; } std::istream & operator >> (std::istream & is, String & s) { char temp[String::STRINGMAX]; is.get(temp, String::STRINGMAX); if (is) s = temp; while (is && is.get() != '\n') continue; return is; } String & String::operator = (const String & s) { if (this == &s) // object assigned to itself return *this; // all done delete [] sentence; sentence = new char [String::STRINGMAX]; strcpy(sentence, s.sentence); return *this; } //s2 = "My name is " + s3; // overloaded =, + operators String & operator + (const char *s, String & str) { char *buffer; int buffercount = strlen(s); int sentencecount = strlen(str.sentence); buffer = new char [buffercount + sentencecount + 1]; strcpy(buffer, s); strcat(buffer, str.sentence); strcpy(str.sentence, buffer); delete [] buffer; return str; } String & String::operator + (const String &str) { strcat (sentence, str.sentence); return *this; } String & String::Stringup(void) { char *buffer; buffer = &sentence[0]; count = strlen(sentence); for (int x = 0; x < count; x++) { *sentence = toupper(*sentence); sentence++; } sentence = buffer; return *this; } int String::has(char letter) { char *buffer; buffer = &sentence[0]; while (*sentence) { if (*sentence == letter) count++; sentence++; } sentence = buffer; return count; }Main.cpp #include <iostream> #include "header.h" using namespace std; int main() { String s1(" and I am a C++ student."); String s2 = "Please enter your name: "; String s3; cout << s2; // overloaded << operator cin >> s3; // overloaded >> operator s2 = "My name is " + s3; // overloaded =, + operators cout << s2 << ".\n"; s2 = s2 + s1; s2.Stringup(); // converts string to uppercase cout << "The string\n" << s2 << "\ncontains " << s2.has('A') << " 'A' characters in it.\n"; s1 = "red"; // String(const char *), // then String & operator=(const String&) String rgb[3] = { String(s1), String("green"), String("blue")}; /* cout << "Enter the name of a primary color for mixing light: "; String ans; bool success = false; while (cin >> ans) { ans.stringlow(); // converts string to lowercase for (int i = 0; i < 3; i++) { if (ans == rgb[i]) // overloaded == operator { cout << "That’s right!\n"; success = true; break; } } if (success) break; else cout << "Try again!\n"; } cout << "Bye\n"; */ return 0; }
-
Ach, jetzt verstehe ich was er will! Er will nur die Deklaration des Arrays!

Der "Prototyp", also die Deklaration, sähe so aus:
extern String rgb[3]; //Zu diesem "Zeitpunkt" muss String lediglich deklariert sein
-
ICh lag wohl doch falsch, aber das hat einen Grund
:Cheerful Coder schrieb:
Ich komme bei dem Punkt der Initialisierung von String rgb[3] = { String(s1), String("green"), String("blue")}; in Main nicht weiter.
Das ist überhaupt nicht was du geschrieben hast.
-
Du benötigst einen Copy-Konstruktor. Wie ich sehe, hast du ihn im Header deklariert, aber in der .cpp hast du ihn nicht implementiert.
Und beim deinem Default-Konstruktor entsteht wahrscheinlich dein Memory Problem. So ist es besser:
String::String() { sentence = NULL; count = 0; }
-
Ramanujan schrieb:
So ist es besser:
String::String() { sentence = NULL; count = 0; }Wieso keine Initialisierungsliste?
-
Vielen Dank für die Hilfe!
Habs jetzt soweit fast fertig.
Er gibt nur noch nen Fehler
bei meinem Destructor, wüsste gerne warum er das tut
Wenn ich den Destructor weglasse, dann beendet er das Programm ganz normal.Hier ist mein Code:
header.h #ifndef HEADER_H_INCLUDED #define HEADER_H_INCLUDED #include<iostream> class String { private: char *sentence; int count; static const int STRINGMAX = 30; public: String(); ~String(); String(const char *); String(const String &); String & Stringup(); String & Stringlow(); int has(char); bool operator == (const String &) const; String & operator=(const String &); String & operator + (const String &); friend String & operator + (const char *, String &); friend std::ostream & operator<<(std::ostream &, const String &); friend std::istream & operator>>(std::istream & is, String & st); }; #endif // HEADER_H_INCLUDEDSource.cpp #include "header.h" #include <iostream> #include <cstring> String::String() { sentence = NULL; count = 0; } String::~String() { delete [] sentence; } String::String(const String & c) { count = c.count; sentence = new char [count + 1]; std::strcpy(sentence, c.sentence); } String::String(const char *str) { sentence = new char [String::STRINGMAX]; strcpy(sentence, str); } std::ostream & operator << (std::ostream & os, const String & s) { os << s.sentence; return os; } std::istream & operator >> (std::istream & is, String & s) { char temp[String::STRINGMAX]; is.get(temp, String::STRINGMAX); if (is) s = temp; while (is && is.get() != '\n') continue; return is; } String & String::operator = (const String & s) { if (this == &s) // object assigned to itself return *this; // all done delete [] sentence; sentence = new char [String::STRINGMAX]; strcpy(sentence, s.sentence); return *this; } //s2 = "My name is " + s3; // overloaded =, + operators String & operator + (const char *s, String & str) { char *buffer; int buffercount = strlen(s); int sentencecount = strlen(str.sentence); buffer = new char [buffercount + sentencecount + 1]; strcpy(buffer, s); strcat(buffer, str.sentence); strcpy(str.sentence, buffer); delete [] buffer; return str; } String & String::operator + (const String &str) { strcat (sentence, str.sentence); return *this; } String & String::Stringup(void) { char *buffer; buffer = &sentence[0]; count = strlen(sentence); for (int x = 0; x < count; x++) { *sentence = toupper(*sentence); sentence++; } sentence = buffer; count = 0; return *this; } String & String::Stringlow(void) { char *buffer; buffer = &sentence[0]; count = strlen(sentence); for (int x = 0; x < count; x++) { *sentence = tolower(*sentence); sentence++; } sentence = buffer; count = 0; return *this; } int String::has(char letter) { char *buffer; buffer = &sentence[0]; while (*sentence) { if (*sentence == letter) count++; sentence++; } sentence = buffer; return count; } bool String::operator == (const String &str) const { return (std::strcmp(sentence, str.sentence) == 0); }Main.cpp #include <iostream> #include "header.h" using namespace std; int main() { String s1(" and I am a C++ student."); String s2 = "Please enter your name: "; String s3; cout << s2; // overloaded << operator cin >> s3; // overloaded >> operator s2 = "My name is " + s3; // overloaded =, + operators cout << s2 << ".\n"; s2 = s2 + s1; s2.Stringup(); // converts string to uppercase cout << "The string\n" << s2 << "\ncontains " << s2.has('A') << " 'A' characters in it.\n"; s1 = "red"; // String(const char *), // then String & operator=(const String&) String rgb[3] = { String(s1), String("green"), String("blue")}; cout << "Enter the name of a primary color for mixing light: "; String ans; bool success = false; while (cin >> ans) { ans.Stringlow(); // converts string to lowercase for (int i = 0; i < 3; i++) { if (ans == rgb[i]) // overloaded == operator { cout << "That’s right!\n"; success = true; break; } } if (success) break; else cout << "Try again!\n"; } cout << "Bye\n"; return 0; }
-
Wozu brauchst du STRINGMAX? Wie lang darf dein String damit jemals werden? Hält dein Programm sich datan?
-
Cheerful Coder schrieb:
Vielen Dank für die Hilfe!
Habs jetzt soweit fast fertig.
Er gibt nur noch nen FehlerBeim Überfliegen fallen mir in fast jeder Funktion Fehler auf (Default-konstruktor und Destruktor sind die Einzigen ohne Fehler - wobei dein Defaultkonstuktor ggf. trotzdem überarbeitet werden sollte). C-String-Funktionen reagieren in der Regel allergisch auf Nullpointer. Wozu ist eigentlich count gut?
-
manni66 schrieb:
Wozu brauchst du STRINGMAX? Wie lang darf dein String damit jemals werden? Hält dein Programm sich datan?
Ich hab es so übernommen aus dem Buch ... dachte das das so möglich wäre,
wenn ich es als statisch in der Klasse deklariere...ist das falsch?
camper schrieb:
Beim Überfliegen fallen mir in fast jeder Funktion Fehler auf (Default-konstruktor und Destruktor sind die Einzigen ohne Fehler - wobei dein Defaultkonstuktor ggf. trotzdem überarbeitet werden sollte). C-String-Funktionen reagieren in der Regel allergisch auf Nullpointer. Wozu ist eigentlich count gut?
Count soll abzählen wieviele Buchstaben in stringup bzw. stringlow groß- bzw. kleingeschrieben werden sollen, aber vermutlich kann ich auch sowas nehmen wie
while (*sentence)richtig?

Könnteste mir vielleicht sagen, was meine Fehler sind?
Reicht auch
wenns die gröbsten Fehler sind, das wäre sehr hilfreich!
-
Es ist möglich mit einem Nullzeiger einen leeren String darzustellen. Das ist allerdings inkompatibel mit den meisten FUnktionen der Standardbibliothek, konsequenterweise müsste bei jedem Funktionsaufruf (strlen,strcpy was auch immer) vorher dieser Fall geprüft werden.
Damit sind nahezu alle Funktionen falsch.Praktisch ist die Variante mit Nullzeiger allerdings nicht.
Eine Möglichkeit besteht darin, den leeren String nicht als Sonderfall zu betrachten - dann verzichtet man z.B. gleich auf einen eigenständigen Defaultkonstruktor und verpasst z.B. dem const char*-Konstruktor ein Defaultargument.String(const char* s="") { std::size_t len = strlen(s); sentence = new char[len + 1]; std::memcpy( sentence, s, len + 1 ); }Eine andere Möglichkeit besteht darin, dafür ein statisches Array zu verwenden:
class String { private: static char empty_string[1]; ... }; char String::empty_string[1] = { '\0' }; String::String() { sentence = empty_string; } String::~String() { if ( sentence != empty_string ) delete [] sentence; }Von der Beschränkung auf STRINGMAX Zeichen ist nichts zu halten. Man könnte dafür ja gleich das Array als Klassenmember halten und auf dynamische Speicherverwaltung verzichten. In jedem Fall ist bei einem der Länge nach begrenzten String sicherzustellen, dass diese Grenze nicht überschritten wird. Das ist z.B. in String::String(const char *str) nicht der Fall.
Der operator+ ist seltsam; normalerweise sollte dieser nicht seine Argumente verändern. Zudem besteht dann auch ein Aliasproblem:str s = "foo"; s+s;dürfte nicht funktionieren. Der Test auf Länge fehlt sowieso. Der andere operator+ funktioniert auch nicht.
-
Ich hab es so übernommen aus dem Buch ... dachte das das so möglich wäre,
wenn ich es als statisch in der Klasse deklariere...ist das falsch?Nicht direkt, STRINGMAX darf halt nur so groß werden, wie der Index es werden darf.
Eine Möglichkeit besteht darin, den leeren String nicht als Sonderfall zu betrachten - dann verzichtet man z.B. gleich auf einen eigenständigen Defaultkonstruktor und verpasst z.B. dem const char*-Konstruktor ein Defaultargument.
Ein leerer String hat die Länge 1 und besteht nur aus
'\0', das sollte auch die C-Funktionen nicht verstören.Von der Beschränkung auf STRINGMAX Zeichen ist nichts zu halten. Man könnte dafür ja gleich das Array als Klassenmember halten und auf dynamische Speicherverwaltung verzichten.
Nicht direkt, STRINGMAX sollte die größtmögliche Zahl des Indexes vorgeben.
Warum reservierst du - immer, wenn du temporären Speicher reservierst nicht strlen() viele Elemente, anstatt STRINGMAX? Ist doch pure Speicherverschwendung.
Abgesehen davon kopiert strcpy den abschließenden '\0' Terminierer nicht mit, den musst du meines Wissens selbst anhängen.
Übrigens... Welches Buch liest du denn?
-
Der Tobi schrieb:
Ein leerer String hat die Länge 1 und besteht nur aus
'\0'Ein leerer String hat die Länge Null.
-
Sone schrieb:
Der Tobi schrieb:
Ein leerer String hat die Länge 1
Hast du nen Hirnschaden? ^^
Anscheinend hast du einen Hirnschaden, wenn du gleich drauf los musst.
-
[Rewind] schrieb:
Anscheinend hast du einen Hirnschaden, wenn du gleich drauf los musst.
Gut, das war sehr grob, tut mir Leid.
-
*facepalm*
-
camper schrieb:
*facepalm*
Ach, Scheiße! Ich hab's falsch verstanden. Natürlich hat camper Recht. Ich dachte er meint leere Strings (also einen Zeiger auf das Terminierungszeichen)... weil ich schon wieder zu schnell lese...

Klar, strlen o. ä. haben immer sowas stehen:while(*ptr)Nen' Null-Pointer zu dereferenzieren ist natürlich UB und führt zum crash.