Thread Merkwürdiges Verhalten von "split()"
(20 answers)
Opened by hlubenow at 2017-07-29 19:59 2017-07-31T08:51:19 Raubtier 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; } |