Hallo momentan mach ich das so
void setname(const char *c = "")
{strcpy(name,c);}
...
char name[20];
oder so
void setNEWname (const char *c = "")
{newnamen = new char[strlen(c) + 1];
strcpy(newnamen,c);}
...
char *newnamen;
aber da bringt der Combiler immer ne Warnung
gibts da noch bessere Medtoden
> aber da bringt der Combiler immer ne Warnung
Schön, daß Du die für Dich behältst. Da Du auch nicht sagst, was Du
anstellen willst, kann nur die Glaskugel befragt werden.
a) es handelt sich offensichtlich um C++ - Code.
b) Im ersten "Beispiel" (ich bin jetzt mal gutmütig und nenne den Rotz
so) benutzt Du die Variable name, bevor Du sie deklariert hast.
c) Dasselbe stellst Du im zweiten "Beispiel" mit newnamen an.
Das ganze ist in einer Klasse und sieht dann zb so aus
class String
{
public:
void setNEWname (const char *c = "")
{newnamen = new char[strlen(c) + 1];
strcpy(newnamen,c);}
private:
char *newnamen;
};
String meinname;
meinname.setNEWname("Franz");
und da bringt er immer ne Warnung
strcpy': This function or variable may be unsafe
unter MS VC gibt es diese _s funktionen, die sollen save sein. Meist
spuckt er da ne Warning aus für z.B. sprintf.
Ist dein SrcString nicht am richtigen Ende mit '\0' terminiert (also
erst irgendwann durch zufall) oder zu lang schreibst du in Speicher, wo
dir dann das OS auf die Finger haut (oder sollte).
Daher "unsave".
Aber ein C-Programmierer sollte wissen, was er tut. Wenn nicht, lerne
Java :-)
VG,
/th.
Man beachte hier auch das richtige CamelCase.
Die Klassendefinitionen kommen in den Header, damit die in anderen
Modulen richtig #include-d werden können (sonst gehts schief).
Die Methoden kommen in das cpp file (#include "header.h" nicht
vergessen!)
VG,
/th.
Random ... schrieb:
> unter MS VC gibt es diese _s funktionen, die sollen save sein. Meist> ...> Daher "unsave".
To save or not to save, that's the question.
Aber das Ding heisst safe, wie der Compiler auch schon richtig schreibt.
Random ... schrieb:
> Aber ein C-Programmierer sollte wissen, was er tut. Wenn nicht, lerne> Java :-)
:-)
Es reicht völlig, wenn er C++ programmiert, wenn er einen C++ Compiler
benutzt. Aber auch das wurde schon angesprochen :-)
Man beachte hier auch das richtige CamelCase.
Die Klassendefinitionen kommen in den Header, damit die in anderen
Modulen richtig #include-d werden können (sonst gehts schief).
Die Methoden kommen in das cpp file (#include "header.h" nicht
vergessen!)
VG,
/th.
Severino R. schrieb:
> Random ... schrieb:>> unter MS VC gibt es diese _s funktionen, die sollen save sein. Meist>> ...>> Daher "unsave".>> To save or not to save, that's the question.>> Aber das Ding heisst safe, wie der Compiler auch schon richtig schreibt.
whoops :-)
Random ... schrieb:
> so gehts:
Brauch ich dir wahrscheinlich auch nicht sagen:
So einfach wirst du diese Warnung vom MS-Compiler nicht los.
Aber in der Warnung vom Compiler steht auch drinnen, wie man sie mit
einem #define abschalten kann :-)
"so gehts" war nicht auf die Warnung, sondern auf richtiges /
richtigeres C++ bezogen. Damits auch mit Modulen klappt, sonst hatter
gleich nach seiner Warning nen Error auf der Matte stehen :-)
> wie man sie mit> einem #define abschalten kann :-)megaLOL
Erinnert mich irgendwie an Lint. Will Lint nicht, will ich wohl, daher
schalten wir's ab :-)
VG,
/th.
Random ... schrieb:
> "so gehts" war nicht auf die Warnung, sondern auf richtiges /> richtigeres C++ bezogen.
Na ja.
Wenn wir danach gehen, dann hat auch deine letzte Version noch einigen
Nachholbedarf :-)
Das fängt beim Constructor, Copy Constructor, Operator=, Destruktor an
und hört beim wegfallen des Defaultarguments in der Funktionsdefinition
auf.
(Aber das soll der OP alleine herausfinden. Oder am besten gleich
richtiges C++ programmieren und std::string benutzen :-)
void setNEWname (const char *c = "")
um mal beim Thema zu bleiben unser Prof stellt in der Prüfung
zb diesen Rumpf (siehe oben) zur Verfügung und dann heists machmal
mit der std::string haben wir bei den Übungen nichts gemacht
deshalb denke ich nicht das das Überhaupt in der Prüfung drankommt
Kolos schrieb:
> void setNEWname (const char *c = "")>>> um mal beim Thema zu bleiben unser Prof stellt in der Prüfung>> zb diesen Rumpf (siehe oben) zur Verfügung und dann heists machmal
wenn du in deiner Funktion dann vor der Allokierung des neuen Speichers
den Speicher freigibst, auf den newname vorher zeigt, dann hinterlässt
dein Code auch keine Speicherlöcher :-)
Mehr kannst du mit dem bischen Kontext nicht tun und auch nicht
erwarten.
Die Warnung ist ein 'Feature' des Microsoft Compilers, von dem die MS
Leute denken, dass sie C-Code sicherer macht (was sie natürlich nicht
tut. Ihre sogenannten safe-Versionen können ein grundsätzliches Problem
der String-Verarbeitung in C nicht beheben. Ich kann immer noch meinen
Compiler anlügen und ihm sagen meine Targetarea sei größer als sie
tatsächlich ist)
> mit der std::string haben wir bei den Übungen nichts gemacht> deshalb denke ich nicht das das Überhaupt in der Prüfung drankommt
Das sollte einem eigentlich zu denken geben.
Hab da nochmal was im Skript enteckt was mir komisch vorkommt.
Daten Daten::operator=(const Daten &s)
{
if (this != &s) // alternat: if (pString != s.pString)
{ // nichts tun, falls identisch
delete [] newnamen;
newnamen = new char[strlen(s.newnamen) + 1];
strcpy(newnamen, s.newnamen);
}
return *this;
}
so stehts im Skript aber wäre es nicht besser wenn man das so schreibt
delete [] s.newnamen;
newnamen ist dann wohl eine Member Variable. Ob Du das Delete auf
s.newnamen oder auf this->newnamen etc. machst, ist egal.
Aber wenn Du von einem Prof sprichst uns ich mir das so anschaue, ist es
doch bedenklich was ihr da so gelehrt bekommt.
Sorry, der Zusatz musste sein.
Ich hab mir ein eigenes Programm geschrieben
und ich bekomm bei diesem delete [] newnamen;
ständig folgende Meldung
Unbehandelte Ausnahme bei 0x657431ea (msvcr90d.dll) in test.exe:
0xC0000005: Zugriffsverletzung beim Lesen an Position 0xccccccc0.
und ich denk mal das das am delete liegt
Karl heinz Buchegger schrieb:
>> mit der std::string haben wir bei den Übungen nichts gemacht>> deshalb denke ich nicht das das Überhaupt in der Prüfung drankommt> Das sollte einem eigentlich zu denken geben.
Dass man an einer Hochschule noch Grundlagen lernt, statt sich nur auf
Bibliotheken zu verlassen?
kannst latürnich nur deleten wenn der auch vorher auf valid speicher
steht.
Beim debuggen kannste das im MS VC debugger an 0xcccccccc für Vars oder
0xcdcdcdcd für pointer sehen, oder initialisierst deine Pointer mit 0
oder NULL und prüfst vor jedem access drauf (fp = fopen z.B. gibt eine 0
zurück wenns schiefgeht, die kann man abfangen)
VG,
/th.
Rene H. schrieb:
> Sorry, stimmt nicht. Das if ist ja != :-)> In dem Fall delete s.newnamen oder delete newnamen. Ist egal.
Wie kommst du drauf, dass das egal ist?
Du kannst doch nicht einfach dem übergebenen Argument seinen String
unter dem Hintern wegdeleten!
So wärs richtig (Jedes Zeichen beachten! Auch der Returntyp der FUnktion
ist wichtig!)
1
Daten&Daten::operator=(constDaten&s)
2
{
3
if(this!=&s)// alternat: if (pString != s.pString)
4
{// nichts tun, falls identisch
5
delete[]newnamen;
6
newnamen=newchar[strlen(s.newnamen)+1];
7
strcpy(newnamen,s.newnamen);
8
}
9
return*this;
10
}
Allerdings wäre die noch bessere Version die hier
1
DatenDaten::operator=(constDaten&s)
2
{
3
char*tmp=newchar[strlen(s.newnamen)+1];
4
strcpy(tmp,s.newnamen);
5
delete[]newnamen;
6
newnamen=tmp;
7
8
return*this;
9
}
Die ist dann auch noch Exception-safe.
(Ist ein op= korrekt geschrieben, dann braucht man keine Überprüfung auf
Self Assignment)
> Aber wenn Du von einem Prof sprichst uns ich mir das so anschaue,> ist es doch bedenklich was ihr da so gelehrt bekommt.
Wird wohl das übliche sein.
Die Profs die auf der Uni lehren, sollten selbst erst mal einen
vernünftigen C++ Kurs besuchen.
Peter Stegemann schrieb:
> Karl heinz Buchegger schrieb:>>>> mit der std::string haben wir bei den Übungen nichts gemacht>>> deshalb denke ich nicht das das Überhaupt in der Prüfung drankommt>> Das sollte einem eigentlich zu denken geben.>> Dass man an einer Hochschule noch Grundlagen lernt, statt sich nur auf> Bibliotheken zu verlassen?
Sorry. Aber das hat nichts mit Grundlagen mehr zu tun.
In C++ gibt es eine offizielle String Klasse die genauso vorhanden ist,
wie eine Dateibehandlung. Mit der sollte man erst mal anfangen, ehe man
sich selber auf das Niveau der eigenen String Allokierung begibt. Du
implementierst ja auch deine Dateizugriffe nicht Fetsplattenebene
selber.
Nur weil C keine vernünftigen Strings kennt, heisst das noch lange
nicht, dass man daher auch in C++ auf jeglichen Komfort verzichten
sollte. Vor allen Dingen dann nicht, wenn die entsprechenden C++ Klassen
aus dem Stand heraus funktionieren.
Wenn man genügend Erfahrung in der Programmierung hat, kann man immer
noch auf die Details einer eigenen Stringbehandlung eingehen und diese
implementieren. Aber zum lernen, wie man in C++ programmiert ist die
(halbherzige) Kentniss einer C-Stringverarbeitung genauso hilfreich, wie
das lernen von Japanisch wenn man Kisuaheli kann.
Man muss einfach nur akzeptieren, dass die Grundlagen in C++ andere sind
als in C.
Kolos schrieb:
> Ich hab mir ein eigenes Programm geschrieben>> und ich denk mal das das am delete liegt
Nein. Das liegt nicht daran.
Das liegt höchst wahrscheinlich daran, dass du newname im Konstruktor
keinen NULL Pointer verpasst hast.
Karl heinz Buchegger schrieb:
> Rene H. schrieb:>> Sorry, stimmt nicht. Das if ist ja != :-)>> In dem Fall delete s.newnamen oder delete newnamen. Ist egal.>> Wie kommst du drauf, dass das egal ist?>> Du kannst doch nicht einfach dem übergebenen Argument seinen String> unter dem Hintern wegdeleten!>
Ja, stimmt natürlich :-). Habe nicht so genau hingeguckt.
Karl heinz Buchegger schrieb:
> Peter Stegemann schrieb:>> Dass man an einer Hochschule noch Grundlagen lernt, statt sich nur auf>> Bibliotheken zu verlassen?> Sorry. Aber das hat nichts mit Grundlagen mehr zu tun.
Doch, sehr wohl. Denn hier geht's kaum um wirklich spezielles
String-Wissen, sondern um einfache Set- und Get-Methoden, mit ein
bisschen allokieren und kopieren. Da auf std::string zu verweisen ist
kontraproduktiv.
> In C++ gibt es eine offizielle String Klasse die genauso vorhanden ist,> wie eine Dateibehandlung. Mit der sollte man erst mal anfangen, ehe man> sich selber auf das Niveau der eigenen String Allokierung begibt.
Beides ist nicht immer vorhanden und auch oft nicht optimal. Gerade
Dateibehandlung ist in der STL einfach nur noch schraeg, voellig
unnoetig abstrahiert. Mit ordentlichen File- und Directory-Klassen waere
der C++-Welt mehr gedient gewesen.
> Du implementierst ja auch deine Dateizugriffe nicht Fetsplattenebene> selber.
Nicht alles was hinkt, ist ein Vergleich.
> Nur weil C keine vernünftigen Strings kennt, heisst das noch lange> nicht, dass man daher auch in C++ auf jeglichen Komfort verzichten> sollte.
Nur weil es fuer C++ std::string gibt, heisst das nicht, dass das
vernuenftige Strings sind.
> Vor allen Dingen dann nicht, wenn die entsprechenden C++ Klassen> aus dem Stand heraus funktionieren.
Das tun sie auch nicht immer. Aber das merkt man erst im harten
Praxisalltag, nicht im Elfenbeinturm.
> Wenn man genügend Erfahrung in der Programmierung hat, kann man immer> noch auf die Details einer eigenen Stringbehandlung eingehen und diese> implementieren.
Wo soll denn die Erfahrung herkommen, wenn schon die Stringverarbeitung
umschifft wird? Strings sind sehr praktisch, um die Tuecken von new,
delete, Resourcenverwaltung und Pointern zu lernen.
Quatsch ist, erst mal C++ in der Softvariante zu lehren, dem Schueler zu
vermitteln wie einfach es ist ein dickes Programm zu schreiben und ihm
dann zuzusehen, wie er mit dem Ding nicht mehr zurecht kommt.
> Aber zum lernen, wie man in C++ programmiert ist die> (halbherzige) Kentniss einer C-Stringverarbeitung genauso hilfreich, wie> das lernen von Japanisch wenn man Kisuaheli kann.
Voelliger Bloedsinn.
Peter Stegemann schrieb:
>> Doch, sehr wohl. Denn hier geht's kaum um wirklich spezielles> String-Wissen, sondern um einfache Set- und Get-Methoden, mit ein> bisschen allokieren und kopieren. Da auf std::string zu verweisen ist> kontraproduktiv.
Dann sollte man sich auch auf Setter und Getter konzentrieren und nicht
auf ds Verwalten von dynamischen Resourcen.
>> In C++ gibt es eine offizielle String Klasse die genauso vorhanden ist,>> wie eine Dateibehandlung. Mit der sollte man erst mal anfangen, ehe man>> sich selber auf das Niveau der eigenen String Allokierung begibt.>> Beides ist nicht immer vorhanden und auch oft nicht optimal.
Wenn wir in Mikrovontroller & Elektronik wären würde ich dir recht
geben. ABer wir sind hier in PC-Programmierung. Und da gibt es nun mal
in C++ eine String Klasse.
Und selbst wenn es diese nicht gibt, dann hat in einer Firma schon
jemand eine geschrieben.
> Gerade> Dateibehandlung ist in der STL einfach nur noch schraeg, voellig> unnoetig abstrahiert. Mit ordentlichen File- und Directory-Klassen waere> der C++-Welt mehr gedient gewesen.
Geb ich dir recht.
Trotzdem hält der Vergleich:
Wenn du in C an ein File rannwillst, implementierst du auch kein halbes
Dateisystem mit dynamischer Handle-Allokierung und Bufferung. Genauso
wie du ein fopen, fwrite, fread zur Verfügung hast, hast du in C++ ein
std::string zur Verfügung.
> Nur weil es fuer C++ std::string gibt, heisst das nicht, dass das> vernuenftige Strings sind.
Doch.
Die sind vernünftig. Zumindest in dem Sinne, dass sie funktionieren, was
man von grob geschätzt 70% aller 'Ich implementier mir meine C-Strings
in C++ selber'-Klassen nicht sagen kann.
> Das tun sie auch nicht immer. Aber das merkt man erst im harten> Praxisalltag, nicht im Elfenbeinturm.
Dann ist das ein Fehler in der jeweiligen STL. Den teilt man dem
Hersteller mit, der fixt den Bug und alle sind glücklich.
Und mal ehrlich: Ich hab zwar auch schon einige Probleme in der STL
gesehen, aber eine String Klasse hat noch immer funktioniert.
> Wo soll denn die Erfahrung herkommen, wenn schon die Stringverarbeitung> umschifft wird? Strings sind sehr praktisch, um die Tuecken von new,> delete, Resourcenverwaltung und Pointern zu lernen.
Ja.
Aber da geht es um das erlernen, wie man mit dynamischen Resourcen
umgeht. Die meisten lernen diesen ganzen Kram allerdings zu einem
Zeitpunkt an dem eigentlich 'Stringverarbeitung' ansteht. Und dazu
braucht es keine dynamische Allokierung im Eigenbau.
> Quatsch ist, erst mal C++ in der Softvariante zu lehren, dem Schueler zu> vermitteln wie einfach es ist ein dickes Programm zu schreiben
Sorry, Aber das seh ich ganz anders.
Denn das dicke Programm wird plötzlich ganz schlank, wenn er die Dinge
mit STL Mitteln angeht.
(Warst nicht du es, der in einem anderen Thread eine Filebearbeitung in
C dynamisch ausformuliert hat. Dort sieht man doch am allerbesten was
einem der Einsatz der C++ Klassen bringt. Eine Handvoll C++ Zeilen
kontra 2 Seiten C-Code. Was davon nist jetzt dicker und
fehleranfälliger)
> Voelliger Bloedsinn.
Tut mir leid.
Das ist meine Meinung: Völliger Blödsinn ist es, einen Anfänger in
C-Stringverarbeitung hineinzujagen, wenn er mit std::string seine Dinge
mehr als ausreichend geregelt bekommt.
@ Karl heinz Buchegger
für was verwendest du hier den Adressoperator das geht doch ohne auch
Daten Hierrr!!!!! operator=( const Daten & s )
{
char * tmp = new char[ strlen(s.name) + 1 ];
strcpy( tmp, s.name );
delete [] name;
name = tmp;
return *this;
}
@Peter
Nicht falsch verstehen. Ich propagier keineswegs, dass ein C++
Programmierer nicht mit dynamischen Resourcen umgehen können muss.
Keineswegs.
Ich bin nur dafür, dass dieses Thema zu geeigneter Zeit gemacht wird und
nicht wenn der Lernende mit hunderttausend andere Dingen überflutet
wird, die er erst einmal einordnen muss.
Tim schrieb:
> @ Karl heinz Buchegger>> für was verwendest du hier den Adressoperator das geht doch ohne auch
Wenn du haben willst, das das Objekt an welches du gerade zugewiesen
wurde beim return noch einmal kopiert wird, dann mach das ruhig! Stell
aber besser sicher, dass der Copy Construktor richtig funktioniert und
vor allen Dingen nicht durch Aufruf des Zuweisungsoperators definiert
wurde. Ansonsten gibts nämlich eine Endlosschleife :-)
Ist eine Kopie zuviel, aber was solls. Rechner sind ja schnell genug
heutzutage.
> Daten Hierrr!!!!! operator=( const Daten & s )
Dieser 'Adressoperator' ist eine Referenz!
in deinem Code brauchst du auch noch diesen Konstruktor
Daten(const char *c) : name( NULL )
{
char * tmp = new char[ strlen(c) + 1 ];
strcpy( tmp, c );
delete [] name;
name = tmp;
}
damit diese aufufe möglich sind
Daten name("Karl");
friend ostream &operator<<(ostream &os, const Complex &z)
{
return os << blablabla;
}
aber hier wird doch das & vor dem Operator benötigt benötigt
wieso ist das dann da so
Tim schrieb:
> friend ostream &operator<<(ostream &os, const Complex &z)> {> return os << blablabla;> }>> aber hier wird doch das & vor dem Operator benötigt benötigt> wieso ist das dann da so
An dieser Stelle kann es keinen Adressof-Operator geben.
Im Funktionskopf ist & immer das Kennzeichen einer Referenz.
os wird per Referenz übergeben
z wird per Referenz übergeben
die Funktion liefert eine Referenz
Einen Adressof-Operator kannst du immer nur im Funktionsrumpf haben oder
in Initialisierungen. Grob gesprochen: in Code der auch ausgeführt wird.
Ein Funktionskopf führt aber nichts aus. Er deklariert nur, wie die
Schnittstelle zum Aufrufer aussieht.
hab ich jetzt nicht verstanden! was ist da der Unterschied zwischen
friend ostream &operator<<(ostream &os, const Complex &z)
Daten operator=( const Daten & s )
Daten & operator=( const Daten & s )
Tim schrieb:
> hab ich jetzt nicht verstanden! was ist da der Unterschied zwischen>> Daten operator=( const Daten & s )
Hier wird ein Daten OBJEKT zurückgegeben.
Damit dies möglich ist, muss das Objekt aus der Funktion herauskopiert
werden. Je nach Objekt, kann es aber teuer sein ein Objekt zu kopieren.
> Daten & operator=( const Daten & s )
Hier wird eine REFERENZ auf ein Datenobjekt zurückgegeben.
Eine Referenz ist nicht das Objekt selber, sondern sie steht für das
Objekt. Damit man eine Referenz aus einer Funktion herauskopieren kann,
muss nur sichergestellt sein, dass das eigentliche Objekt nach dem
Funktionsaufruf noch existiert. Bei *this sollte das eigentlich ausser
Frage stehen :-)
Gibt man eine Referenz aus der Funktion heraus, muss das Objekt nicht
kopiert werden. Es muss nur nach dem Aufruf noch existieren.
Ich empfehle ein C++ Buch.
Tim schrieb:
> Bei Büchern dauert es zu lange bis man da die passende Antwort findet>
Klar. Wenn du erst zu lesen anfängst, wenn du auf ein Problem stößt.
Solche Bücher kann man auch im Vorfeld lesen. Sollte man sogar tun. Dann
weiß man auch, was es so alles gibt. Wie das alles zusmmenhängt und in
welchem Kapitel welches Thema behandelt wird. Und nein: Referenzen sind
alles andere als ein esoterisches Thema, welches im Vorbeigehen auf den
Fussnoten 2er Seiten abgehandelt wird.
> ich hab sogar 2 Bücher
Ach. Und? Beide schon ausgemalt?
(Sorry. Konnte nicht widerstehen)
wenn ich dir mein skript geb dann würdest du sehen das da sehr schnell
über
Referenzen hinweggegangen wurde dort sind einige beispiele drinnen
und das wars
Du weißt aber schon, daß es neben "Deinem Skript" auch andere Bücher
gibt? Und daß Du für Dein Studium/Deine Ausbildung/Deine Schule auch
Deinen Arsch notfalls in eine Bücherei bewegen solltest, um Dir
Grundlagenwissen anzueignen?