C Eine Funktion schreiben, die ein char-Array entgegennimmt und ein char-Array returnt

Jack159

Lieutenant
Registriert
Dez. 2011
Beiträge
766
Hi,

Ich kriege es irgendwie nicht hin in C eine Funktion zu schreiben, welche ein char-Array entgegennimmt und ein char-Array zurückgibt.

Beispiel:

Code:
#include<stdio.h>
#include <string.h>

char test[](char bla[]) {
	
	return "test";
}

int main() {
	char a[100] = test("bla");	
	return 0;
}

Hier würde er mir folgende Warnung und Fehlermeldung geben:

main.c:4:25: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{'
token
char test[](char bla[]) {
^
main.c: In function 'main':
main.c:10:2: warning: implicit declaration of function 'test' [-Wimplicit-functi
on-declaration]
char a[100] = test("bla");
^
main.c:10:2: error: invalid initializer
 
char test[](char bla[]) {
Du hast die Klammern falsch gesetzt.

So muss es geschrieben werden:
char[] test(char bla[]) {
Es ist schließlich kein Methodenarray (was auch immer das ist) sondern ein Char-Array.


Und was sollte das hier?
char a[100] = test("bla");
Nimm das Char-Array und packe es in Feld Nummer 100 von a? Das funktioniert so nicht.

So ist es korrekt:
char[] a = test("bla");
 
e-Laurin schrieb:
char test[](char bla[]) {
Du hast die Klammern falsch gesetzt.

So muss es geschrieben werden:
char[] test(char bla[]) {


Und was sollte das hier?
char a[100] = test("bla");
Nimm das Char-Array und packe es in Feld Nummer 100 von a? Das funktioniert so nicht.

So ist es korrekt:
char[] a = test("bla");

Ahh ok danke ;)

Ich denke zu sehr in Java :D
 
Da sind gleich mehrere Fehler drin. Erstens: Es müsste nicht heißen char test[](...), sondern char[] test(...), denn "test" ist der Name der Funktion, und kein Array. Die eckigen Klammern gehören wenn, dann zum Rückgabetyp (char).

Zweitens: Mit return "test"; könnte es Probleme mit der Speicherverwaltung geben. Sprich: Der Speicher für das char-Array in dem der Text "test" abgelegt wird, wird vermutlich in der Methode test erzeugt und bei Ende wieder gelöscht. Vermutlich musst du da eher mit new und delete arbeiten, um den Speicher explizit anzulegen und wieder zu löschen wenn er nicht mehr benötigt wird.

So weit ich mich erinnere hab ich da normalerweise als Übergabe- und Rückgabetyp auch nicht char[] verwendet, sondern eher char*, also einen Zeiger auf das erste Element des Arrays, das man mit "new" angelegt hat.

(Könnte so aber auch funktionieren, C++ ist jetzt schon eine Weile her ^^)

main.c: In function 'main':
main.c:10:2: warning: implicit declaration of function 'test' [-Wimplicit-functi
on-declaration]
char a[100] = test("bla");
^
main.c:10:2: error: invalid initializer[/I]
Der Fehler kommt genau deshalb, weil wie anfangs gesagt die Methode "test" nicht syntaktisch richtig hingeschrieben ist (eckige Klammern falsch), und er "test("bla") deshalb in der Methode "main" nicht als existierende Methode erkennt.
 
Würde es als Zeiger schreiben. Das kommt dem, was passiert näher und geht auch leichter von der Hand. Allgemein sieht das Programm merkwürdig aus. Kann man überhaupt (sinnvoll) einen String Literal zurückgeben? Habe gerade keinen Compiler hier zum ausprobieren.
 
e-Laurin schrieb:
char test[](char bla[]) {
Du hast die Klammern falsch gesetzt.

So muss es geschrieben werden:
char[] test(char bla[]) {
Es ist schließlich kein Methodenarray (was auch immer das ist) sondern ein Char-Array.


Und was sollte das hier?
char a[100] = test("bla");
Nimm das Char-Array und packe es in Feld Nummer 100 von a? Das funktioniert so nicht.

So ist es korrekt:
char[] a = test("bla");


Hmm ich habs jetzt mal ausprobiert, aber ich bekomme immer noch Fehlermeldungen.


Der neue Code:

Code:
#include<stdio.h>
#include <string.h>

char[] test(char bla[]) {
	return "test";
}

int main() {
	 char[] a = test("bla"); 
	return 0;
}


Fehlermeldung:


main.c:4:5: error: expected identifier or '(' before '[' token
char[] test(char bla[]) {
^
main.c: In function 'main':
main.c:9:7: error: expected identifier or '(' before '[' token
char[] a = test("bla");
^
 
man gibt in C kein Char Array so zurück.
Wenn du ein Char Array zurückgeben willst, musst du die Boost Lib nehmen
oder du returnst char*
 
@Jack159
So funktioniert das in C auch nicht. Auch nicht so wie e-laurin das gezeigt hat. In C gibt es statische Arrays, die werden direkt mit einer Größe versehen beim Deklarieren, so wie du es im 1. Beispiel hattest, allerdings kannst du diese nicht mit dem Rückgabewert einer Funktion initialisieren, da eine Funktion kein statisches Array zurückgeben kann.

Du musst hier also mit dynamischen Arrays arbeiten (Pointer), wenn du welche zurückgeben willst oder einfach dein statisches Array als Parameter übergeben und direkt darin arbeiten.
 
Hatte ich also doch richtig in Erinnerung mit den Char Arrays. ;) Zeiger zurück geben, und fertig. (Na ja, fast.)

C++ ist halt nicht so schön bequem wie Java oder C#. Aber hat dafür andere Vorteile.
 
Wenn man in C eine Funktion schreiben will, die ein Array zurückgibt, dann realisiert man das üblicherweise nicht als Rückgabewert, sondern als Rückgabeparameter:
Code:
#define OK 0
#define ERROR_BUFFER_TOO_SMALL 1

int test(const char* input /*Eingabe-Parameter*/, char* output /*Rückgabe-Parameter*/, int outputLen /*Größe von output*/)
{
    char temp[] = "bla";
    if (strlen(temp) < outputLen - 1)    // passt temp in output?
    {
        strcpy(output, temp);            // temp in output kopieren
        return OK;                       // OK zurückgeben
    }
    else
    {
        return ERROR_BUFFER_TOO_SMALL;   // Fehler zurückgeben
    }
}

int main()
{
    char a[100];
    test("bla", a, 100);
    return 0;
}
Hier unterscheidet sich C erheblich von Java ;)
 
Zuletzt bearbeitet:
kinglouy schrieb:
@Jack159
So funktioniert das in C auch nicht. Auch nicht so wie e-laurin das gezeigt hat. In C gibt es statische Arrays, die werden direkt mit einer Größe versehen beim Deklarieren, so wie du es im 1. Beispiel hattest, allerdings kannst du diese nicht mit dem Rückgabewert einer Funktion initialisieren, da eine Funktion kein statisches Array zurückgeben kann.

Du musst hier also mit dynamischen Arrays arbeiten (Pointer), wenn du welche zurückgeben willst oder einfach dein statisches Array als Parameter übergeben und direkt darin arbeiten.

Code:
#include<stdio.h>
#include <string.h>

char *test(char bla[]) {
	return "test";
}

int main() {
	 char *a = test("bla"); 
	 printf("%s", a);	
	return 0;
}

jetzt funktioniert es. Ich denke so war es gemeint?!

Danke nochmals ;)
 
Ok, die neuen Antworten sind deutlich kompatibler mit dem, was ich von C kenne.

Also richtige Antwort:

Code:
char *f(char *in){
    char *out = malloc(...);
    [...]
    return out;
}

Rückgabewert von malloc() natürlich prüfen und wenn man das Ergebnis nicht mehr benötigt, free() nicht vergessen.

Für Details verweise ich auf kompetente Lehrbücher.
 
Zuletzt bearbeitet:
@asdfman: so kann man das zwar machen, handelt sich damit aber das Problem ein, dass der Aufrufer der Funktion test() sich darum kömmern muss, den mit malloc() allokierten Speicher irgendwann wieder mit free() freizugeben. Die Lösung mittels Rückgabeparameter ist in der Hinsicht eleganter. Nur kontraintuitiver für jemanden, der davon ausgeht, dass das, was zurückgegeben werden soll, im Rückgabewert (statt in einem Parameter) stecken sollte.
Ergänzung ()

Kelshan schrieb:
Vermutlich musst du da eher mit new und delete arbeiten, um den Speicher explizit anzulegen und wieder zu löschen wenn er nicht mehr benötigt wird.

Sneazel schrieb:
Wenn du ein Char Array zurückgeben willst, musst du die Boost Lib nehmen
oder du returnst char*
kleine Anmerkung: in C gibt es weder eine Boost Lib noch new und delete. Wir sind hier nicht in C++ ;)
 
Jack159 schrieb:
Code:
#include<stdio.h>
#include <string.h>

char *test(char bla[]) {
return "test";
}

int main() {
 char *a = test("bla"); 
 printf("%s", a);
return 0;
}

jetzt funktioniert es. Ich denke so war es gemeint?!

Danke nochmals ;)

Computerbase-Spitzenleistung mal wieder. Der arme Kerl hat nichts gelernt, aber bedankt sich fein für die unerklärte "Lösung", mit der er bei der nächsten kleinen Variation des Problems gnadenlos scheitern wird. Auch Bonuspunkte für den Mann mit seinem herrlich unangebrachten sowie unnötig komplizierten und für einen Anfänger unverständlichen ohne Erklärung geposteten Beispiel mit dem Rückgabeparameter.

Bravo, Bravo, Bravo!
 
Ich vermutlich auch. Aber inwiefern nützt das OP? Das verwirrt ihn nur und am Ende hat er keinerlei Erkenntnisgewinn.
 
Vielleicht wäre es zum Anfang recht sinnvoll ein kleines Kommandozeilentool zu schreiben, was auf eine Eingabe wartet, und den eingegebenen Wert wieder zurückgibt oder einfach nur die vorhandenen Beispiele um eine Ausgabe der Zwischenergebnisse erweitert.
 
Na hier wird aber ein Kauderwelch produziert nach der Methode "Hauptsache es funktioniert".

Code:
char[] a = test( ... )
Das geht allgemein nicht da der Compiler im rechten Teil von = eine Konstante zur Initalisierung erwartet, damit er die Größe auf dem Stack ermitteln kann. C ist keine Interpretersprache.

Code:
char* a = test( ... )
Ist übersetzbar, aber nun sollte man nachdenken. Man bekommt einen Zeiger auf ein beliebiges Stück Speicher geliefert. Sieht deine Funktion test(char* string) so aus:
Code:
char* test(char* string)
{ return "blaaa" }
bekommst du je nach Compiler ein festes Stück Speicher aus deinem Data Segment, dümmstenfalls aber auch nur einen Zeiger auf ein temporäres Stück Speicher was nach dem return schon wieder geleert wurde vom Compiler.


Eine "saubere" C-Notation für die Rückgabe von Zeichenketten entspricht z.B. der Funktion strdup:
Code:
void Test(char* src, char* dest, size_t buf_size)
{
/*Achtung: Der Ausdruck dest = "test" würde nix bewirken da du nur den Zeiger auf dem Stack verbiegst
   daher Byte-weise kopieren/setzen*/
   size_t size_src = strlen(src);
   size_t n = 0;
   for (n=0; n<buf_size-1 && n<size_src; n++)
      dest[n] = src[n]; ///Einfache Kopie

   dest[n] = 0x00; //Terminating 0
}

Die Buffer musst du vorher festlegen, der Aufruf sieht dann folgendermaßen aus (hier konstante Buffer):
Code:
char my_str[] = "Blaablaaa";

const size_t size_buffer = 100;
char output_buffer[size_buffer];

Test(my_str, output_buffer, size_buffer);

cout << output_buffer;

Anmerkung: Freihand-Coding. Ich habe das jetzt nicht kompiliert sondern nur aus dem Kopf codiert. Kann also noch kleine Fehler enthalten. Aber das Prinzip sollte klar sein.
 
Zuletzt bearbeitet:
Sculletto schrieb:
kleine Anmerkung: in C gibt es weder eine Boost Lib noch new und delete. Wir sind hier nicht in C++ ;)
Das stimmt natürlich. Reines C brauchte ich noch nie und verwende den Begriff aus Gewohnheit daher äquivalent. Wenn es wirklich reines C sein soll ist das natürlich entsprechend zu beachten.
 
Zurück
Oben