Thread Merkwürdiges Verhalten von "split()" (20 answers)
Opened by hlubenow at 2017-07-29 19:59

hlubenow
 2017-07-31 12:09
#187063 #187063
User since
2009-02-22
876 Artikel
BenutzerIn
[default_avatar]
2017-07-31T08:51:19 Raubtier
Naja, das C-Split (sofern du von strtok sprichst) ist ja auch eine mehr als merkwürdige Funktion, weswegen es ja noch _r und _s gibt...

strok() ist in der Tat merkwürdig. Deswegen möchte ich das auch anders machen, mit einer verketteten Liste. Für deren Implementierung eine ganze Reihe von Funktionen (am Ende in einer Bibliothek) benötigt werden. (So wie im Perl-Interpreter eben auch. Da benutzt man ja die Listen wie @a, aber dafür müssen sie im Interpreter implementiert sein (weißt Du natürlich)).
Soll keine Angeberei sein, aber hier ist mal mein Machwerk. Nur mal main() angucken:
Code (C): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*  listsplit.c, (C) Hauke Lubenow, 2017, License: LGPL. */

typedef char * string;
typedef char * stringpointer;

enum types {TYPE_VOID, TYPE_INT, TYPE_FLOAT, TYPE_CHAR, TYPE_STRING};

struct List {
    struct List *next;
    struct List *previous;
    int type;
    void *data;
};

typedef struct List List;

// ----------------------------------------------
// List-functions:

List *initList() {
    List *border_first = malloc(sizeof(List));
    List *border_last = malloc(sizeof(List));
    border_first->next = border_last;
    border_first->previous = NULL;
    border_last->previous = border_first;
    border_last->next = NULL;
    border_first->type = TYPE_VOID;
    border_last->type = TYPE_VOID;
    return border_first;
}

void push(List *current, void *data, int type) {
    while (current->next != NULL) {
        current = current->next;
    }
    List *border_last = current;
    current = current->previous;
    List *sn = malloc(sizeof(List));
    sn->type = type;
    if (type == TYPE_STRING) {
        sn->data = strdup((char *) data);
    } else {
        sn->data = data;
    }
    border_last->previous = sn;
    current->next = sn;
    sn->next = border_last;
    sn->previous = current;
}

string getNodeDataAsString(List *current) {
    string s = malloc(100);
    switch (current->type) {

        case TYPE_VOID:
            puts("Warning: Accessing data of border-node.");
            s = "";
            break;

        case TYPE_INT:
            sprintf(s, "%d", * (int *) current->data);
            break;

        case TYPE_FLOAT:
            sprintf(s, "%f", * (double *) current->data);
            break;

        case TYPE_CHAR:
            sprintf(s, "\'%c\'", * (char *) current->data);
            break;

        case TYPE_STRING:
            s = realloc(s, strlen(current->data) + 10);
            sprintf(s, "\"%s\"", (char *) current->data);
            break;
    }
    return s;
}

void printList(List *current) {
    char *s;
    if (current->previous == NULL) {
        current = current->next;
    }
    printf("[");
    while (current->next != NULL) {
        s = getNodeDataAsString(current);
        printf("%s", s);
        free(s);
        current = current->next;
        if (current->next != NULL) {
            printf(", ");
        }
    }
    // Now, we're on border_last:
    printf("]\n");
}

void clearList(List *current) {
    while (current->next != NULL) {
        current = current->next;
        if (current->previous->type == TYPE_STRING) {
            free(current->previous->data);
        }
        free(current->previous);
    }
    free(current);
}

// ----------------------------------------------
// Functions, that use strings and lists:

List *split(string s, string substr, int showlast) {
    List *l = initList();
    stringpointer p = s;
    int slen = strlen(s);
    stringpointer p2 = s;
    string a;
    int i;
    while ((p = strstr(p, substr)) != NULL){
        a = malloc(p - p2);
        for (i = 0; i < p - p2; i++) {
            *(a + i) = *(p2 + i);
        }
        *(a + i) = '\0';
        push(l, a, TYPE_STRING);
        free(a);
        p += strlen(substr);
        p2 = p;
    }
    // The last part of the string, after the last occurrence
    // of substr has been found:
    if (p2 - s < slen) {
        push(l, p2, TYPE_STRING);
    }
    else if (p2 - s == slen && showlast) {
        push(l, p2, TYPE_STRING);
    }
    free(s);
    return l;
}


int main() {
    string a = malloc(100);
    strcpy(a, "The black cat climbed the green tree");
    List *l = initList();
    l = split(a, " ", 0);
    printList(l);
    clearList(l);
    return 0;
}

View full thread Merkwürdiges Verhalten von "split()"