Anfängerfrage Funktionen und Werteübergabe (Arrays) [SOLVED]
-
Ok mein Problem ist das ich erst wirklich seit ein paar Tagen mich mit C++ beschäftige und nachdem ich das mit den Pointern gemeistert habe nun versuche zu verstehen wie Klassen funktionieren. Im Grunde denke ich das ich das spiel verstanden habe aber trotzdem hänge ich nun bei meinem kleinen selbstgemachten Beispielprogramm an zwei Fehlermeldungen. Ok, hier das Programm ...
#include <iostream> #include <fstream> using namespace std; /* * file class and its functions */ class file { private: char Name[1024]; public: char IO; fstream Stream; file(char fName[]); ~file(); void SetName(char fName[]); char GetName(); }; file::file(char fName[]) { SetName(fName); } void file::SetName(char fName[]) { Name = fName; // Fehler 1 error C2440: '=': 'char []' kann nicht in 'char [1024]' konvertiert werden lernen9.cpp 31 } char file::GetName() { return Name; //Fehler 2 error C2440: 'return': 'char [1024]' kann nicht in 'char' konvertiert werden lernen9.cpp 36 } /* * Programm */ int main(int argc, char* argv[]) { file Inputfile("test.txt"); return 0; }
Ok ich weis ich mache bei der konvertierung der Datetypen einen Fehler aber nach 4 Büchern und endlosem suchem im Netz denke ich mir ich stell die Frage einfach mal den Cracks. Ich könnte auch struct verwenden aber mir gehts grade um das Verständniss der Klassen und natürlich auch der Datenübergabe.
Also was mache ich Falsch und wie müssten die Funktionen aussehen um das zu bewerstelligen was ich erreichen will.
Vielen Dank schonmal im voraus für eure Zeit und Eure Antworten.
Micha
-
Wenn du Zeichenketten übergeben willst, so benutze char* (Zeiger auf das erste Element des char-Arrays) oder string.
-
Mit Klassen selbst hat dein Problem erstmal nichts zu tun, sondern mit Arrays. Du kannst Arrays nicht einfach zuweisen (außer bei der Initialisierung). Du musst eine Schleife machen und jedes Element einzeln kopieren (oder memcpy oder std::copy verwenden). Und dann kannst du ein char-Array natürlich nicht einfach als char zurückgeben. Die Standardvariante wäre, dass die Funktion ein Array übergeben bekommt, in das du den Inhalt dann einfach hineinkopieren kannst.
-
Ok nun steh ich noch mehr vor böhmischen Dörfern. Fehler Nr 2 Hab ich inzwischen eliminiert aber natürlich bekommt ich nun wenn ich über cout ausgebe 1024 Zeichen datenmüll (aber das ist logisch weil ja noch nichts drinsteht oder besser der Müll drinsteht der bei der Initialisierung drin stand.
Lösung für Fehler 2: (equivalente Anpassung des Prototyps in der Klasse)
char* file::GetName() { return Name; }
Ok wenn ich das also richtig verstanden habe bau ich mir ne schleife in der ich fname in Name kopiere?
Mags String nun noch nicht anrühren solange es bei mir noch an den Basics hapert.
-
Ja, das mit dem Kopieren hast du richtig verstanden.
Du musst allerdings aufpassen, durch deine GetName()-Funktion gibst du dem Klassenbenutzer die Möglichkeit direkt auf deine private-Variable zuzugreifen. Kopierst du den Inhalt hingegen in einen vom Benutzer bereitgestellten Speicher, so bleiben deine Daten weiterhin gekapselt.
-
Ok, danke nun hab ichs glaube ich kapiert, hier mal mein Programm wie es aussehen sollte.
#include <iostream> #include <fstream> using namespace std; /* * file class and its functions */ class file { private: char Name[1024]; public: char IO; fstream Stream; file(char fName[]); ~file(){} void SetName(char fName[]); char* GetName(); }; file::file(char fName[]) { SetName(fName); } void file::SetName(char fName[]) { int a = 0; while(fName[a] != '\0') { Name[a] = fName[a]; a++; } Name[a] = '\0'; } char* file::GetName() { return Name; } /* * Programm */ int main(int argc, char* argv[]) { file Inputfile("test.txt"); cout << Inputfile.GetName() << endl; cin.get(); return 0; }
Und ja ich weis darum das ich dem Nutzer im Grunde Zugriff auf die private gebe, hätte auch alles in public setzen können aber dann hätte ich zum ändern ja keine Funktionen gebraucht :).
Da gings mir halt eher ums verständniss, leider setzen viele Bücher und Tutorials es nur mit int Werten um und dann hängt man dann in der Praxis und mag Mit Zeichenketten arbeiten und steht wie ein Ochs vorm Berg.
Danke nochmal an alle die hier gepostet haben!
Problem solved!
-
Zeichenketten übergibt man üblicherweise als char const*.
-
Videonauth schrieb:
[...] ich erst wirklich seit ein paar Tagen mich mit C++ beschäftige [...]
Ok ich weis ich mache bei der konvertierung der Datetypen einen Fehler aber nach 4 Büchern und endlosem suchem im Netz denke ich mir ich stell die Frage einfach mal den Cracks.Welche 4 Bücher? Und was heißst das überhaupt? Dass Du die 4 Bücher durchgelesen hast?
Videonauth schrieb:
[...] Also was mache ich Falsch [...]
Du hast nicht das richtige Buch in den Händen. Das mit den rohen Arrays gewöhnst Du Dir mal ganz schnell ab. Als Ersatz haben wir std::array, std::vector und std::string. Zeichenkettenübergabe an eine Funktion am besten
void so1(char const* dings); void so2(std::string const& bums); void so3(std::string temp);
(haben alle Vor- und Nachteile)
Zeichenkettenrückgabe per std::string.
-
krümelkacker schrieb:
Welche 4 Bücher? Und was heißst das überhaupt? Dass Du die 4 Bücher durchgelesen hast?
Bücher:
Helmut Erlenkötter - C++, Objektorientierte programmieren von Anfang an.
Rowolt Verlag - ISBN 978-3-499-60077-7Dirk Louis - C++ Programmieren mit einfachen Beispielen
M&T Verlag - ISBN 978-3-8272-4483-3André Wilms - C++ Programmierung
Addison-Wesley Verlag - ISBN 3-8273-1627-8Jesse Liberty - Jetzt Lerne ich C++
M&T Verlag - ISBN 3-8272-5663-1Und ja, gelesen, teilgelesen, nach Informationen durchsucht.
krümelkacker schrieb:
Du hast nicht das richtige Buch in den Händen.
Ja Das mag sein sind alle sehr unübersichtlich und für einen wirklichen Einsteiger zudem auch sehr verwirrend wenn man versucht autodidaktisch an das Ganze heranzugehen.
krümelkacker schrieb:
Das mit den rohen Arrays gewöhnst Du Dir mal ganz schnell ab. Als Ersatz haben wir std::array, std::vector und std::string. Zeichenkettenübergabe an eine Funktion am besten
void so1(char const* dings); void so2(std::string const& bums); void so3(std::string temp);
(haben alle Vor- und Nachteile)
Zeichenkettenrückgabe per std::string.
Ok das es die String Funktionen in der stdlib gibt weis ich nun, aber wie soll ich den Grundsatz verstehen wenn ich nicht erstmal mit grade dem anfange was den ganzen Funktionen zu Grunde liegt?
I sage ja nicht das mein Programm Eleganz hat, es funktioniert und hat mir veranschaulicht welche Fehler ich in dem Prozess gemacht habe.
Gruss Micha
-
Videonauth schrieb:
[...] aber wie soll ich den Grundsatz verstehen wenn ich nicht erstmal mit grade dem anfange was den ganzen Funktionen zu Grunde liegt?
Das klingt so, als glaubtest Du, man müsse beim C++ lernen "von unten" anfangen. Das stimmt natürlich nicht. Wenn Du Python lernst, guckst Du Dir ja auch nicht an, wie im Python-Interpreter Listen und Dictionaries implementiert sind. Du kannst beim C++ lernen auch erst mit den high-level Bausteinen anfangen (vector, string, etc) und später lernen, wie man solche Bausteine in "reinem C++" erzeugt.
-
krümelkacker schrieb:
void so1(char const* dings); void so2(std::string const& bums); void so3(std::string temp);
(haben alle Vor- und Nachteile)
Zeichenkettenrückgabe per std::string.
Warum widerrufst du deine Empfehlung mit diesem ewigen, diplomatischen "hat Vor- und Nachteile"? Als würde ausgerechnet ein Anfänger diese "Vor- und Nachteile" kennen. Die scheinst ja nicht einmal du zu kennen, sonst hättest du sie nennen können.
Ich drösel das mal kurz auf:Annahme: Die Funktion soll eine Kopie einer Zeichenkette wegspeichern.
void so1(char const* dings);
Vorteile: -
Nachteile:
- Null-terminiert (kennt seine Länge nicht in O(1) = Informationsverlust)
- kann Nullzeiger sein
- hat kein Iterator-Debugging
- um die Zeichenkette dann zu speichern, braucht man ohnehin etwas wiestring
void so2(std::string const& bums);
Vorteile:
- Kennt seine Länge
- hat keinen Nullzustand
- Iteratoren sind in den meisten Implementationen etwas sicherer als nackte Zeiger
- Ausnahmesicherheit vs. C-Gefrickel
Nachteile:
- erzwingt hier eine unnötige Kopievoid so3(std::string temp);
Vorteile:
(wie vorherige)
- Macht genau so viele Kopien wie nötig
Nachteile: -
-
TyRoXx schrieb:
void so2(std::string const& bums);
- erzwingt hier eine unnötige Kopie
Wieso sollte bei einer Übergabe per Referenz eine Kopie erstellt werden?
TyRoXx schrieb:
void so2(std::string temp);
- Macht genau so viele Kopien wie nötig
Und wie meinst du das? Da wird doch genau eine Kopie erstellt, oder nicht?
-
Ein Beispiel:
struct Box { void a(const std::string &value) { m_value = value; } void b(std::string value) { m_value = std::move(value); //vermutlich ist nicht einmal move() hier nötig, weil value lokal ist und sonst nicht benutzt wird } private: std::string m_value; }; int main() { Box x; //wird genau gleich benutzt, Variante a macht zwei Speicheranforderungen //und b nur eine x.a("hallo"); x.b("hallo"); }
-
Hoppla. Hab übersehen das direkt eine Zeichenkette und kein std::string übergeben wird.
Ja, dann ist das ja logisch