String übergeben an Funktion

Du bist neu in der Welt von C++? Dann schau hier herein!
Antworten
Tom17
Beiträge: 17
Registriert: 23. Juni 2011 14:01

String übergeben an Funktion

Beitrag von Tom17 »

Hallo,
ich möchte einen String an eine Funktion als Referenz übergeben. Diese Funktion fügt dann an den String etwas dazu. Wie mache ich dies nun richtig?

Mein Ansatz der aber nicht geht, da als Referenz ja kein String übergeben wird:

Code: Alles auswählen

#ifndef OUTSTR_H
#define OUTSTR_H
#endif // OUTSTR_H

#include "qstring.h"

void calc(char *str[], int z, int n)
{
    str.append(QString::number(z));
    str.append("x");
    str.append(QString::number(n));
    str.append("=");
    str.append(QString::number(z*n));
    str.append("   ");
}
Danke für eure Info.

LG, Tom
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: String übergeben an Funktion

Beitrag von franzf »

str ist ein Zeiger auf ein char-Array. Wie kommst du darauf, dass da eine Memberfunktion "append" existiert?
Ändere den Parameter in "QString& str" und alles sollte so funktionieren.
Noch besser wäre in deinem Fall, die Funktion calc würde einen QString zurückgeben, anstatt den Ergebnis-String als Parameter zu bekommen.
Tom17
Beiträge: 17
Registriert: 23. Juni 2011 14:01

Re: String übergeben an Funktion

Beitrag von Tom17 »

Hallo,
danke es funktioniert.

Da ich eine Tabelle darstelle und die Funktion mehrmals aufrufe und somit den String immer wieder verwende, ist es so für mich einmal besser. Trotzdem danke für den Hinweis.

LG, Tom
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: String übergeben an Funktion

Beitrag von franzf »

Besser wäre es, du würdest deine Tabelle ordentlich in Klassen kapseln.
Auch wenn du bei deinen freien Funktionen bleiben würdest, wären Rückgabewerte einfacher, flexibler und fehlerunanfälliger.

* Wenn Funktionen einen ihrer Parameter verändern, muss man da auch immer daran denken. Wenn man die Option hat, mit return-Werten zu arbeiten sollte man das auch machen. Man sollte Nebeneffekte so weit wie möglich vermeiden (Hauptaufgabe: String zusammenfügen. Nebeneffekt: den Parameter str manipulieren)

* returns sind auch flexibler:

Code: Alles auswählen

QString str;
calc(str, 1, 2);
calc(str, 4, 6);
calc(str, 20, 17);
gegenüber

Code: Alles auswählen

QString str = calc(1,2)
            + calc(4,6)
            + calc(20,17);
Wenn man den string vor dem Anfügen noch manipulieren will, wird es noch komlizierter:

Code: Alles auswählen

QString str;
calc(str,1,2);
QString tmp;
calc(tmp,4,6);
str.append(manipulate(tmp));
calc(str, 20, 17);
gegenüber

Code: Alles auswählen

QString str =  calc(1,2)
            + manipulate(calc(4,6))
            + calc(20,17);
Was gefällt dir besser?
Tom17
Beiträge: 17
Registriert: 23. Juni 2011 14:01

Re: String übergeben an Funktion

Beitrag von Tom17 »

Hallo,
habe leider erst jetzt gesehen, dass du noch eine AW geschrieben hast. Habe es auch schon umgestellt, dass ich einen String zurückgebe. Ist wirklich besser.

LG
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: String übergeben an Funktion

Beitrag von RHBaum »

dass ich einen String zurückgebe. Ist wirklich besser.
Besser ist relativ ^^
Richtig lauten muesste es: Es ist sicherer !

Und auch diese Methode hat Nachteile.
- Du nagelst den Empfaenger deines Strings auf eine Kopie eines Heap allokierten Speicherbereiches fest.
- Performance-verhalten ist abhaengig von der darunterliegenden Implementation (std::string ? Copy on Write implementiert oder nicht, wird meistens nicht sein) .

Kommt es dir nicht auf die performance an, isses natuerlich so der absolut beste Weg.
Iss Performance nen wichtiges Thema, wird deine Funktions-Signatur eher C-Style haben:

Code: Alles auswählen

void calc(char * buffer, size_t buffersize, int z, int n) 
Der absolute Performance Vorteil ist dann, das du nicht dynamisch umallokierst, was zu kurzen und abschaetzbaren Laufzeiten fuehrt.

Code: Alles auswählen

char pText[1024];
calc(pText,1024,5,7); 

std::cout << pText << std::endl;
Also, besser ist wirklich relativ ! :-)

Ciao ...
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: String übergeben an Funktion

Beitrag von franzf »

Du hast sicher recht. Aber in diesem Fall wird es einfach zu kompliziert und fehleranfällig.
Er will bei jedem Funktionsaufruf an den übergebenen String etwas anhängen. Dafür muss der String natürlich groß genug sein.
Damit man nicht aus Versehen über die Grenzen des Array hinaus schreibt, muss man eigentlich noch einen weiteren Parameter hinzufügen - len für die Länge der noch zu schreibenden Zeichen (machst du ja). Damit für den nächsten Aufruf der Pointer richtig gesetzt wird, muss man die Funktion eigentlch die geschriebenen Zeichen (Anzahl) zurückgeben lassen. Reicht die Anzahl der Zeichen nicht mehr aus, muss man selber ein neues Array anlegen und kopieren (Natürlcich mus die Funktion selber prüfen, ob sie genug Platz hat und den Mangel dem Aufrufer mitteilen).
Wenn man dann überlegt, für jeden Aufruf ein neues Array anzulegen (um nicht ständg Gräßen etc. anpassen zu müssen) um nach dem Aufruf an ein anderes anzustückeln, kann man gleich einen QString/std::string nehmen.

DENN:
Halbwegs aktuelle Compiler können RVO! Eine Kopie des intern angelegten Strings wird beim return eben NICHT MEHR gemacht, sondern direkt das interne Objekt herausgereicht.

Will man auf Performance optimieren (was man prinzipiell erst dann machen sollte, wenn sich existierender Code als Flaschenhals erweist), kann man eine andere Lösung andenken. Ich würde dann aber immer noch versuchen, die Optimierungen hinter einem einfach benutzbaren Interface zu verstecken.
Und da spielt jetzt wieder OOP rein:
Definier dir ein Interface, das du konstant halten kannst, die Interna kannst du jederzeit ändern, ohne dass die Verwendung angepasst werden muss.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: String übergeben an Funktion

Beitrag von RHBaum »

Halbwegs aktuelle Compiler können RVO!
Der ReturnWert-Übergabe ist IMHO auch ned das performance Problem.
Das "Problem" ist die Allokierung des Rueckgabewertes, und die eventuelle dynamische vergroesserung des Buffers.
Linderung schafft, indem man nicht mit trivialen

Code: Alles auswählen

std::string treturn;
allokiert, sondern erst dann wenn man scho weiss wie gross das teil wird und dann scho mit der entsprechenden groesse initialisiert

Code: Alles auswählen

std::string treturn(expectedSize,0);
Aber in diesem Fall wird es einfach zu kompliziert und fehleranfällig.
Definitiv.
Aber, ich sag immer wieder, wenn man niemals in nem Programm "Schmutz", "Hacks" oder andere wilde Dinge macht, um der Performance zu genügen, sollte man sich aber auch fragen, ob C++ die richtige Sprache an der Stelle war :-)
Das heisst nicht, das man in C++ nicht sauber und sicher auf Kosten der Performance programmieren soll ... das sollt auch in C++ die Regel sein.
Aber trotzdem sollt man sich der Performance-Thematik bewusst sein und auch bewusst die Entscheidung gegen die Performance treffen. Dann weiss man auch sofort, wo und wie man im entsprechenden Falle optzimieren koennt.
ch würde dann aber immer noch versuchen, die Optimierungen hinter einem einfach benutzbaren Interface zu verstecken.
Und genau das geht dann meistens nicht ... weil das Interface selber schon das performance Problem darstellt.

Biespiel:
Ich analysiere hier zur Laufzeit Datenstroeme mit Geschwindigkeiten um die 50Mbit .
Manche Werte ergeben halt Texte (ASCII).
wuerde Irgendwein Interface so aussehen
std::string IClass::getValue() const;
waer ich mit der Performance am Arsch ^^
Meine groessten feinde sind die news und die allokatoren ...

Und ich hab grad hier arg Probleme mit anderen Programmierkollegen.
Ich krieg interface's vorgesetzt, mit denen kann ich allein schon wegen dem Interface nimmer performant sein.
Performance faengt leider auch schon mit dem Design des Interfaces an ...

Aber davon denk ich, is der TE noch weit entfernt.
Trotzdem sollt man von Anfang an scho bissi in die Richtung denken, und lernen sich bewusst zwischen Performance und Sicherheit und Wartbarkeit entscheiden, und diese Entscheidung auch tragen. Das begleitet einen seinen ganzen Weg als Programmierer.

Und obwohl ich mit Leib und Seele C++ Programmierer bin, und Scriptjunkies belaechele :-) solange ich in der Firma bin, muessen sich meine Kollegen die Frage gefallen lassen: "Und warum qt / c++ ? Das haett man doch in Java / Python schneller und saueberer hinbekommen ?" :-)

Ciao ...
Tom17
Beiträge: 17
Registriert: 23. Juni 2011 14:01

Re: String übergeben an Funktion

Beitrag von Tom17 »

Danke für euren Beitrag.

LG
Antworten