PDA

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&uuml;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&uuml;ckerhalten. <BR>Also wie? <BR> <BR>Gruß, Marek

Import-Script
09.08.2002, 23:05
Das geht nicht. Du musst eine Zeichenkette anlegen &#40;eine leere notfalls&#41;, den Zeiger darauf an die Funktion &uuml;bergeben &#40;= &#34;by Reference&#34;&#41;, die Funktion ändert die Zeichenkette und fertig. <BR> <BR>void StringFkt&#40;char &#42; pText&#41;; <BR> <BR>main <BR>{ <BR> <BR>char sText[20]; <BR> <BR>StringFkt&#40;sText&#41;; <BR>// nach dem Aufruf hat die Funktion &#34;Hallo&#34; in sText geschrieben <BR> <BR>} <BR> <BR>void StringFkt&#40;char &#42; pText&#41; <BR>{ <BR> strcpy&#40;pText, &#34;Hallo&#34;&#41;; <BR>}

Import-Script
09.08.2002, 23:24
Das geht schon, wenn man den Speicher in der Funktion anfordert, einen Zeiger darauf zur&uuml;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&uuml;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&uuml;berliegenden Programmebenen haben, tja. <BR>Was ist aber mit &#34;by Reference&#34; gemeint und mit Zeiger? <BR>Sorry f&uuml;r meine Fragerei, fange erst mit C&#43;&#43; an, komme von QBasic und da hat man solche Probleme nicht... <BR> <BR>Beste Gr&uuml;ße, Marek

Import-Script
11.08.2002, 14:07
Das mit dem &#34;by Reference&#34; in C ist wie mit dem ByVal und ByRef in Basic. <BR> <BR>Bei ByRef&#40;by Reference&#41; wir der Funktion die Speicheraddresse, der Vaiabelen &uuml;bergeben, damit die Funktion direkt darauf zugreifen kann. <BR> <BR>Bei ByVal&#40;by Value&#41; wird der Funktion nur der Wert der Variabele &uuml;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&uuml;ß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>&#62;&#62;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&uuml;ckgabe wert hat&#40;Über return&#41;. Bei int, long, char... hat sie einen direkten R&uuml;ckgabewert. In Basic sähe es dann so aus x = Funktion&#40;y&#41; <BR> <BR>Das mit ByRef und ByVal funktioniert mit Pointern. Wenn in der Funktion am Anfang, der Variabele, die Übergeben wird ein &#42; steht dann wird ein Pointer &uuml;bergeben. Ein Pointer aber ist nichts anderes, als ein Zeiger auf eine bestimmte Speicherzelle, wo eine Variabele steht. Steht aber kein &#42; davor, so wird die Variabele grundsätzlich ByVal &uuml;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 &amp; 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 &#34;&#42;&#34;, wenn ich mit dem Pointer arbeite habe ich also dann die Möglichkeit &#40;oder die Gefahr&#41;, 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 &#40;ich weiß, hinkt ein bisschen&#41;. <BR>Also das mit dem &amp;-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&uuml;r das Zentrieren einer Zeichenkette geschrieben: <BR> <BR>void center&#40;int, char&#42;&#41;; <BR> <BR>void center&#40;int zeile, char&#42; string&#41; <BR>{ <BR> //V. 003 <BR> gotoxy&#40;40 - strlen&#40;string&#41;/2, zeile&#41;; <BR> printf&#40;string&#41;; <BR>} <BR> <BR>void main&#40;void&#41; <BR>{ <BR> char text[80]; <BR> strcpy&#40;text, &#34;Dieser Satz erscheint Zenteriert&#34;&#41;; <BR> center&#40;1, text&#41;; <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 &#42;g&#42; <BR> <BR>Beste Gr&uuml;ße, Marek

Import-Script
12.08.2002, 00:05
Ja, das ist die Besonderheit! Bei Zeichenketten kommst du ohne &amp; aus, weil Zeichenketten &#40;= sonstige Arrays&#41; grundsätzlich als Pointer &uuml;bergeben werden. Ansonsten m&uuml;ssten nämlich die Werte aller Felder &uuml;bergeben werden. <BR>In deinem Aufruf center&#40;1, text&#41; ist text ein Pointer, ohne dass du extra &amp; davorschreiben musst. <BR>Wolltest du aber z.B. nur das f&uuml;nfte Zeichen deiner Zeichenkette zentrieren &#40;ok, das ist zu nix gut und w&uuml;rde auch nicht gehen, weil strlen das Endekennzeichen &#40;null&#41; nicht findet&#41;, m&uuml;sste dein Aufruf heißen: <BR>center&#40;1, &amp;text[5]&#41; <BR>Denn text[5] ist kein Pointer, sondern ein einzelner Wert. Mit &amp; davor ermittelst du die Adresse dieses Wertest, erzeugst also einen Pointer auf den Wert. <BR>Man kann mit den Zeigern in C &uuml;brigens beliebig viel falsch machen, aber wenn man sich gewöhnt hat, geht&#39;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&#40;int &#42;zahl&#41; <BR>{ <BR>zahl = 4; // falsch, Zeiger wird geändert <BR>&#42;zahl = 4; // richtig, Wert, auf den Zeiger zeigt, wird geändert <BR>} <BR> <BR>void main&#40;void&#41; <BR>{ <BR>int a; <BR>SetzeVier&#40;&amp;a&#41;; <BR>printf&#40;&#34;%i&#34;, a&#41;; <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&uuml;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&uuml;bergabe Subroutine nur mit, wo sie zu finden sind. <BR> <BR>Zur Zeichenketten&uuml;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 &#40;Subroutine&#41; &uuml;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>&#34;int Zahl&#34; legt eine 16/32 bit breite Zahl in den Speicher. Die Bitbreite bei Int hängt von der Betriebssystembreite ab. <BR> <BR>&#34;int &#42;Zahl&#34; legt Speicherzellen an, die auf eine andere verweisen. Der Grund, warum man trotzdem int &#40;o.ä.&#41; angeben muß ist simpel. Inkrementiert man diese &#34;Zahl&#34;, 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= &#42;&#40;Feld&#43;i&#41;; <BR>Bei einer Schleife, die mehrere hunderttausend mal aufgerufen wird, ist die Geschwindigkeitszunahme sp&uuml;rbar. <BR>x= &#42;&#40;Feld&#43;i&#41;; heißt folgendes: <BR>Nimm die Adresse &#34;Feld&#34;, zähle i Elemente weiter und schreibe den Ihalt der Adresse in die Variable x. <BR> <BR>Mit dem &#42; kann man bei einem Pointer auf den Inhalt zugreifen, <BR>mit dem &amp; auf die Adresse einer normalen Variablen. <BR> <BR>Wir erinnern uns <BR>scanf&#40;&#34;%i&#34;,&amp;Zahl&#41;; <BR>warum das &amp;? ganz einfach, wohin soll die Funktion scanf&#40;&#41; den Wert schreiben. <BR> <BR>In C sind die Befehle, sofern nicht elementar &#40;if/int/char/else...&#41; Funktionsaufrufe, als wenn man sie selber macht. Diese stehen in den #include-Dateien und werden einfach in das Programm eingef&uuml;gt, bevor es compiliert wird. <BR> <BR>Es spricht nichts dagegen, eine eigene Bibliothek zu schreiben und sie an beliebiger Stelle mit <BR>#include&#34;Bibliothek.c&#34; 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&uuml;gend Speicherplatz bereitzustellen. <BR> <BR>Der hat jedoch keinerlei Kontrolle dar&uuml;ber, was die aufgerufene Funktion wirklich damit macht. Und wenn diese aus irgendeinem Grund mehr benötigt, nimmt sie sich diesen einfach und &uuml;berb&uuml;gelt gnadenlos Dein Programm oder andere wichtige Speicherbereiche. <BR> <BR> <BR>Abhilfe ist theoretisch ganz einfach, leider macht das kaum einer: <BR> <BR>Du &uuml;bergibst der Funktionen nicht nur einen Zeiger auf den Speicherplatz, sondern auch eine Zahl, wieviel Bytes darauf verf&uuml;gbar sind. Und diese Funktion schreibst Du eben so, daß sie abbricht, bevor Schaden angerichtet wird. Sie kann ja dann einen Fehlerkode zur&uuml;ckgeben, daß zu wenig Speicher da war. <BR> <BR>Z.B. der Supergau: <BR> <BR>char buffer[20]; <BR>int i; <BR>sprintf&#40; buffer, &#34;%d %s&#34;, i &#41;; <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&#40; buffer, 20, &#34;%d %s&#34;, i &#41;; <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 &#40;C64 kann das sehr gut&#41;. Bei PCs sind heutzutage leider die Daten etwas gefärdet.