Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: String_Replace zu langsam! Hat jemand eine Idee?

24 views
Skip to first unread message
Message has been deleted

U. v. Bassewitz

unread,
Feb 25, 2012, 12:41:25 PM2/25/12
to
Thomas Mundt <mundt_...@yahoo.de> wrote:
> In einem sehr großer string > 10 Millionen char sollen Wörter ersetzt
> werden.
>
> Das funktioniert auch, nur dauert es verdächtig lange :-(
>
> Hat jemand eine Idee woran es liegen könnte?

Für Deine Hausaufgaben bin ich zu faul, aber ich kann Dir folgenden
Artikel empfehlen:

http://german.joelonsoftware.com/Articles/BacktoBasics.html

Gruß


Uz


--
Ullrich von Bassewitz u...@spamtrap.musoftware.de
18:39:32 up 31 days, 7:46, 3 users, load average: 0.65, 0.72, 0.77
Message has been deleted

Jan Seiffert

unread,
Feb 25, 2012, 9:11:27 PM2/25/12
to
Thomas Mundt schrieb:
> In einem sehr großer string > 10 Millionen char sollen Wörter ersetzt
> werden.
>
> Das funktioniert auch, nur dauert es verdächtig lange :-(
>
> Hat jemand eine Idee woran es liegen könnte?
>

[snip - code]
Wenn ich das richtig verstehe kopierst du den ganzen string ständig im vollen
hin und her, das ist schon unschön. Dann benutzt du die C string Funktionen noch
in der echten Schlemier-der-Maler art-und-weise (siehe auch joelonsoftware).

Hier mal ungetested wie ich das machen würde

#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>

static char *correct_len(char *a, size_t *len, size_t have, size_t need)
{
if(have < need)
{
size_t t = need - have;
char *x;
t += *len + 1;
x = realloc(a, t);
if(!x) {
free(a);
return NULL;
}
a = x;
*len = t;
}
return a;
}

char *replace(const char *arg)
{
const char *m_start;
char *ret, *match;
size_t o_len, ro_len, r_len, r_start;
int cnt = 1;

o_len = strlen(arg) + 1;

ret = malloc(o_len);
if(!ret)
return NULL;

ro_len = r_len = o_len;
r_start = 0;
m_start = arg;
while ((match = strstr(m_start, "item")))
{
size_t m_len = match - m_start;

/* 12 char should be enough to print an int */
if(!(ret = correct_len(ret, &ro_len, r_len, m_len + sizeof("item") + 12)))
return NULL;
memcpy(ret + r_start, m_start, m_len);
r_start += m_len;
r_len -= m_len;
m_start += m_len + sizeof("item") - 1;
m_len = sprintf(ret + r_start, "item%d", cnt++);
r_start += m_len;
r_len -= m_len;
}
o_len = strlen(m_start) + 1;
if(!(ret = correct_len(ret, &ro_len, r_len, o_len)))
return NULL;
memcpy(ret + r_start, m_start, o_len);
return ret;
}

Das kann man noch optimieren, z.B. je nach dem wieviel Speicher verschwended
werden darf den neuen String viel grösser vor allozieieren.
Auch sprintf ist nicht das schnellste.
Man könnte strstr und das memcpy zusammmenfassen, strstr muss eh immer über den
string und alle Buchstaben anfassen, da kann es sie gleich kopieren, und da der
Suchstring fest vorgegeben ist ist das auch noch optimierungsfähig...

Gruss
Jan

Stefan Reuther

unread,
Feb 26, 2012, 6:09:05 AM2/26/12
to
U. v. Bassewitz wrote:
> Thomas Mundt <mundt_...@yahoo.de> wrote:
>>In einem sehr großer string > 10 Millionen char sollen Wörter ersetzt
>>werden.
>>
>>Das funktioniert auch, nur dauert es verdächtig lange :-(
>>
>>Hat jemand eine Idee woran es liegen könnte?
>
> Für Deine Hausaufgaben bin ich zu faul, aber ich kann Dir folgenden
> Artikel empfehlen:
>
> http://german.joelonsoftware.com/Articles/BacktoBasics.html

Sehr schön.

Bei > 10 Millionen char wäre ansonsten auch zu überlegen, ob ein String
noch die richtige Datenstruktur ist oder ob nicht besser etwas
kleinteiligeres (z.B. Array von (Zeigern auf) Substrings) sinnvoller
wäre, so dass man beim Austauschen eines Wortes nur einen Substring neu
allokieren muss und nicht die ganzen 10 Millionen Bytes.


Stefan

Rainer Weikusat

unread,
Feb 26, 2012, 2:41:26 PM2/26/12
to
Thomas Mundt <mundt_...@yahoo.de> writes:

> In einem sehr großer string > 10 Millionen char sollen Wörter ersetzt
> werden.
>
> Das funktioniert auch, nur dauert es verdächtig lange :-(
>
> Hat jemand eine Idee woran es liegen könnte?
>
> Hier der Code:
> -----------------------------------------------------------------------------------------------------
>
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
>
> char string[] = "Sehr_grosser_string_der_<item>und</
> item>sehr_oft_ca_30000_mal_enthaelt";
>
>
> // Copy the string in a new bigger string
> char *new_string;
> new_string = (char*) malloc(50000000 * sizeof(char));
>
> strcpy(new_string,string);
>
> char search[] = "item";
> char replace[1000];
>
> char *tempString;
> char *searchStart;
>
> int error = 0;
> int len = 0;
> int cnt = 1;
>
>
> // Check if substring could be found
> searchStart = strstr(new_string, search);
> if(searchStart != NULL) {
>
> // Allocate memmory
> tempString = (char*) malloc(50000000 * sizeof(char));
>
> if(tempString != NULL) {
>
> // Create a temporary copy of the string
> strcpy(tempString, new_string);
>
> // ersten Abschnitt in String setzen
> len = searchStart - new_string;
> new_string[len] = '\0';
>
> // zweiten Abschnitt anhaengen
> sprintf(replace,"item%d",cnt);
> strcat(new_string, replace);
>
> // dritten Abschnitt anhaengen
> len += strlen(search);
> strcat(new_string, (char*)tempString+len);

Um das auch noch mal ausdruecklich hier zu haben: Diese Form des
Umgangs mit sogenannten 'C strings' ist technisch nicht besonders
sinnvoll weil jedes strcat damit beginnt, den ersten String
zeichenweise zu durchsuchen um die abschliessende Null zu finden.
Nehmen wir mal beispielshalber an, der initiale string sei "A" und an
diesen sollen der Reihe nach die Strings "B", "C" und "D" angefuegt
werden.

1. strcat vergleicht 2 Zeichen und kopiert zwei: "AB"

2. strcat vergleicht 3 Zeichen und kopiert zwei: "ABC"

3. strcat vergleicht 4 Zeichen und kopiert zwei: "ABCD"

Das laeuft darauf hinaus, das fuer 'Suchen des Endes' ingesamt 2 + 3 +
4 Arbeitsschritte benoetigt werden bzw 2 + 3 + 4 + ... + n fuer n
Anfuegungen und das sind ((n * n + n) / 2) - 1 Arbeitsschritte
womit erklaert sein duerfte, warum das fuer lange Strings 'lange'
dauert.

Wiederholtes Ersetzen von Teilstrings in einem String hat sogar wenn
es sinnvoll implementiert ist, dasselbe Problem, weil fuer jede
Ersetzung ein 'Schwanzstring' kopiert werden muss, dh fuer die
Gesamtzahl der Arbeitsschritte bekommt man wiederum die Summe eine
Reihe, lediglich einer absteigenden. Hier waere eine Datenstruktur,
die diesen Vorgang ohne wiederholte String-Kopien ermoeglicht, also zB
eine verkettete Liste von 'Teilstrings' (zehn Zeichen von a, dann fuenf
Zeichen von b, dann fuenfzehn Zeichen von a + n usf) sehr angebracht.

Marcel Müller

unread,
Feb 26, 2012, 4:55:38 PM2/26/12
to
On 25.02.12 16.38, Thomas Mundt wrote:
> In einem sehr großer string> 10 Millionen char sollen Wörter ersetzt
> werden.
>
> Das funktioniert auch, nur dauert es verdächtig lange :-(
>
> Hat jemand eine Idee woran es liegen könnte?

10 MB am stück in einem String ist zum editieren/verändern gänzlich
ungeeignet. Einzelne Zeilen in einem String ist ebenfalls ungeeignet,
weil bei XML möglicherweise alles in einer Zeile steht.

Du suchst nach eine Rope-Implementierung. Damit geht das.

Alternativ: zerlege die Datei in beliebige Fragmente, die größer als
Suchstinglänge sind und berücksichtige, dass die Matches auch über
Fragmentgrenzen hinweg reichen können. Mit dieser Lösung ist auch
Stream-Processing möglich, d.h. es werden niemals alle Daten im Speicher
gehalten.

Noch eine Alternative: schreibe eine virtuelle String-Implementierung,
die selbst mit Fragmenten umgehen kann. Die Fragmente sind dann
abwechselnd die Stücken zwischen den Matches und die Replacement
strings. Die Inhalte dieser Fragmente werden nur referenziert, nicht
kopiert. Am Ende serialisiert Du dann diesen virtuellen String aus
seinen Fragmenten in eine Datei oder zu was auch immer. Selbst, wenn Du
danach im Speicher weiter arbeitest, kommst Du mit einem Kopiervorgang,
also O(n) aus, was keine wahrnehmbare Zeit verschlingen sollte.

Zum Vergleich: deine Lösung ist O(n²) und das ist bei 10 Mio. eine sehr
dumme Idee. Ein Geschwindigkeitsfaktor von ein paar Millionen ist also
noch zu holen.


Marcel

Rainer Weikusat

unread,
Feb 26, 2012, 5:14:05 PM2/26/12
to
Rainer Weikusat <rwei...@mssgmbh.com> writes:

[...]


> 1. strcat vergleicht 2 Zeichen und kopiert zwei: "AB"
>
> 2. strcat vergleicht 3 Zeichen und kopiert zwei: "ABC"
>
> 3. strcat vergleicht 4 Zeichen und kopiert zwei: "ABCD"
>
> Das laeuft darauf hinaus, das fuer 'Suchen des Endes' ingesamt 2 + 3 +
> 4 Arbeitsschritte benoetigt werden bzw 2 + 3 + 4 + ... + n fuer n
> Anfuegungen und das sind ((n * n + n) / 2) - 1 Arbeitsschritte
> womit erklaert sein duerfte, warum das fuer lange Strings 'lange'
> dauert.

Damit das nicht so falsch hier rumsteht: Fuer n Anfuegungen sind das
natuerlich 2 + 3 + ... + n + 1 Arbeitsschritte, also (Rechenfehler
vorbehalten :-) (n * n + 3n + 2) / 2.

Hermann Jurksch

unread,
Feb 26, 2012, 8:21:00 PM2/26/12
to
news.5...@spamgourmet.org wrote:

> On 25.02.12 16.38, Thomas Mundt wrote:
>> In einem sehr großer string> 10 Millionen char sollen Wörter ersetzt
>> werden.
>>
>> Das funktioniert auch, nur dauert es verdächtig lange :-(
>>
>> Hat jemand eine Idee woran es liegen könnte?

> 10 MB am stück in einem String ist zum editieren/verändern gänzlich
> ungeeignet.

Das hängt aber stark von der Art der Veränderungen ab. In seinem
Anwendungsfall geht das problemlos, wenn er den String in einem
hinreichend großen Array in der Form
Anfangsabschnitt|Lücke|Endabschnitt
unterbringt. Hier steht quasi der Textcursor am Anfang der Lücke.
Den Cursor um k Zeichen zu verschieben, ist O(k), k Zeichen einfügen
ist ebenfalls O(k). k Zeichen löschen ist O(1). Am Anfang steht der
gesamte Ausgangsstring im Endabschnitt, und der Anfangsabschnitt ist leer.
Jetzt muß er nur noch mit einem geeigneten Suchalgorithmus seine Wörter im
Endabschnitt finden, den Abschnitt vor einem Treffer in den
Anfangsabschnitt kopieren, den Treffer löschen und den Ersatztext
einfügen. Ist der Ersetzungsstring länger als der ersetzte, sollte man
den Speicherbedarf a priori ermitteln, indem man alle Vorkommen des zu
ersetzenden Strings zählt, wenn man ein realloc (z.B. mit Vergrößerung
um einen Faktor 2) vermeiden möchte. Insgesamt kommt hier O(n) für
Laufzeit und Speicherbedarf heraus, wenn n das Maximum der Längen von
Ausgangs- und Ergebnisstring ist. Weniger ist nur in Spezialfällen
möglich.

MfG
Hermann



Rainer Weikusat

unread,
Feb 27, 2012, 11:11:22 AM2/27/12
to
JUR...@elektron-bbs.de (Hermann Jurksch) writes:
> news.5...@spamgourmet.org wrote:
>> On 25.02.12 16.38, Thomas Mundt wrote:
>>> In einem sehr großer string> 10 Millionen char sollen Wörter ersetzt
>>> werden.
>>>
>>> Das funktioniert auch, nur dauert es verdächtig lange :-(
>>>
>>> Hat jemand eine Idee woran es liegen könnte?
>
>> 10 MB am stück in einem String ist zum editieren/verändern gänzlich
>> ungeeignet.
>
> Das hängt aber stark von der Art der Veränderungen ab. In seinem
> Anwendungsfall geht das problemlos, wenn er den String in einem
> hinreichend großen Array in der Form
> Anfangsabschnitt|Lücke|Endabschnitt
> unterbringt. Hier steht quasi der Textcursor am Anfang der Lücke.
> Den Cursor um k Zeichen zu verschieben, ist O(k), k Zeichen einfügen
> ist ebenfalls O(k). k Zeichen löschen ist O(1). Am Anfang steht der
> gesamte Ausgangsstring im Endabschnitt, und der Anfangsabschnitt ist leer.
> Jetzt muß er nur noch mit einem geeigneten Suchalgorithmus seine Wörter im
> Endabschnitt finden, den Abschnitt vor einem Treffer in den
> Anfangsabschnitt kopieren, den Treffer löschen und den Ersatztext
> einfügen.

Das ist technisch gesehen nichts anderes als aus Teilen das
Originalstrings und dem jeweiligen Ersatztext einen zweiten String in
einem neuen Puffer zu konstruieren, lediglich mit etwas bizarrerer
Speicherverwaltung und dem Nachteil, das man realloc nicht wirklich
sinnvoll zur Vergroesserung des zweiten Puffers benutzten kann, weil
das dann wieder O(n*n) wird. Falls man nicht 'aus religioesen/
weltanschaulichen Gruenden' an die 'Datenstruktur' 'zusammenhaengender
Speicherbereich der Laenge n' (n a priori unbekannt) gebunden ist,
kommt man mit einen 2-pass Algorithmus aus, wobei man im ersten
Schritt ermittelt, welche Stringabschnitte in welcher Reihenfolge
zusammengefuegt werden muessen und wie lang das Resultat sein wird und
den Resultatstring dann blind in einem Puffer der richtigen Groesse
zusammenfuegen falls man das moechte.

Bernd Nawothnig

unread,
Feb 28, 2012, 3:39:03 PM2/28/12
to
On 2012-02-25, Thomas Mundt wrote:
> In einem sehr großer string > 10 Millionen char sollen Wörter ersetzt
> werden.

Bist Du wirklich sicher, dass C hier die geeignetste Sprache ist?

Ich melde ernste Zweifel an.




Bernd

--
"Die Antisemiten vergeben es den Juden nicht, dass die Juden Geist
haben - und Geld." [Friedrich Nietzsche]
Message has been deleted

Rainer Weikusat

unread,
Mar 2, 2012, 12:35:11 PM3/2/12
to
Thomas Mundt <mundt_...@yahoo.de> writes:
> On 28 Feb., 21:39, Bernd Nawothnig <Bernd.Nawoth...@t-online.de>
> Da bleibt mir leider keine Wahl, da ich an C gebunden bin :-(
>
> Das langsame ist das Kopieren der Teilstrings in einen neuen String.

'Das langsame' ist die vollkommen hirnlose Weise, in der Du strcat
und strcpy benutzt. Das wurde allerdings schon mehrfach gepostet und
mehrere taugliche Alternativen wurden vorgeschlagen. Um das mal kurz
zu rekapitulieren:

1. Falls es moeglich ist, die Laenge des Zielstrings
ausreichend genau vorherzusagen, dass ein Zielpuffer im
vorraus via malloc angefordert werden kann, kannst Du
jedesmal, wenn der zu ersetzende String gefunden wurde, den
Abschnitt des Originalstrings der hinter dem letzten Vorkommen
des Suchstrings begann und sich bis zum naechsten Vorkommen
erstreckt an die aktuelle Zielposition im Zielpuffer kopieren,
danach den 'Zielcursor' entsprechend inkrementieren, den
Ersatzstring in den Zielpuffer kopieren, den Zielcursor wieder
vorwaertsbewegen und dann ab der Endposition des ersetzten
strings im Original die Suche nach dessen naechsten Vorkommen
neustarten. Das muss solange gemacht werden, bis die Suche
nichts mehr findet. Dann ist noch der Rest des Originalstrings
in den Zielpuffer zu kopieren und dieser Algorithmus hat eine
Laufzeit proportional zur Laenge des Resultstrings, dh er ist
O(n) und nicht (wie Deine bisherige Loesung) O(n*N).

2. Andernfalls kannst Du den Original-String einmal
durchlaufen, dabei eine Liste von String-Abschnitten, die im
Zielstring vorkommen sollen, erstellen und ausserdem dessen
Laenge berechnen. Insofern dieser in einem zusammenhaengenden
Speicherbereich stehen muss, kann danach ein Zielpuffer der
richtigen Groesse belegt werden und die String-Abschnitte
einer nach dem anderen in diesen Zielpuffer kopiert, wobei
wiederum ein Zielcursor zu benutzen waere, der jeweils hinter
den zuletzt kopierten Stringabschnitt im Zielpuffer zeigt.

Wartest Du jetzt darauf, dass sich dieser Sachverhalt von alleine
aendert?

Enrik Berkhan

unread,
Mar 2, 2012, 1:59:49 PM3/2/12
to
Thomas Mundt <mundt_...@yahoo.de> wrote:
> Da bleibt mir leider keine Wahl, da ich an C gebunden bin :-(
>
> Das langsame ist das Kopieren der Teilstrings in einen neuen String.
>
> Ich bin noch immer für jeden Tip dankbar.

Probier es mal so, ich hoffe es sind nicht allzu viele Fehler drin:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

const size_t max_chunk = 10 * 1024 * 1024;

char src[] = "Sehr_grosser_string_der_<item>un"
"d</item>sehr_oft_ca_30000_mal_enthaelt";
char match[] = "item";

char *resize(char *s, size_t *size, size_t *fre) {
if (*size < max_chunk) {
*fre += *size;
*size += *size;
} else {
*fre += max_chunk;
*size += max_chunk;
}
s = realloc(s, *size);
if (!s) {
perror("realloc");
exit(1);
}
return s;
}

int main(void) {
int cnt = 1;
size_t q = 0, len, fre, size = 1;
int m = strlen(match);
char *p, *n, *dst;

dst = malloc(size);
if (!dst) {
perror("malloc");
exit(1);
}
fre = size;
p = src;

while ((n = strstr(p, match))) {

len = n-p;

while (fre < len+100) /* assume max replacement len = 100! */
dst = resize(dst, &size, &fre);
memcpy(dst + q, p, n-p); q += len; fre -= len;
len = sprintf(dst + q, "item%d", cnt); q += len; fre -= len;

p = n+m;

cnt++;
}

while (fre < strlen(p)-1)
dst = resize(dst, &size, &fre);
strcpy(dst + q, p);

puts(dst);
return(0);
}

Rainer Weikusat

unread,
Mar 2, 2012, 2:22:25 PM3/2/12
to
Enrik Berkhan <Enrik....@inka.de> writes:

[...]

> const size_t max_chunk = 10 * 1024 * 1024;
>
> char src[] = "Sehr_grosser_string_der_<item>un"
> "d</item>sehr_oft_ca_30000_mal_enthaelt";
> char match[] = "item";
>
> char *resize(char *s, size_t *size, size_t *fre) {
> if (*size < max_chunk) {
> *fre += *size;
> *size += *size;
> } else {
> *fre += max_chunk;
> *size += max_chunk;
> }
> s = realloc(s, *size);

Allmaehlich sollte man mal darueber nachdenken 'C-Programmierer' als
'jemand, der deswegen Code mit quadratischem Laufzeitverhalten
schreibt weil er sich schlicht weigert, es besser zu machen' zu
definieren ...

Vinzent Hoefler

unread,
Mar 2, 2012, 2:40:36 PM3/2/12
to
Rainer Weikusat wrote:

> Allmaehlich sollte man mal darueber nachdenken 'C-Programmierer' als
> 'jemand, der deswegen Code mit quadratischem Laufzeitverhalten
> schreibt weil er sich schlicht weigert, es besser zu machen' zu
> definieren ...

Aber in C ist doch alles schneller. :-P


Vinzent.

--
The most likely way for the world to be destroyed, most experts agree,
is by accident. That's where we come in; we're computer professionals.
We cause accidents.
-- Nathaniel Borenstein

Bernd Hohmann

unread,
Mar 2, 2012, 3:01:33 PM3/2/12
to
Am 02.03.2012 16:42, schrieb Thomas Mundt:

> Das langsame ist das Kopieren der Teilstrings in einen neuen String.
> Ich bin noch immer für jeden Tip dankbar.

Ist der Ersatz von der Stringlänge her kleiner, gleich, grösser als der
Suchbegriff oder benötigst Du es Universell?

Ich kann Dir einen Ansatz liefern.

1) Für Ersatz.length = Such.length:
Suchen, überschreiben und ab der Fundstelle weitersuchen

2) Für Ersatz.length < Such.length:
Suchen, überschreiben, ab der Fundstelle weitersuchen und den Block
zwischen erster und zweiter Fundstelle nach vorne kopieren. Dann
weitersuchen und den Vorgang wiederholen. Wenn nicht mehr gefunden,
Stringende als Fundstelle betrachten, \0 an passender Stelle schreiben.

3) Für Ersatz.length > Such.length:
Scheiss Situation. Im Prinzip musst Du (2) anwenden, aber von hinten
nach vorne suchen und nach hinten verschieben. Das setzt aber voraus,
dass für den String bereits hinreichend Speicher alloziert wurde. Man
kann das jetzt so machen: Differenz "Ersatz-Such" bringen und mit der
wahrscheinlichen Anzahl von Fundstellen multiplizieren. Dann den String
in den so ermittelten Bereich reinkopieren und loslegen. Wenns
mittendrin nicht passt, nochmal grösser Allokieren, reinkopieren und
weitermachen.

Es gäbe noch einen anderen Ansatz: Man fischt sich erst die Fundstellen
via "findfirst/findnext" heraus und schreibt die in ein Array. Dann kann
man ausrechnen, wie gross der Zielstring sein muss und kopiert um.

Vorteil: Idiotensicher
Nachteil: Man muss das Array mit den Fundpointern entsprechend groß
anlegen damit wirklich alle reinpassen oder ein dynamisches Array
verwenden. Und man braucht mindestens nochmal den gleichen Platz im
Speicher wie er vom Ursprungsstring verwendet wird.

Bernd

Bernd Hohmann

unread,
Mar 2, 2012, 3:26:20 PM3/2/12
to
Am 02.03.2012 20:40, schrieb Vinzent Hoefler:

> Rainer Weikusat wrote:
>
>> Allmaehlich sollte man mal darueber nachdenken 'C-Programmierer' als
>> 'jemand, der deswegen Code mit quadratischem Laufzeitverhalten
>> schreibt weil er sich schlicht weigert, es besser zu machen' zu
>> definieren ...
>
> Aber in C ist doch alles schneller. :-P

Und in Java ist alles langsamer ;-)

Bernd




Georg Bauhaus

unread,
Mar 2, 2012, 4:22:21 PM3/2/12
to
On 02.03.12 21:01, Bernd Hohmann wrote:
> Am 02.03.2012 16:42, schrieb Thomas Mundt:
>
>> Das langsame ist das Kopieren der Teilstrings in einen neuen String.
>> Ich bin noch immer für jeden Tip dankbar.
>
> Ist der Ersatz von der Stringlänge her kleiner, gleich, grösser als der Suchbegriff oder benötigst Du es Universell?
>
> Ich kann Dir einen Ansatz liefern.

Wenn der Stolz OP nicht zwingt, 60 Jahre Informatik für ganz unbrauchbar
halten zu müssen, dann sollte sich in der Grabbelkiste für
die Lösung bekannter Probleme so etwas wie gsub finden lassen.
Nur am Rande vermerkt, falls der Zweck der Übung die Erfüllung einer
Sachaufgabe ist.

Bernd Hohmann

unread,
Mar 2, 2012, 4:46:32 PM3/2/12
to
Am 02.03.2012 22:22, schrieb Georg Bauhaus:
> On 02.03.12 21:01, Bernd Hohmann wrote:

>> Ich kann Dir einen Ansatz liefern.
>
> Wenn der Stolz OP nicht zwingt, 60 Jahre Informatik für ganz unbrauchbar
> halten zu müssen, dann sollte sich in der Grabbelkiste für
> die Lösung bekannter Probleme so etwas wie gsub finden lassen.

Ich bin ganz vorsichtig mit solchen Bemerkungen geworden weil das Schema
"Warum willst Du ein rundes Rad bauen - das 6eckige ist doch ganz
prima!" eben nicht gleichwertig zu "Warum willst Du das Rad neu
erfinden?" ist.

Bist Du auf Anhieb sicher, dass "gsub" die Aufgabe des OP besser löst
als seine Konstruktion?

Einfach mal nur so neutral gefragt.

Bernd

Georg Bauhaus

unread,
Mar 2, 2012, 5:25:31 PM3/2/12
to
On 02.03.12 22:46, Bernd Hohmann wrote:

> Bist Du auf Anhieb sicher, dass "gsub" die Aufgabe des OP besser löst als seine Konstruktion?

In diesem Fall scheint mir der Kommentar aus dem gegebenen Programm:

// Copy the string in a new bigger string

hinreichend für ein "ja" (riecht nach PC/Workstation mit ausreichend RAM)
und insofern passende gsubs zur verfügung stehen. Zum Beispiel solche, die
in O(f(n)), f(n) < n*n, fertig werden.

Die Frage nach einer Differenzierung von Rädern lässt mit dem Hinweis
begründen, dass wir alle sehr viel weniger zu zu tun hätten, wenn
man alles mit den gleichen Rädern ins Roolen bringen könnte ;-)
(Wenn zum Beispiel von einer µSteuerung mit 64kBytes RAM ein Zeichenstromg
verändert weiter gereicht werden soll, dann wird gsub, vermute ich, nicht
helfen und in einer solchen oder ähnlichen Situation würde ich auch von
systematischen Ansätzen wie Rainers oder Deinem ausgehen. Dann bleibt aber
immer noch, bekannte Verfahren nachzuschlagen, wie double buffers,
Wiederverwendung des Speichers eines Präfixes u.a.m. Aber hier?

Der Lerneffekt bei der Lösung der Aufgabe würde, vermute ich, ebenfalls
höher sein, wenn eine Erklärung von Wortersetzungsverfahren kosultiert wird.
Im thread sind ja welche.

Das Thema ist vergleichsweise alt, ich bin mal unter der Überschrift
"The Great Big Substitution Problem" drauf gestoßen. (Python's gsub
scheint jedenfalls rasend schnell zu sein.)

Jan Seiffert

unread,
Mar 2, 2012, 5:48:55 PM3/2/12
to
Jan Seiffert schrieb:
> Thomas Mundt schrieb:
>> In einem sehr großer string > 10 Millionen char sollen Wörter ersetzt
>> werden.
>>
>> Das funktioniert auch, nur dauert es verdächtig lange :-(
>>
>> Hat jemand eine Idee woran es liegen könnte?
>>
>
> [snip - code]
> Wenn ich das richtig verstehe kopierst du den ganzen string ständig im vollen
> hin und her, das ist schon unschön. Dann benutzt du die C string Funktionen noch
> in der echten Schlemier-der-Maler art-und-weise (siehe auch joelonsoftware).
>
> Hier mal ungetested wie ich das machen würde
>

Da ja anscheinend der Code nicht gesehen wurde, hier als full-quote, und als
Verbesserung obendrauf ein simpel match-count estimator...

> #include <stdlib.h>
> #include <stddef.h>
> #include <string.h>
> #include <stdio.h>
>
> static char *correct_len(char *a, size_t *len, size_t have, size_t need)
> {
> if(have < need)
> {
> size_t t = need - have;
> char *x;
> t += *len + 1;
> x = realloc(a, t);
> if(!x) {
> free(a);
> return NULL;
> }
> a = x;
> *len = t;
> }
> return a;
> }
>
> char *replace(const char *arg)
> {
static size_t char_per_match = 20;
> const char *m_start;
> char *ret, *match;
> size_t o_len, ro_len, r_len, r_start;
> int cnt = 1;
>
> o_len = strlen(arg) + 1;
>
ro_len = o_len + ((o_len + char_per_match - 1) / char_per_match) * 12;
> ret = malloc(ro_len);
> if(!ret)
> return NULL;
>
r_len = ro_len;
> r_start = 0;
> m_start = arg;
> while ((match = strstr(m_start, "item")))
> {
> size_t m_len = match - m_start;
>
> /* 12 char should be enough to print an int */
> if(!(ret = correct_len(ret, &ro_len, r_len, m_len + sizeof("item") + 12)))
> return NULL;
> memcpy(ret + r_start, m_start, m_len);
> r_start += m_len;
> r_len -= m_len;
> m_start += m_len + sizeof("item") - 1;
> m_len = sprintf(ret + r_start, "item%d", cnt++);
> r_start += m_len;
> r_len -= m_len;
> }
char_per_match = (char_per_match + (o_len / cnt)) / 2;
> o_len = strlen(m_start) + 1;
> if(!(ret = correct_len(ret, &ro_len, r_len, o_len)))
> return NULL;
> memcpy(ret + r_start, m_start, o_len);
> return ret;
> }
>
> Das kann man noch optimieren, z.B. je nach dem wieviel Speicher verschwended
> werden darf den neuen String viel grösser vor allozieieren.
> Auch sprintf ist nicht das schnellste.
> Man könnte strstr und das memcpy zusammmenfassen, strstr muss eh immer über den
> string und alle Buchstaben anfassen, da kann es sie gleich kopieren, und da der
> Suchstring fest vorgegeben ist ist das auch noch optimierungsfähig...
>

Der match-estimator ist nicht thread safe, falls das wichtig ist.

Gruss
Jan
Message has been deleted

Jan Seiffert

unread,
Mar 4, 2012, 11:14:02 AM3/4/12
to
Thomas Mundt schrieb:
> Was gibt's an Enriks Code auszusetzen?

Das er, so wie ich den Code verstehe, "zu oft" realloc aufruft...

> Funktioniert ohne Fehler und durchaus performant.
>

... was der Performance nicht zuträglich ist.

Oder er ruft realloc nicht so oft auf, aber der Codefluss ist irgendwie Bananne
(diese komische Logik mit max_chunk).
Und eben ein paar kleinigkeiten (das strcpy am ende, er hat die länge ja schon
mit strlen abgefragt, das strlen ist glaub ich auch falsch, das müsste am ende
strlen+1 sein, etc.)

Und ja, nebenbei die hybris das ich "meine Lösung" schon am 26.02 gesendet
hatte, 5 Tage vor Enrik, so das ich nur schliessen konnte das du sie nicht
gesehen hast als du am 2.3 immer noch auf der Suche nach Lösungen warst.

Nebenbei sind unsere Lösungen sehr Artverwandt.

> Gruß
> Thomas
>

Gruss
Jan

Rainer Weikusat

unread,
Mar 4, 2012, 2:04:23 PM3/4/12
to
Thomas Mundt <mundt_...@yahoo.de> writes:
> Was gibt's an Enriks Code auszusetzen?
> Funktioniert ohne Fehler und durchaus performant.

Das wurde Dir auch bereits erklaert. Verstehen wirst Du es aber wohl
nie.

Rainer Weikusat

unread,
Mar 4, 2012, 2:24:46 PM3/4/12
to
Jan Seiffert <inv...@example.invalid> writes:
> Thomas Mundt schrieb:
>> Was gibt's an Enriks Code auszusetzen?
>
> Das er, so wie ich den Code verstehe, "zu oft" realloc aufruft...

realloc kopiert den existierenden Speicherblock, falls eine in place
Vergroesserung nicht moeglich ist. Damit bekommt man fuer dei
Gesamtzahl der notwendigen Kopien fuer n realloc-Aufrufe mit
konstanter Speicherbereichsvergroesserung wieder n0 + n1 + n2 + ... + nn
und das ist immer noch O(n*n). Selbstverfreichlich lassen sich
praktische Probleme fuer jeden bekannten Fall dadurch vermeiden, dass
man 'geeignete Konstanten' benutzt. Allerdings ist das ungefaehr
dasselbe wie:

'Der Programmierer' (nehmen wir mal an sein Nachname reime sich auf
Grund) schreibt ein Programm, dass eine Eingabedatenzeile lesen
soll. In der ersten Version sieht das so aus:

int main(void)
{
char s[8];

gets(s);
return 0;
}

Test ergibt 'Programm funktionert', alles in Butter. Also geht das
jetzt kompiliert an 'den Benutzer'. Der beschwert sich allerdings,
dass es bei ihm immer abstuerzen wuerde. Anfaenglich buegelt 'der
Programmierer' (dessen Nachnahme sich auf 'Na und?' reimt) das mit dem
Hinweis ab, er koenne das nicht reproduzieren. Irgendwann spricht
sich dann zu ihm herum, dass die erste Zeile der ersten richtigen
Benutzereingabe so aussieht:

abcdefghijklmnopqrstuvwxyz

"Aha!" denkt sich 'der Programmierer' (dessen Nachname sich auf
'Schund' reimt) und verbessert sein Programm wie folgt:

int main (void)
{
char s[32];

gets(s);
return 0;
}

Test ergibt 'Programm funktioniert', alles in Butter. Also geht das
jetzt ... und nach einer Weile beschwert sich ein anderer Benutzer ...

.
.
.

und wenn sich nicht gestorben sind, dann drehen sie sich alle heute noch
im Kreis.

Rainer Weikusat

unread,
Mar 4, 2012, 2:29:53 PM3/4/12
to
Rainer Weikusat <rwei...@mssgmbh.com> writes:

[...]


> realloc kopiert den existierenden Speicherblock, falls eine in place
> Vergroesserung nicht moeglich ist. Damit bekommt man fuer dei
> Gesamtzahl der notwendigen Kopien fuer n realloc-Aufrufe mit
> konstanter Speicherbereichsvergroesserung wieder n0 + n1 + n2 + ... + nn
> und das ist immer noch O(n*n).

Hier sei der Fairness halber noch erwaehnt, dass der uebliche
Workaround dafuer von Hermann bereits erwaehnt wurde: Wenn man die
Groess des Speicherbereiches fuer jedes realloc verdoppelt bekommt man
lineares Laufzeitverhalten. Allerdings sollte man das meiner Ansicht
fuer 'Strings mit 10 Millionen Zeichen' lieber vermeiden, weil man
dann schon kraeftig Speicher verschwendet.

Ralf Damaschke

unread,
Mar 4, 2012, 4:03:28 PM3/4/12
to
Rainer Weikusat <rwei...@mssgmbh.com> wrote:

> 'Der Programmierer' (nehmen wir mal an sein Nachname reime sich auf
> Grund) schreibt ein Programm, dass eine Eingabedatenzeile lesen
> soll. In der ersten Version sieht das so aus:
>
> int main(void)
> {
> char s[8];
>
> gets(s);
> return 0;
> }

Ach was, Programmier-Projekte nur für C90? Bei C99 und C11
erzeugt dieses Programm schließlich einen Kompilier-Fehler. Wobei
sich dieser bei C99 durch ein "#include <stdio.h>" beheben lässt,
bei C11 aber nicht in dieser Weise.

-- Ralf

Rainer Weikusat

unread,
Mar 4, 2012, 4:16:07 PM3/4/12
to
Ralf Damaschke <rws...@gmx.de> writes:
> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>
>> 'Der Programmierer' (nehmen wir mal an sein Nachname reime sich auf
>> Grund) schreibt ein Programm, dass eine Eingabedatenzeile lesen
>> soll. In der ersten Version sieht das so aus:
>>
>> int main(void)
>> {
>> char s[8];
>>
>> gets(s);
>> return 0;
>> }
>
> Ach was, Programmier-Projekte nur für C90?

Koenntest Du mich vielleicht mal darueber aufklaeren, wieso Du den
groessten Teil meines Textes ohne Hinweis darauf entfernt hast und zu
diesem Bruchstueck, dessen intendierte Bedeutung nicht mehr verstehbar
ist, diesen vollkommen sinnlosen Kommentar gepostet hast?

Ralf Damaschke

unread,
Mar 5, 2012, 4:43:43 PM3/5/12
to
Rainer Weikusat <rwei...@mssgmbh.com> wrote:

> Ralf Damaschke <rws...@gmx.de> writes:
>> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>>
>>> 'Der Programmierer' (nehmen wir mal an sein Nachname reime
>>> sich auf Grund) schreibt ein Programm, dass eine
>>> Eingabedatenzeile lesen soll. In der ersten Version sieht das
>>> so aus:
>>>
>>> int main(void)
>>> {
>>> char s[8];
>>>
>>> gets(s);
>>> return 0;
>>> }
>>
>> Ach was, Programmier-Projekte nur für C90?
>
> Koenntest Du mich vielleicht mal darueber aufklaeren, wieso Du
> den groessten Teil meines Textes ohne Hinweis darauf entfernt
> hast

Gerne: weil der Rest für meinen Kommentar irrelevant ist.

> und zu diesem Bruchstueck, dessen intendierte Bedeutung
> nicht mehr verstehbar ist,

Du meinst, Dein Gesamttext hatte eine Bedeutung (mal außer der
Äußerung von Befindlichkeiten)?

> diesen vollkommen sinnlosen Kommentar
> gepostet hast?

Ach was. Jeder halbwegs erfahrene C-Programmierer sieht sofort,
dass das Programm Deines hypothetischen Programmierers unter
einer halbwegs modernen C-Implementierung nicht übersetzbar wäre
und somit gar nicht erst beim Kunden landen könnte.

-- Ralf

Bernd Hohmann

unread,
Mar 5, 2012, 4:48:37 PM3/5/12
to
Am 05.03.2012 22:43, schrieb Ralf Damaschke:

> Ach was. Jeder halbwegs erfahrene C-Programmierer sieht sofort,
> dass das Programm Deines hypothetischen Programmierers unter
> einer halbwegs modernen C-Implementierung nicht �bersetzbar w�re
> und somit gar nicht erst beim Kunden landen k�nnte.

Du hast einfach keinen Humor - selbst ich als "C Outsider" hab den Witz
verstanden.

Bernd


Rainer Weikusat

unread,
Mar 5, 2012, 4:58:07 PM3/5/12
to
Ralf Damaschke <rws...@gmx.de> writes:
> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>
>> Ralf Damaschke <rws...@gmx.de> writes:
>>> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>>>
>>>> 'Der Programmierer' (nehmen wir mal an sein Nachname reime
>>>> sich auf Grund) schreibt ein Programm, dass eine
>>>> Eingabedatenzeile lesen soll. In der ersten Version sieht das
>>>> so aus:
>>>>
>>>> int main(void)
>>>> {
>>>> char s[8];
>>>>
>>>> gets(s);
>>>> return 0;
>>>> }
>>>
>>> Ach was, Programmier-Projekte nur für C90?
>>
>> Koenntest Du mich vielleicht mal darueber aufklaeren, wieso Du
>> den groessten Teil meines Textes ohne Hinweis darauf entfernt
>> hast
>
> Gerne: weil der Rest für meinen Kommentar irrelevant ist.

In anderen Worten, weil ich den Aufhaenger, den Du zwecks Anbringung
Deines (immer noch vollkommen sinnlosen) Kommentars gerne gehabt
haettest, nun mal nicht geschrieben habe, hast Du Dir erlaubt, Dir
etwas passendes zurechzufaelschen.

>> und zu diesem Bruchstueck, dessen intendierte Bedeutung
>> nicht mehr verstehbar ist,
>
> Du meinst, Dein Gesamttext hatte eine Bedeutung (mal außer der
> Äußerung von Befindlichkeiten)?

In der Tat meine ich das. Speziell ging es um das Verfahren, einen
grundlegend kaputten Ansatz zur Loesung eines Problems dadurch zu
kaschieren, dass man im Falle von konkreten Problemen ein paar
Parameter so aendert, dass diese konkreten Problem nicht auftreten.
Also zB einen statischen Puffer, in dem man Eingaben von von
vorneherein unbekannter Laenge speichert, um einen geeigneten Betrag
vergroessert, wann immer die momentan benutzte Laenge zu klein war
oder eben, in dem man einen O(n*n)-Algorithmus dadurch 'verbessert',
dass man 'heuristisch' fuer kleine n sorgt.

Mit 'meinen Befindlichkeiten' hat das eher nichts zu tun.

>
>> diesen vollkommen sinnlosen Kommentar
>> gepostet hast?
>
> Ach was. Jeder halbwegs erfahrene C-Programmierer sieht sofort,
> dass das Programm Deines hypothetischen Programmierers unter
> einer halbwegs modernen C-Implementierung nicht übersetzbar wäre

Eventuell moechtest Du mal den Deutschlehrer, den Du seit der zehnten
Klasse nicht mehr gesehen hast, ausfindig machen, und ein paar
Informationen ueber Eigenschaften bestimmter literarischer Gattungen
einholen ...

Jan Seiffert

unread,
Mar 6, 2012, 2:44:34 PM3/6/12
to
Bernd Hohmann schrieb:
> Am 02.03.2012 16:42, schrieb Thomas Mundt:
>
>> Das langsame ist das Kopieren der Teilstrings in einen neuen String.
>> Ich bin noch immer für jeden Tip dankbar.
>
[snip]
>
> Es gäbe noch einen anderen Ansatz: Man fischt sich erst die Fundstellen via
> "findfirst/findnext" heraus und schreibt die in ein Array. Dann kann man
> ausrechnen, wie gross der Zielstring sein muss und kopiert um.
>
> Vorteil: Idiotensicher
> Nachteil: Man muss das Array mit den Fundpointern entsprechend groß anlegen
> damit wirklich alle reinpassen oder ein dynamisches Array verwenden. Und man
> braucht mindestens nochmal den gleichen Platz im Speicher wie er vom
> Ursprungsstring verwendet wird.
>

Ich lass das mal hier....
Macht nur ein alloc der richtigen Grösse. Braucht aber stack, hier z.b 64byte
pro match. Getested mit 3,8MiB Text, bei ca. 80.000 Ersetzungen, braucht das so
5MiB stack, und ist in 24 Millionen Instruktionen durch. Das teuerste ist strstr
mit 10M, dann das put_dec mit 4M.
(man kann in ilog2 noch die passende Maschineninstruktion einsetzen und put_dec
geht auch noch schneller)

#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>

#define SEARCH_STR "obj"

static unsigned int ilog2(unsigned int v)
{
register unsigned int r;
register unsigned int shift;
r = (v > 0xFFFF) << 4; v >>= r;
shift = (v > 0xFF ) << 3; v >>= shift; r |= shift;
shift = (v > 0xF ) << 2; v >>= shift; r |= shift;
shift = (v > 0x3 ) << 1; v >>= shift; r |= shift;
r |= (v >> 1);
return r;
}

static unsigned int ilog10(unsigned int v)
{
static unsigned int const pof10[] = {
1, 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000, 1000000000
};
int r, t;
t = (ilog2(v) + 1) * 1233 >> 12;
r = t - (v < pof10[t]);
return r;
}

static void put_dec(char *s, unsigned int n)
{
do {
*--s = (n % 10) + '0';
} while(n /= 10);
}

static char *rr(const char *arg, size_t start, unsigned int cnt)
{
const char *match = strstr(arg, SEARCH_STR);
char *res;
size_t t, l;

if (match) {
match += sizeof(SEARCH_STR) - 1;
t = match - arg;
l = ilog10(cnt) + 1;
res = rr(match, start + t + l, cnt + 1);
if (res)
put_dec(memcpy(res + start, arg, t) + t + l, cnt);
} else {
t = strlen(arg) + 1;
res = malloc(start + t);
if(res)
memcpy(res + start, arg, t);
}
return res;
}

char *replace(const char *arg)
{
return rr(arg, 0, 1);
}

> Bernd
>

Gruss
Jan

Ralf Damaschke

unread,
Mar 6, 2012, 6:40:10 PM3/6/12
to
Rainer Weikusat <rwei...@mssgmbh.com> wrote:

> Ralf Damaschke <rws...@gmx.de> writes:
>> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>>
>>> Ralf Damaschke <rws...@gmx.de> writes:
>>>> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>>> Koenntest Du mich vielleicht mal darueber aufklaeren, wieso Du
>>> den groessten Teil meines Textes ohne Hinweis darauf entfernt
>>> hast
>>
>> Gerne: weil der Rest für meinen Kommentar irrelevant ist.
>
> In anderen Worten, weil ich den Aufhaenger, den Du zwecks
> Anbringung Deines (immer noch vollkommen sinnlosen) Kommentars
> gerne gehabt haettest, nun mal nicht geschrieben habe, hast Du
> Dir erlaubt, Dir etwas passendes zurechzufaelschen.

Häh? Ich habe gar nichts gefälscht, das bildest Du Dir nur ein.

> Eventuell moechtest Du mal den Deutschlehrer, den Du seit der
> zehnten Klasse nicht mehr gesehen hast, ausfindig machen, und
> ein paar Informationen ueber Eigenschaften bestimmter
> literarischer Gattungen einholen ...

Auf dieses Niveau lasse ich micht nicht herunterziehen.

-- Ralf

Bernd Hohmann

unread,
Mar 7, 2012, 5:52:39 AM3/7/12
to
Am 06.03.2012 20:44, schrieb Jan Seiffert:

> Macht nur ein alloc der richtigen Grösse. Braucht aber stack, hier z.b 64byte
> pro match. Getested mit 3,8MiB Text, bei ca. 80.000 Ersetzungen, braucht das so
> 5MiB stack, und ist in 24 Millionen Instruktionen durch. Das teuerste ist strstr
> mit 10M, dann das put_dec mit 4M.

Bin nicht so der C Runtime-Experte, aber wenn ich das richtig verstehe
läufst Du hier:

> const char *match = strstr(arg, SEARCH_STR);

jedesmal von Anfang an durch den kompletten String. Da würde ich mir
jetzt eine strstrx(int begin, char *in, char *str) bauen.

Bernd

Jan Seiffert

unread,
Mar 7, 2012, 8:15:08 AM3/7/12
to
Bernd Hohmann schrieb:
Nein ;)
Schau noch mal genau hin.
Das ruft sich rekursiv selbst auf, jedes mal mit dem Stringpointer hinter den
letzten match verschoben. (oder beim start mit dem Pointer auf den Start des
string). Er sucht also von match zu match.
Das rekursiv aufrufen hat halt den Nachteil das es ein stackframe pro match
braucht...

> Bernd
>

Gruss
Jan

Bernd Hohmann

unread,
Mar 7, 2012, 10:15:28 AM3/7/12
to
Am 07.03.2012 14:15, schrieb Jan Seiffert:
> Bernd Hohmann schrieb:

> Nein ;)
> Schau noch mal genau hin.
> Das ruft sich rekursiv selbst auf, jedes mal mit dem Stringpointer hinter den
> letzten match verschoben.

Stimmt, "arg" ist ja nur ein Pointer.

Bernd

Holger Suhr

unread,
Mar 12, 2012, 5:55:59 AM3/12/12
to
Am 25.02.2012 16:38, schrieb Thomas Mundt:
> In einem sehr großer string> 10 Millionen char sollen Wörter ersetzt
> werden.
>
> Das funktioniert auch, nur dauert es verdächtig lange :-(
>
> Hat jemand eine Idee woran es liegen könnte?
>

Ich habs nun auch nochmal probiert...
Ohne realloc.
In 18MB Sourcecode 36375 "int" durch "WILLI" ersetzt.
real 0m0.125s
user 0m0.080s
sys 0m0.040s

-----------------------------------------------------------------

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
int ls,le,n,cnt;
char *dest,*src;
char *p,*sp,*dp,*esrc;
char *such="int";
char *ers="WILLI";

src=malloc(20000000);
// zum Test.. lesen von stdin
read(0,src,20000000);

ls=strlen(such);
le=strlen(ers);

for(esrc=src;*esrc;esrc++);

for(cnt=0,p=src;p<esrc && (p=strstr(p,such));p+=ls,cnt++);
n=esrc-src+cnt*(le-ls);

dest=malloc(n);
sp=src;
dp=dest;

for(p=src;p<esrc && (p=strstr(p,such));sp=(p+=ls)) {
n=p-sp;
memcpy(dp,sp,n);
dp+=n;
memcpy(dp,ers,le);
dp+=le;
}
n=esrc-sp;
memcpy(dp,sp,n);
dp+=n;
*dp='\0';

// zum Test.. Ergbnis auf stdout
write(1,dest,dp-dest);

return(0);
}

Gruß
Holger

Helmut Schellong

unread,
Jun 7, 2012, 5:45:41 AM6/7/12
to
Vinzent Hoefler wrote:
> Rainer Weikusat wrote:
>
>> Allmaehlich sollte man mal darueber nachdenken 'C-Programmierer' als
>> 'jemand, der deswegen Code mit quadratischem Laufzeitverhalten
>> schreibt weil er sich schlicht weigert, es besser zu machen' zu
>> definieren ...
>
> Aber in C ist doch alles schneller. :-P

Das stimmt sogar.
Ich stellte mal fest, daß eine bestimmte Aufgabe
in COBOL etwa 80-mal länger dauerte als in C.
Das galt auch bei Variation dieser einen Aufgabe.
C war hier auch vielfach schneller als PASCAL.
Man bedenke den wirtschaftlichen Schaden, der durch
COBOL entstand/entsteht, auch wenn man ihn bereinigt.

Jedoch noch viel größere Geschwindigkeitsgewinne
sind durch Verbesserung des Algorithmus zu erreichen.
Ich hatte mal mit einer Software gearbeitet, die für eine
bestimmte Aufgabe einige Minuten Zeit benötigte.
Ich wollte das nicht einsehen, daß der Vorgang so lange
dauern (muß) und programmierte selbst.
Meine Lösung benötigte nur einige Millisekunden, war
also etwa 60000-fach schneller.

Bei diesem String_Replace ist das ähnlich.
Das am häufigsten vorkommende Manko ist, daß ein
Programmierer Probleme hat, ein gutes bis optimales
Lösungskonzept (Algorithmus) zu (er)finden.



--
Mit freundlichen Grüßen
Helmut Schellong v...@schellong.biz
www.schellong.de www.schellong.com www.schellong.biz
http://www.schellong.de/c.htm

Helmut Schellong

unread,
Jun 7, 2012, 5:54:47 AM6/7/12
to
Thomas Mundt wrote:
> Was gibt's an Enriks Code auszusetzen?
> Funktioniert ohne Fehler und durchaus performant.
>
> Gruß
> Thomas

Deine Problemstellung müßte beim Run auf einem einigermaßen
aktuellen PC weniger als eine Millisekunde brauchen.
Dann wäre es wirklich performant.

Claus Reibenstein

unread,
Jun 7, 2012, 9:21:24 AM6/7/12
to
Helmut Schellong schrieb:

> Thomas Mundt wrote:

Vor ueber drei Monaten. Meinst Du wirklich, dass das Thema noch relevant
ist?

Gruss aus dem sonnigen Brisbane (QLD)
Claus

Claus Reibenstein

unread,
Jun 7, 2012, 9:23:08 AM6/7/12
to
Helmut Schellong schrieb:

> Vinzent Hoefler wrote:

Und auch das ist schon ueber 3 Monate her.

Helmut Schellong

unread,
Jun 8, 2012, 6:24:46 AM6/8/12
to
Ich habe nur einen neuen news-Server ausprobiert, nachdem T-Online
ihren für Normalkunden nicht mehr zur Verfügung stellt.

Vinzent Hoefler

unread,
Jun 8, 2012, 7:54:24 AM6/8/12
to
Helmut Schellong wrote:

> Claus Reibenstein wrote:
>> Helmut Schellong schrieb:
>>
>>> Vinzent Hoefler wrote:
>>
>> Und auch das ist schon ueber 3 Monate her.
>>
>> Gruss aus dem sonnigen Brisbane (QLD)
>> Claus
>
> Ich habe nur einen neuen news-Server ausprobiert, nachdem T-Online
> ihren für Normalkunden nicht mehr zur Verfügung stellt.

Und das wiederum ist schon über ein Jahr her. :D


Vinzent.

--
The most likely way for the world to be destroyed, most experts agree,
is by accident. That's where we come in; we're computer professionals.
We cause accidents.
-- Nathaniel Borenstein

Helmut Schellong

unread,
Jun 8, 2012, 10:01:11 AM6/8/12
to
Vinzent Hoefler wrote:
> Helmut Schellong wrote:
>
>> Claus Reibenstein wrote:
>>> Helmut Schellong schrieb:
>>>
>>>> Vinzent Hoefler wrote:
>>>
>>> Und auch das ist schon ueber 3 Monate her.
>>>
>>> Gruss aus dem sonnigen Brisbane (QLD)
>>> Claus
>>
>> Ich habe nur einen neuen news-Server ausprobiert, nachdem T-Online
>> ihren für Normalkunden nicht mehr zur Verfügung stellt.
>
> Und das wiederum ist schon über ein Jahr her. :D

Genau. Und daran kann man ermessen, welch kolossale Bedeutung
dieser Ausprobiervorgang für mich hat.

Claus Reibenstein

unread,
Jun 8, 2012, 10:50:59 AM6/8/12
to
Helmut Schellong schrieb:

> Ich habe nur einen neuen news-Server ausprobiert

de.test kennst Du?

Gruss aus dem sonnige Brisbane (QLD)
Claus

Stefan Reuther

unread,
Jun 8, 2012, 12:10:44 PM6/8/12
to
Vinzent Hoefler wrote:
> Helmut Schellong wrote:
>> Claus Reibenstein wrote:
>>> Helmut Schellong schrieb:
>>>> Vinzent Hoefler wrote:
>>>
>>> Und auch das ist schon ueber 3 Monate her.
>>
>> Ich habe nur einen neuen news-Server ausprobiert, nachdem T-Online
>> ihren für Normalkunden nicht mehr zur Verfügung stellt.
>
> Und das wiederum ist schon über ein Jahr her. :D

Usenet ist *kein* Echtzeitmedium.


Stefan

Helmut Schellong

unread,
Jun 8, 2012, 2:37:30 PM6/8/12
to
Claus Reibenstein wrote:
> Helmut Schellong schrieb:
>
>> Ich habe nur einen neuen news-Server ausprobiert
>
> de.test kennst Du?

Jene Gruppe bedeutet mir nichts.
Es war mir wichtig, daß diejenigen Gruppen konkret funktionieren,
wo ich öfter mal Leute schön ärgern kann.

Claus Reibenstein

unread,
Jun 8, 2012, 9:10:20 PM6/8/12
to
Stefan Reuther schrieb:
Trotzdem bleibt die Frage, ob der Thread noch relevant ist. 3 Monate
sind 3 Monate, und selbst der langsamste Newsserver duerfte deutlich
weniger Zeit zur Synchronisation brauchen.

Claus Reibenstein

unread,
Jun 8, 2012, 9:15:55 PM6/8/12
to
Helmut Schellong schrieb:

> Claus Reibenstein wrote:
>
>> Helmut Schellong schrieb:
>>
>>> Ich habe nur einen neuen news-Server ausprobiert
>>
>> de.test kennst Du?
>
> Jene Gruppe bedeutet mir nichts.

Sie ist fuer Testzwecke da. Wenn Du Deinen Server testen willst, ist
diese Gruppe genau die richtige.

> Es war mir wichtig, daß diejenigen Gruppen konkret funktionieren,
> wo ich öfter mal Leute schön ärgern kann.

Gruppen "funktionieren" nicht. Newsserver funktionieren. Genau das
kannst Du mit de.test wunderbar testen.

Die anderen Gruppen sind keine Testgruppen und sollten dafuer auch nicht
missbraucht werden. Schon gar nicht von Dir.

Du moegest Dich bitte mit den Gepflogenheiten des Usenet auseinandersetzen!

Helmut Schellong

unread,
Jun 9, 2012, 1:01:28 AM6/9/12
to
Claus Reibenstein wrote:
> Helmut Schellong schrieb:
>
>> Claus Reibenstein wrote:
>>
>>> Helmut Schellong schrieb:
>>>
>>>> Ich habe nur einen neuen news-Server ausprobiert
>>>
>>> de.test kennst Du?
>>
>> Jene Gruppe bedeutet mir nichts.
>
> Sie ist fuer Testzwecke da. Wenn Du Deinen Server testen willst, ist
> diese Gruppe genau die richtige.
>
>> Es war mir wichtig, daß diejenigen Gruppen konkret funktionieren,
>> wo ich öfter mal Leute schön ärgern kann.
>
> Gruppen "funktionieren" nicht. Newsserver funktionieren. Genau das
> kannst Du mit de.test wunderbar testen.

Wenn es gelingt. in de.test eine Nachricht abzusetzen, so ist das
kein Beweis, daß dies in dclc auch gelingen wird.
Es ist lediglich wahrscheinlich, das dies dann in dclc gelingen wird.

> Die anderen Gruppen sind keine Testgruppen und sollten dafuer auch nicht
> missbraucht werden. Schon gar nicht von Dir.
>
> Du moegest Dich bitte mit den Gepflogenheiten des Usenet auseinandersetzen!

Das habe ich schon viele Jahre länger als Du.
Ich war schon hier, da warst Du ...

Claus Reibenstein

unread,
Jun 9, 2012, 7:09:04 AM6/9/12
to
Helmut Schellong schrieb:

> Claus Reibenstein wrote:
>
>> Gruppen "funktionieren" nicht. Newsserver funktionieren. Genau das
>> kannst Du mit de.test wunderbar testen.
>
> Wenn es gelingt. in de.test eine Nachricht abzusetzen, so ist das
> kein Beweis, daß dies in dclc auch gelingen wird.

Wenn de.test funktioniert, funktionieren auch alle anderen Gruppen, die
der Newsserver fuehrt. Du musst also nur noch schauen, ob auch die
Gruppen dabei sind, die Du haben moechtest.

Wenn jeder, der einen Newsserver testet, in jeder Gruppe, die er
darueber beziehen moechte, eine Testnachricht absetzen wuerde ...

>> Du moegest Dich bitte mit den Gepflogenheiten des Usenet auseinandersetzen!
>
> Das habe ich schon viele Jahre länger als Du.
> Ich war schon hier, da warst Du ...

Was zu beweisen waere.

Vinzent Hoefler

unread,
Jun 9, 2012, 4:37:45 PM6/9/12
to
Wieso? Helmut hat doch echt Zeit[1] gebraucht, festzustellen, daß sein
Newsserver kaputt ist. :P


Vinzent.

[1] FdI#463.

Helmut Schellong

unread,
Jun 9, 2012, 11:38:08 PM6/9/12
to
Vinzent Hoefler wrote:
> Stefan Reuther wrote:
>
>> Vinzent Hoefler wrote:
>>> Helmut Schellong wrote:
>>>> Claus Reibenstein wrote:
>>>>> Helmut Schellong schrieb:
>>>>>> Vinzent Hoefler wrote:
>>>>>
>>>>> Und auch das ist schon ueber 3 Monate her.
>>>>
>>>> Ich habe nur einen neuen news-Server ausprobiert, nachdem T-Online
>>>> ihren für Normalkunden nicht mehr zur Verfügung stellt.
>>>
>>> Und das wiederum ist schon über ein Jahr her. :D
>>
>> Usenet ist *kein* Echtzeitmedium.
>
> Wieso? Helmut hat doch echt Zeit[1] gebraucht, festzustellen, daß sein
> Newsserver kaputt ist. :P

So ist die Sache nun doch nicht abgelaufen.

Ich hatte das mit news.t-online.de in zwei Wochen bemerkt.
Daraufhin habe ich news1.dtag.de eingesetzt, was funktionierte.
Der ging dann nach einer Weile auch weg.
Und dann hatte ich Newsgroups für lange Zeit ad acta gelegt.

Aber jetzt habe ich mich mal, weil ich vier Tage arbeitsfrei hatte, um
einen Newsserver gekümmert, der außerhalb der Telekom liegt
und kostenlos ist: news.solani.org
0 new messages