1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#!/usr/bin/perl use warnings; use strict; use feature 'say'; my $a = "Heswqe llo asdaBe llo ro llo ka llo ge llo"; my $b = "Heswqe llo asdaBe llo ro llo ka llo ge "; my @c = split(/llo/, $a); my @d = split(/llo/, $b); say for @c; say ""; say for @d; say $#c; say $#d;
perldoc -f split...
If LIMIT is negative, it is treated as if it were instead arbitrarily large; as many fields as possible are produced.
...
If LIMIT is omitted (or, equivalently, zero), then it is usually treated as if it were instead negative but with the exception that trailing empty fields are stripped (empty leading fields are always preserved); if all fields are empty, then all fields are considered to be trailing (and are thus stripped in this case).
...
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my $sample = "Heswqe llo asdaBe llo ro llo ka llo ge llo";
my @arr = split /llo/, $sample, -1;
print Dumper( \@arr );
2017-07-31T08:51:19 RaubtierNaja, 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...
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; }
QuoteSoll keine Angeberei sein, aber hier ist mal mein Machwerk.
2017-07-31T11:20:33 Raubtier3. Das abweichende Verhalten für strings in der Liste ist merkwürdig (strings werden kopiert, die anderen Typen aber nicht?)
1
2
3
4
5
if (type == TYPE_STRING) {
sn->data = strdup((char *) data);
} else {
sn->data = data;
}
2017-07-31T11:20:33 RaubtierDaran verstehe ich so einiges nicht.
1. Listen haben normalerweise eine Liste und dann ListNodes als Elemente. Dann kannst du dir die beiden Sentinels sparen.
Raubtier2. Sehr verwirrende typedefs. "string" und "stringpointer" sind beide dasselbe wie char*. Lass die typedefs lieber weg.
Raubtier3. Das abweichende Verhalten für strings in der Liste ist merkwürdig (strings werden kopiert, die anderen Typen aber nicht?)
betterworldIch denke mal, das Ziel ist, dass man auf den Rückgabewert immer free() anwenden kann/soll.
Raubtier4. malloc+realloc für das getNodeDataAsString? würde man nicht eher einen Buffer von außen dazugeben? Ansonsten nur malloc, gleich mit der richtigen Größe
Raubtier5. Das split free't den Eingabestring?!
Raubtier6. Überhaupt linked lists - warum, was haben die für einen Vorteil, außer dass sie langsam sind und so die CPU bzw. den Cache schön beschäftigen?
RaubtierZumal du auch ein "push" benutzt, das erst noch ganz die Liste durchlaufen muss - also du nutzt die langsamst mögliche Operation auf deiner Liste in einer Schleife!
Raubtier7. in main: string a = malloc(100); strcpy(a, "The black cat climbed the green tree"); - warum würde man das so tun wollen, warum nicht direkt den string verwenden? Ach ja, geht ja nicht, weil split nur mit ge"malloc"ten Strings funktioniert!
Raubtier8. list=initList(); list=was_anderes; scheint mit ein Speicherleck zu sein!
RaubtierQuoteSoll keine Angeberei sein, aber hier ist mal mein Machwerk.
Damit wirst du auch wohl kaum angeben können...
2017-07-31T16:22:11 hlubenowVielleicht hast Du bei Dir ja auch eine fertige Library für sowas rumliegen?
2017-07-31T16:22:11 hlubenowAber wenn ich nicht nur "next", sondern "next" und "previous" haben will, muß ich die doch auch irgendwie bei einer leeren Liste verketten.
QuoteIrgendwie finde ich "string" aber viel aussagekräftiger als "char *", denn letzteres kann ja auch ein Zeiger auf char, also ein Zeiger auf einen einzelnen char sein.
QuoteRaubtier3. Das abweichende Verhalten für strings in der Liste ist merkwürdig (strings werden kopiert, die anderen Typen aber nicht?)
betterworldIch denke mal, das Ziel ist, dass man auf den Rückgabewert immer free() anwenden kann/soll.
Genau, das ist der Plan. Sollte natürlich irgendwie einheitlich sein.
1
2
3
int i = 1234;
push(liste, &i, TYPE_INT);
i = 4321; // jetzt ist in der Liste auch 4321 drin
QuoteRaubtier5. Das split free't den Eingabestring?!
Ja. Normalerweise will man danach ja eben die Liste haben und nicht mehr den String.
QuoteRaubtier6. Überhaupt linked lists - warum, was haben die für einen Vorteil, außer dass sie langsam sind und so die CPU bzw. den Cache schön beschäftigen?
Denselben Vorteil wie Perl(...)
QuoteC ist eben schwer. Willst Du mich jetzt entmutigen