Archiv verlassen und diese Seite im Standarddesign anzeigen : C-Frage #2: Rückgabe einer Zeichenkette von einer Function
Import-Script
09.08.2002, 21:27
Hi, wie muss der Prototyp einer Function aussehen, die mir eine Zeichenkette zurückgibt? <BR>Hab es mit char versucht, aber das funzt nicht, nur bei einem Zeichen, ich möchte aber eine ganze Zeichenkette oder nen char-Feld zurückerhalten. <BR>Also wie? <BR> <BR>Gruß, Marek
Import-Script
09.08.2002, 23:05
Das geht nicht. Du musst eine Zeichenkette anlegen (eine leere notfalls), den Zeiger darauf an die Funktion übergeben (= "by Reference"), die Funktion ändert die Zeichenkette und fertig. <BR> <BR>void StringFkt(char * pText); <BR> <BR>main <BR>{ <BR> <BR>char sText[20]; <BR> <BR>StringFkt(sText); <BR>// nach dem Aufruf hat die Funktion "Hallo" in sText geschrieben <BR> <BR>} <BR> <BR>void StringFkt(char * pText) <BR>{ <BR> strcpy(pText, "Hallo"); <BR>}
Import-Script
09.08.2002, 23:24
Das geht schon, wenn man den Speicher in der Funktion anfordert, einen Zeiger darauf zurückgibt, danach den Inhalt auswertet, und dann wieder freigibt. <BR>Call by Reference ist aber sicherlich eleganter.
Import-Script
11.08.2002, 00:36
Hi, danke für den Tipp. <BR>Habe es nun in Etwa auch so gelöst. Wusste gar nicht, dass man mit einer Function auch Variablen in der aufrufenden Prozedur verändern kann. <BR>In der Schule hat man uns gesagt, dass Manipulationen an Variablen in Functions keine Auswirkungen auf die darüberliegenden Programmebenen haben, tja. <BR>Was ist aber mit "by Reference" gemeint und mit Zeiger? <BR>Sorry für meine Fragerei, fange erst mit C++ an, komme von QBasic und da hat man solche Probleme nicht... <BR> <BR>Beste Grüße, Marek
Import-Script
11.08.2002, 14:07
Das mit dem "by Reference" in C ist wie mit dem ByVal und ByRef in Basic. <BR> <BR>Bei ByRef(by Reference) wir der Funktion die Speicheraddresse, der Vaiabelen übergeben, damit die Funktion direkt darauf zugreifen kann. <BR> <BR>Bei ByVal(by Value) wird der Funktion nur der Wert der Variabele übergeben. So kann die Funktion sie nicht ändern. <BR> <BR>Gruß Tobias
Import-Script
11.08.2002, 14:44
Aha! Und wie wähle ich nun zwischen beiden Fällen aus? <BR>By Reference wenn ich void vor die Funktion schreibe und By Value wenn was anderes davor steht, etwa int, char oder so, oder wie geht das? <BR> <BR>Beste Grüße, Marek
Import-Script
11.08.2002, 15:01
Ich progge nich in c und daher ist das alle hier nur teoretisches Wissen von mir aber ich schau mal, was ich noch weis: <BR> <BR>>>By Reference wenn ich void vor die Funktion schreibe <BR> <BR>Ne das is anders: <BR>Void bedeutet nur, dass die Funktion nicht direkt einen Rückgabe wert hat(Über return). Bei int, long, char... hat sie einen direkten Rückgabewert. In Basic sähe es dann so aus x = Funktion(y) <BR> <BR>Das mit ByRef und ByVal funktioniert mit Pointern. Wenn in der Funktion am Anfang, der Variabele, die Übergeben wird ein * steht dann wird ein Pointer übergeben. Ein Pointer aber ist nichts anderes, als ein Zeiger auf eine bestimmte Speicherzelle, wo eine Variabele steht. Steht aber kein * davor, so wird die Variabele grundsätzlich ByVal übergeben. <BR> <BR>So und jetzt noch ein Teil wo ich mir nich sicher bin, ob er stimmt: <BR> <BR>Ruft man eine Funktion, die einen Pointer Verlangt auf, so muss man im Aufruf ein & Zeichen vor die Vaiabele stellen, damit nicht nacher ihr Wert im Ponter steht sondern ihre Adresse. Aber das ist alles nur theretisches Wissen. <BR> <BR>Gruß Tobias <BR> <BR>Ps: <BR>Eventuelle Rechtschreibfehler sind gewollt <BR>Koregiert mich, wenn ich falsch liege.
Import-Script
11.08.2002, 15:26
Ah, ich glaub ich hab das verstanden. <BR>Also der Pointer ist das Sternchen "*", wenn ich mit dem Pointer arbeite habe ich also dann die Möglichkeit (oder die Gefahr), Variabeln zu verändern, dass die Veränderung auch außerhalb der Function bestehen bleibt. Also in etwa so zu vergleichen, wie die direkte/indirekte Adressierung in Assembler (ich weiß, hinkt ein bisschen). <BR>Also das mit dem &-Zeichen kann ich nicht nachvollziehen, meine Functions kommen ohne aus und wenn ich es einsetze kommen eh nur Fehlermeldungen. <BR>Hab mir z.B. eine Function für das Zentrieren einer Zeichenkette geschrieben: <BR> <BR>void center(int, char*); <BR> <BR>void center(int zeile, char* string) <BR>{ <BR> //V. 003 <BR> gotoxy(40 - strlen(string)/2, zeile); <BR> printf(string); <BR>} <BR> <BR>void main(void) <BR>{ <BR> char text[80]; <BR> strcpy(text, "Dieser Satz erscheint Zenteriert"); <BR> center(1, text); <BR>} <BR> <BR>Und das klappt problemlos. <BR>Aber danke, nun weiß ich bescheid und kann erst mal weiterarbeiten; wenn´s wieder hakt, dann hak ich nach *g* <BR> <BR>Beste Grüße, Marek
Import-Script
12.08.2002, 00:05
Ja, das ist die Besonderheit! Bei Zeichenketten kommst du ohne & aus, weil Zeichenketten (= sonstige Arrays) grundsätzlich als Pointer übergeben werden. Ansonsten müssten nämlich die Werte aller Felder übergeben werden. <BR>In deinem Aufruf center(1, text) ist text ein Pointer, ohne dass du extra & davorschreiben musst. <BR>Wolltest du aber z.B. nur das fünfte Zeichen deiner Zeichenkette zentrieren (ok, das ist zu nix gut und würde auch nicht gehen, weil strlen das Endekennzeichen (null) nicht findet), müsste dein Aufruf heißen: <BR>center(1, &text[5]) <BR>Denn text[5] ist kein Pointer, sondern ein einzelner Wert. Mit & davor ermittelst du die Adresse dieses Wertest, erzeugst also einen Pointer auf den Wert. <BR>Man kann mit den Zeigern in C übrigens beliebig viel falsch machen, aber wenn man sich gewöhnt hat, geht's. <BR>Noch etwas: <BR>Wenn du innerhalb einer Funktion dann den Wert verändern willst, auf den der Zeiger zeigt, musst du dort einen Stern davorstellen. <BR>Also: <BR>void SetzeVier(int *zahl) <BR>{ <BR>zahl = 4; // falsch, Zeiger wird geändert <BR>*zahl = 4; // richtig, Wert, auf den Zeiger zeigt, wird geändert <BR>} <BR> <BR>void main(void) <BR>{ <BR>int a; <BR>SetzeVier(&a); <BR>printf("%i", a); <BR>} <BR> <BR>a wird auf 4 gesetzt.
Import-Script
12.08.2002, 12:12
Hi, <BR> <BR>von der Assembler-Seite aus betrachtet, gibt es mehrere Möglichkeiten einen Funktionsaufruf mit Übergabeparametern zu realisieren. <BR> <BR>1. der Prozessor hat genügend Register. <BR>Alle Aufrufparameter in Register packen und per CALL an die Subroutine aufrufen. <BR>2. der Prozessor hat wenig Register, alles auf den Stack packen, CALL an die Subroutine, die liest den Stack aus, usw. <BR>3. die Parameter/Variablen bleiben dort wo sie sind und man teilt der per Adressübergabe Subroutine nur mit, wo sie zu finden sind. <BR> <BR>Zur Zeichenkettenübergabe sind die Varianten 1-2 nicht geeignet. Daher bleibt der String im Speicher liegen und es wird nur die Adresse und ggf. die Länge des Strings an die Funktion (Subroutine) übergeben. <BR> <BR>Siegfried
Import-Script
26.08.2002, 14:24
Hi, <BR>Bei C kann man Variablen als Pointer oder als normale Variable erzeugen. <BR> <BR>"int Zahl" legt eine 16/32 bit breite Zahl in den Speicher. Die Bitbreite bei Int hängt von der Betriebssystembreite ab. <BR> <BR>"int *Zahl" legt Speicherzellen an, die auf eine andere verweisen. Der Grund, warum man trotzdem int (o.ä.) angeben muß ist simpel. Inkrementiert man diese "Zahl", dann springt die Adresse um die Breite des Typs weiter, damit man damit direkt die nächste Zahl erreicht. <BR> <BR>Übrigens: x= Feld[i]; ist deutlich langsamer als <BR>x= *(Feld+i); <BR>Bei einer Schleife, die mehrere hunderttausend mal aufgerufen wird, ist die Geschwindigkeitszunahme spürbar. <BR>x= *(Feld+i); heißt folgendes: <BR>Nimm die Adresse "Feld", zähle i Elemente weiter und schreibe den Ihalt der Adresse in die Variable x. <BR> <BR>Mit dem * kann man bei einem Pointer auf den Inhalt zugreifen, <BR>mit dem & auf die Adresse einer normalen Variablen. <BR> <BR>Wir erinnern uns <BR>scanf("%i",&Zahl); <BR>warum das &? ganz einfach, wohin soll die Funktion scanf() den Wert schreiben. <BR> <BR>In C sind die Befehle, sofern nicht elementar (if/int/char/else...) Funktionsaufrufe, als wenn man sie selber macht. Diese stehen in den #include-Dateien und werden einfach in das Programm eingefügt, bevor es compiliert wird. <BR> <BR>Es spricht nichts dagegen, eine eigene Bibliothek zu schreiben und sie an beliebiger Stelle mit <BR>#include"Bibliothek.c" einzubinden. <BR> <BR>Gruß <BR>Elmar
Import-Script
26.08.2002, 21:48
Wenn Du Dir Funktionen zur Zeichenkettenverarbeitung schreibst, machs nicht, wie die Profi-C-Programmierer, sondern machs besser. <BR> <BR>Der Hauptgrung, warum es unter Windows alle Naselang kracht, sind nämlich diese kreuzgefährlichen Zeichenkettenfunktionen. <BR> <BR>Wie ja oben schon gesagt, liegt es meistens in der Verantwortung des Aufrufers, genügend Speicherplatz bereitzustellen. <BR> <BR>Der hat jedoch keinerlei Kontrolle darüber, was die aufgerufene Funktion wirklich damit macht. Und wenn diese aus irgendeinem Grund mehr benötigt, nimmt sie sich diesen einfach und überbügelt gnadenlos Dein Programm oder andere wichtige Speicherbereiche. <BR> <BR> <BR>Abhilfe ist theoretisch ganz einfach, leider macht das kaum einer: <BR> <BR>Du übergibst der Funktionen nicht nur einen Zeiger auf den Speicherplatz, sondern auch eine Zahl, wieviel Bytes darauf verfügbar sind. Und diese Funktion schreibst Du eben so, daß sie abbricht, bevor Schaden angerichtet wird. Sie kann ja dann einen Fehlerkode zurückgeben, daß zu wenig Speicher da war. <BR> <BR>Z.B. der Supergau: <BR> <BR>char buffer[20]; <BR>int i; <BR>sprintf( buffer, "%d %s", i ); <BR> <BR>Da wurde einfach das 2. Argument vergessen und schon kracht es sonstwo. <BR> <BR> <BR>Die Lösung: <BR> <BR>char buffer[20]; <BR>int i; <BR>my_sprintf( buffer, 20, "%d %s", i ); <BR> <BR>Dann steht zwar immer noch in buffer[] ein falscher Text, aber Dein Programm läuft weiter und könnte Dir eine Fehlermeldung ausgeben. <BR> <BR> <BR> <BR>Peter <BR> <BR>
Import-Script
03.01.2003, 14:06
Hi, <BR>muß man halt mal erlebt haben, wenn sich der Computer singend und Pfeifend verabschiedet (C64 kann das sehr gut). Bei PCs sind heutzutage leider die Daten etwas gefärdet.
Powered by vBulletin® Version 4.1.7 Copyright ©2012 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.