Forum: PC-Programmierung C returne char[][] („String“-Array)


von Bartosz B. (bartosz)



Lesenswert?

Hallo,
ich hatte nach langer Zeit mal wieder Lust auf C und ich diesmal dabei, 
eine Headerdatei zu schreiben, die ich in zukünftige Projekte einbauen 
kann, um es einfacher zu haben. Ich will einige Funktionen haben, die 
ich aus dem .NET-Framework kenne, und die es einem einfacher machen.

Mein derzeitiges Problem besteht darin, dass ich in der Headerdatei eine 
Funktion split() habe, die einen String (ja, ich weiß, es gibt in C 
keine Strings per se) anhand von einem Trennzeichen aufsplittet. Ich 
möchte, dass die Funktion mir ein zweidimensionales Char-Array 
zurückgibt (also ein „String-Array“). Bei der Rückgabe habe ich 
Schwierigkeiten.
Ich habe heute schon Einiges probiert:

https://stackoverflow.com/questions/36535898/pass-a-struct-to-a-function

https://stackoverflow.com/questions/4085372/how-to-return-a-string-array-from-a-function

https://www.quora.com/How-do-you-create-a-function-that-returns-an-array-of-strings-in-C


Wenn ich die Quellcodes kopiere, gibt es entweder Compilerfehler, oder 
ich kann den zurückgegebenen **Pointer nicht auslesen.

Ich kompiliere das Projekt in x64. Ich schreibe das Programm in Visual 
Studio 2019 CE. Es ist ein C++-Konsolenprojekt, allerdings habe ich 
eingestellt, dass nur als C-Code kompiliert wird.
1
char StringToSplit[] = { "This is - www.tutorialspoint.com - website" };
2
char deli[2] = "-";
3
char *Test = split(StringToSplit, deli);
–––
1
char* split(char* StringToSplit, char* delimiters)
2
{
3
    static char temp[10][20]={'\0'};
4
    int i = 0;
5
    char* token;
6
    /* have a look first */
7
    token = strtok(StringToSplit, delimiters);
8
    /* walk through tokens */
9
    while (token != NULL)
10
    {
11
        strcpy(temp[i], token);
12
        i++;
13
        printf(" %s\n", token);
14
        token = strtok(NULL, delimiters);
15
    }
16
    return *temp;
17
}

von PittyJ (Gast)


Lesenswert?

Ich habe schon seit Jahren keine Lust mehr auf die char * Rechnerei.
Ich nehme nur noch std::string. Und wenn ich Vektoren davon brauche, 
dann noch mal std::vector davon.
Die Probleme mit char * (Nullptr Zugriff, zeigen ins Nirvana ...) sind 
drastisch gesunken.
Wenn du C++ hast, verwende es einfach. Das hätte dir den Post hier 
erspart.

von J. S. (jojos)


Lesenswert?

die Antwort steht doch schon im 2. Stackoverflow Link. Das statisch 
angelegte Array ist ein zweidimensionales Feld von char, und nicht ein 
Array von Zeigern. Genau das brauchst du aber und das muss dann 
dynamisch angelegt werden.
1
#include <stdio.h>
2
#include <string.h>
3
#include <stdlib.h>
4
5
char** split(char* StringToSplit, char* delimiters)
6
{
7
    //static char temp[10][20]={'\0'};
8
    int i = 0;
9
    char* token;
10
11
    // allocate string memory
12
    char ** temp = malloc(10 * sizeof(char*));
13
    for (int i =0 ; i < 10; ++i) {
14
        temp[i] = malloc(20 * sizeof(char));
15
        temp[i][0] = 0;
16
    }
17
    
18
    /* have a look first */
19
    token = strtok(StringToSplit, delimiters);
20
    /* walk through tokens */
21
    while (token != NULL)
22
    {
23
        strcpy(temp[i], token);
24
        printf("%d:  %s\n", i, token);
25
        i++;
26
        token = strtok(NULL, delimiters);
27
    }
28
29
    return temp;
30
}
31
32
33
int main()
34
{
35
    char StringToSplit[] = { "This is - www.tutorialspoint.com - website" };
36
    char deli[2] = "-";
37
    char **Test = split(StringToSplit, deli);
38
    
39
    printf("Test: %s\n", Test[0]);
40
    printf("Test: %s\n", Test[1]);
41
    printf("Test: %s\n", Test[2]);
42
    printf("Test: %s\n", Test[3]);
43
44
    return 0;
45
}

kann man auch schön in https://www.onlinegdb.com/ testen.
Der code ist allerdings übel mit so fixen Längen, ich bevorzuge auch 
Stringklassen.
Oder nur ein Array mit Zeigern auf die Teilstrings füllen, ohne die 
Strings nochmal zu kopieren.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Bartosz B. schrieb:

> ich hatte nach langer Zeit mal wieder Lust auf C

Du bist wohl eine kleiner Masochist? Lust auf C? Das benutzt man, wenn's 
partout nicht anders geht oder der Aufwand ohne die Verwendung von C 
extrem wachsen würde. Sonst niemals.

> und ich diesmal dabei,
> eine Headerdatei zu schreiben, die ich in zukünftige Projekte einbauen
> kann, um es einfacher zu haben. Ich will einige Funktionen haben, die
> ich aus dem .NET-Framework kenne, und die es einem einfacher machen.

Tja, es ist wirklich nicht leicht, den Luxus echter Hochsprachen in 
einen aufgedonnerten Macro-Assembler zu übertragen. Ich wünsche noch 
viel "Spaß" dabei...

von Bartosz B. (bartosz)


Lesenswert?

@J. S. Vielen Dank! Habs nur nochmal mit anderen Worten gebraucht. Ich 
übergebe des Weiteren nun "by reference" einen Integer, welcher in der 
split-Funktion beschrieben wird. So weiß ich, wenn split geendet hat, 
wie viele Teilstrings es gibt, und kann mit 'ner for-Schleife die 
Teilstrings drucken.

Und free nicht vergessen :)

von Dirk B. (dirkb2)


Lesenswert?

Du hättest das char temp[10][20] auch als Parameter übergeben können.

Die 10 und 20 könnte man auch noch als Parameter voranstellen (siehe 
VLA)

von totomitharry (Gast)


Lesenswert?

Wieso nutzt man nicht den eigentlichen String weiter und übergibt direkt 
die Pointer?
1
    while (token != NULL)
2
    {
3
        temp[i++] = token;
4
        token = strtok(NULL, delimiters);
5
    }

somit arbeitet man nur mit dem String und Pointern, strtok ersetzt sogar 
den Delimiter durch ein '\0'..  da braucht man dann auch nix kopieren.

von Rolf M. (rmagnus)


Lesenswert?

c-hater schrieb:
> Du bist wohl eine kleiner Masochist? Lust auf C? Das benutzt man, wenn's
> partout nicht anders geht oder der Aufwand ohne die Verwendung von C
> extrem wachsen würde. Sonst niemals.

C mit Assembler verwechselt?

von W.S. (Gast)


Lesenswert?

Rolf M. schrieb:
> C mit Assembler verwechselt?

Nö. Da gibt es fast nix zu verwechseln... bis auf den Umstand, daß man 
beim Assembler genau das kriegt, was man geschrieben hat (und nicht, was 
man gemeint hat) während man bei C das kriegt, was der Compiler meint, 
daß man es gemeint haben könnte. Mahlzeit.

W.S.

von WF88 (Gast)


Lesenswert?

W.S. schrieb:
> . Da gibt es fast nix zu verwechseln... bis auf den Umstand, daß man
> beim Assembler genau das kriegt, was man geschrieben hat (und nicht, was
> man gemeint hat) während man bei C das kriegt, was der Compiler meint,
> daß man es gemeint haben könnte. Mahlzeit

Ah, deshalb kommt von dir so grauenhaft lesbarer C Coder immer mal 
wieder. Bisher dachte ich immer, das seit 80er Pascal Style auf 2010er 
Hardware in C angewendet.

Nimm das bitte nicht all zu Ernst, das ist ein Witz. Ich bin aber glaube 
nicht der Einzige, dem das in Sinn kam ;)

von WF88 (Gast)


Lesenswert?

* dachte ich immer, das sei ....

nicht seit.

von Liebhaberschönencodes (Gast)


Lesenswert?

Ach so, das ist es also, was die "Lernbetty" so unerträglich macht -- 
dieser üble Leichengeruch nach Pascal, der tötesten aller Leersprachen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.