return Wert *char oder AnsiString
-
Gibt es dazu noch mehr Quelltext? Von welchem Typ ist andereMethode?
-
NIE einen Zeiger auf etwas zurückgeben dessen Ursprung nicht ausserhalb der funktion liegt!
-junix
-
Hallo,
sry, hier nun mit mehr Code.
die aufrufende:
extern char andereMethode(int port, int ausz_befehl, char *rueckgWert) ; // steht oben in der Main-Datei ..... void __fastcall TsgPort::btnScanAllClick(TObject *Sender) { int port = 1; int ausz_befehl = 1; char *rueckgWert; char *r_daten = andereMethode(port, ausz_befehl, rueckgWert); }Compiler-Fehler: "Konvertierung von int nach char* nicht möglich"
und hier die aufgerufene, von wo der Wert zurückgegeben werden soll (mal alles unnötige ausgerschmissen und zum testen einfach versucht einen String zurückzugeben):
char andereMethode(int port, int ausz_befehl, char *rueckgWert) { rueckgWert = "Rueckgabewert"; return rueckgWert; }Compiler-Fehler: "Konvertierung von char* nach int nicht möglich"
Aber ich konvertiere doch eigentlich nix... so schaut es jedenfalls für mich aus.
-
Schau nochmal wie die externe Funktion deklariert ist....
Und ausserdem:
junix schrieb:
NIE einen Zeiger auf etwas zurückgeben dessen Ursprung nicht ausserhalb der funktion liegt!
-
junix schrieb:
Schau nochmal wie die externe Funktion deklariert ist....
uff, also irgendwie stehe ich da total auf dem Schlauch. Sehe da irgendwie keinen Fehler.
junix schrieb:
Und ausserdem:
junix schrieb:
NIE einen Zeiger auf etwas zurückgeben dessen Ursprung nicht ausserhalb der funktion liegt!
Stimmt, die Rückgabe muss ja eigentlich ohne * sein.
Ich habe aber irgendwie keine andere Möglichkeit gefunden, wie man einen char String (kann auch gerne ansistring sein) zurückgeben kann.
-
Gib der Funktion den ZEiger wo sie reinschreiben kann doch einfach mit?
-junix
-
junix schrieb:
Gib der Funktion den ZEiger wo sie reinschreiben kann doch einfach mit?
-junix
das hört sich so schön leicht an, für einen "Anfänger" ist das aber ziemlich harte Arbeit.

Kann die Funktionsdeklaration nicht so bleiben? Muss ich stattdessen nicht nur die Adresse des Char-Strings übergeben, also der Aufruf:
andereMethode(port, ausz_befehl, &rueckgWert);Durch das & wird ja die Adresse übergeben.
Muss ich dann überhaupt was an return anhängen? So wie ich das deute, muss ich ja nix übergeben, da ich bereits auf der Adresse des ursprünglichen char Strings gearbeitet habe und der Wert dort erhalten bleibt.
sollte dann irgendwie so aussehen?
Funktionieren tut das leider auch nicht, bin aber irgendwie mit meinem Latein am Ende... könnte jetzt mal einen großen Wink mit dem Zaunpfahl vertragen.
extern char andereMethode(int port, int ausz_befehl, char *rueckgWert) ; // steht oben in der Main-Datei ..... void __fastcall TsgPort::btnScanAllClick(TObject *Sender) { int port = 1; int ausz_befehl = 1; char *rueckgWert; andereMethode(port, ausz_befehl, &rueckgWert); ListBox->AddItem(rueckgWert, ListBox); }char andereMethode(int port, int ausz_befehl, char *rueckgWert) { rueckgWert = "Rueckgabewert"; return 0; }
-
Probiers mal statt mit "=" mit "strncpy" (o;
Ansonsten vielleicht noch "rueckgWert" hat ja gar keinen Speicher hinterlegt?
Und wenn du schon eine Adresse hast (char
dann brauchste den & operator nicht mehr...Wenn du Zeiger deklarierst, gewöhn dir an, sie mit NULL zu initialisieren oder direkt mit new [] und neuem speicher. Aber dann das delete [] nicht vergessen...
-junix
-
Hi,
also wenn Du als Rückgabewert einen char-pointer haben willst muss Du es auch so deklarieren

nicht
char methode(...)sondern
char * methode(...)Wobei Pointer auf eine in der Funktion deklarierten Variable zurückzugeben ist nicht sauber. Beachte, dass beim Verlassen der Funktion die Variable "eigentlich" nicht mehr existiert. Kann zu den lustigsten effekten führen

nimm doch als Rückgabewert einfach einen AnsiString
AnsiString methode(...)
-
junix schrieb:
Probiers mal statt mit "=" mit "strncpy" (o;
Ansonsten vielleicht noch "rueckgWert" hat ja gar keinen Speicher hinterlegt?
Und wenn du schon eine Adresse hast (char
dann brauchste den & operator nicht mehr...Wenn du Zeiger deklarierst, gewöhn dir an, sie mit NULL zu initialisieren oder direkt mit new [] und neuem speicher. Aber dann das delete [] nicht vergessen...
-junix
Hi,
habe es nun mit char [] und strcpy hinbekommen.
Danke.

-
junix schrieb:
...
Wenn du Zeiger deklarierst, gewöhn dir an, sie mit NULL zu initialisieren oder direkt mit new [] und neuem speicher. Aber dann das delete [] nicht vergessen...hmmm... es gibt noch ein Problem mit delete, denn der Rückgabewert wird nicht wirklich gelöscht. Wenn die Abfragen kein Ergebnis haben, wird auch nix ausgegeben. Sobald das erste Ergebnis einen Rückgabewert enthält, haben auch die folgenden Ausgaben genau den gleichen Rückgabewert, obwohl das einfach nicht sein kann.
hier mal der Code (hoffentlich reicht der):
void __fastcall TsgPort::btnScanAllClick(TObject *Sender) { int port = 1; int ausz_befehl = 1; char rueckgWert[10]; // vor Bearbeitung neu anlegen andereMethode(port, ausz_befehl, rueckgWert); ListBox->AddItem(rueckgWert, ListBox); delete []rueckgWert; // nach Bearbeitung löschen }int andereMethode(int port, int ausz_befehl, char *rueckgWert) { // gobale Variable "AnsiString rueckgWert_a = NULL"; // in der Funktion wird der AnsiString nach und nach gefüllt, z.B.:: rueckgWer_a += sh_ver_log.Substring(pos, 4); ... // an Ende wird dann alles ins char kopiert: strcpy(rueckgWert, rueckgWert_a.c_str()); return 0; }
-
Führe NIEMALS delete auf Stackobjekte aus! Das darfst du nicht!
Ausserdem frage ich mich was du vom Delete erwartest? Und dann würde ich mir genau überlegen, was du da genau mit AddItem machst...Ausserdem sagte ich du sollst strncpy verwenden. Das andere ist zu unsicher und kann zu Pufferüberläufen führen.
-junix
-
junix schrieb:
Führe NIEMALS delete auf Stackobjekte aus! Das darfst du nicht!
Ausserdem frage ich mich was du vom Delete erwartest? Und dann würde ich mir genau überlegen, was du da genau mit AddItem machst...Ausserdem sagte ich du sollst strncpy verwenden. Das andere ist zu unsicher und kann zu Pufferüberläufen führen.
-junix
Stimmt, Du hast strncpy geschrieben. Hatte mich aber zuerst für strcpy entschieden, da es für mich die einfachere Möglichkeit war und ich keinen wirklich großen Unterschied zw. den beiden gesehen habe.
Das mit dem Delete hatte ich falsch verstanden. Ich dachte, dass ich dadurch die Daten an der Speicheradresse löschen. Habe mich auch irgendwie gewundert, da die am Ende nach der } ja automatisch gelöscht wird.... wusste es halt nicht besser.
Mit der Listbox wollte ich natürlich das Ergebnis in einem Fenster ausgeben.

hmm... hat ja sicherlich einen Grund, warum Du so auf die hinweisst.
Umgehen könnte ich das, indem ich den Rückgabewert via copy in eine struct kopiere (wo die eigentlich eh hin soll) und dann erst den Wert aus der struct ausgebe.
Dadurch das sich der Port ja immer ändert, wir dann auch immer das tatsächlich aktuell zurückgegebene ausgegeben.hier mal der Code (hoffentlich reicht der):
void __fastcall TsgPort::btnScanAllClick(TObject *Sender) { int port = 1; int ausz_befehl = 1; char rueckgWert[15]; andereMethode(port, 1, rueckgWert); AnsiString r_Wert = rueckgWert; int r_Wert_laenge = r_Wert.Length(); int pos = r_Wert.Pos("x"); meineStruct[port].R_ID = r_Wert.SubString(0, pos-2); meineStruct[port].Reg = r_Wert.SubString(pos-1, r_Wert_laenge-3 ); lbVerlauf->AddItem(att[port].Reg, lbVerlauf); lbVerlauf->AddItem(att[port].R_ID, lbVerlauf); }int andereMethode(int port, int ausz_befehl, char *rueckgWert) { // gobale Variable "AnsiString rueckgWert_a = NULL"; // in der Funktion wird der AnsiString nach und nach gefüllt, z.B.:: rueckgWer_a += sh_ver_log.Substring(pos, 4); ... // an Ende wird dann alles ins char kopiert: strncpy(rueckgWert, rueckgWert_a.c_str(), 12); return 0; }
-
Michael_S schrieb:
Stimmt, Du hast strncpy geschrieben. Hatte mich aber zuerst für strcpy entschieden, da es für mich die einfachere Möglichkeit war und ich keinen wirklich großen Unterschied zw. den beiden gesehen habe.
Der Wichtige aber nicht so grosse UNterschied ist die Tatsache, dass strncpy die Möglichkeit bietet die Grösse des Zielpuffers anzugeben und damit das Schreiben über die Speichergrenzen verhindert.
Michael_S schrieb:
[...]Habe mich auch irgendwie gewundert, da die am Ende nach der } ja automatisch gelöscht wird.... [...]
Hab leider grad keinen BCB zur HAnd, was ist die Deklaration von AddITem?
-junix
-
Hallo,
junix schrieb:
Hab leider grad keinen BCB zur HAnd, was ist die Deklaration von AddITem?
-junix
lautet wie folgt:
void __fastcall AddItem(AnsiString Item, TObject AObject);gruß,
MMFS
-
Michael_S,
ich würde Dir empfehlen sich mit den Grundlagen von C++ etwas zu befassen.
Ancheinend erkennst Du den Unterschied zwischen stack und heap nicht, genauso wenig wie char und char* .Außerdem würde ich an Deiner Stelle etwas am eigenen Design arbeiten,
was z.Bsp Funktionsdeklaration angeht, Präfixe etc.Es ist nicht persönlich gemeint lediglich als freundlicher Tipp
