Dateien einlesen und vergleichen
-
Zum Beispiel mit diesen 2 Funktionen (kann man auch leicht selber schreiben, in dem man das Problem in seine Bestandteile zerlegt und diese Teilprobleme einzeln löst.)
void substr(char * in, char * lowout,char search) { // Teile den String in zwei Teile an der ersten Stelle search und vergiss das Zeichen an der Bruchstelle char *highout; highout=in; while ( ( search != * in ) && ( * in ) ) *lowout++ = *in++; *lowout=0; if (0 != *in)in++; while ( * in ) *highout++= *in++; *highout=0; return; } void StrRmLe(char *s) { // Entferne alle führenden whitespace characters aus einem String int i; int count=0; int len=strlen(s); for (i=0;i<len;i++) { if ( 0 == isspace(s[i])) break; else count++; } if (count > 0) for (i=0;i<len-count+1;i++) s[i]=s[i+count]; return; }
Benutzung:
char *input="1 A_ID=4543"; char part1[80+1]; char part2[80+1]; substr(input,part1,' '); // => in part1 steht "1" in input jetzt " A_ID=4543" StrRmLe(input); // => in input steht jetzt "A_ID=4543" substr(input,part2,'='); // => in part2 steht "A_ID" in input jetzt "4543"
Somit hast du deine 3 Teile und kannst die anderen Aktione durchführen.
PS: falls einer für StrRmLe eine bessere Implementierung weis, ich bin neugierig?
-
int substr(char *quelle, char *ziel, char suche) { char *pos; //Zeichen suchen pos = strchr(quelle, suche); //Zeichen gefunden? if(pos) { //gefundenes Zeichen überschreiben *pos++ = 0; //alles nach dem gefundenen Zeichen kopieren strcpy(ziel, pos); return(0); //Alles OK } else { return(-1); //Suchzeichen nicht gefunden! } }
Bei der zweiten Funktion sollte man anstatt der Schleife zum Kopieren die Funktion strcpy() verwenden oder memcpy() (wenn einem das lieber ist).
-
habe beide codes (von PAD & AJ) mal ausprobiert und habe festgestellt, dass sie sich beide zwar compilieren lassen, jedoch aber beim ausführen einen speicherfehler aufweisen. woran könnte das noch liegen? der debugger hilft mir in diesem fall nicht wirklich weiter.
-
AJ schrieb:
... //gefundenes Zeichen überschreiben *pos++ = 0; ...
genau an der Stelle verabschiedet sich der Debugger... bis dahin funtz es noch. woran könnte das liegen
-
Zeig mal den Aufruf und was du sonst noch mit den verwendeten Strings machst. Ich hoffe du hast nicht die Funktionen einfach mit einem festen String aufgerufen. (z. B. substr("Test=Wert", wert, '=') da der 1. Parameter in der Funktion auch verändert wird, gibt es hier einen Speicherfehler!)
-
char *input="1 A_ID=4543"; char part1[80+1]; char part2[80+1]; sub(input,part1,' '); // => in part1 steht "1" in input jetzt " A_ID=4543" //StrRmLe(input); // => in input steht jetzt "A_ID=4543" //sub(input,part2,'='); // => in part2 steht "A_ID" in input jetzt "4543"
... so rufe ich die Funktion auf
-
natürlich habe ich die funktion von substr in sub umbenannt.
es könnte allerdings auch an:char *input="1 A_ID=4543";
... liegen, vielleicht muss ich das * weglassen und dafür ein vordefiniertes Array nehmen???
-
Korrekt!
Der String ist konstant -> konstant != variabel -> also nicht änderbar
-
Funktion funktioniert zwar, aber nicht richtig. Man beachte beim Orginal verbleibt das Ende des Strings in ersten Parameter, bei der neuen verbleibt dies im zweiten Parameter.
Die Funktion scheint aber schneller zu sein.
Korrektur:
Begin test1 Orginal-Funktion
End test1: 0.256421 Sekunden
Begin test2 Neue Lösung
End test2: 0.332843 Sekunden
Begin test3 Leere Schleife
End test3: 0.070380 Sekunden#define NUM 1000000 void test3(void) {int i; char Peter[129]; char Peter1[129]; APPLTraceB(APPLV1,"test3") for (i=0;i<NUM;i++) { strcpy(Peter,"Dies ist ein Test,hier der zweite Teil"); _substr_(Peter,Peter1,','); //substr, substr_ } APPLTraceE(APPLV1,"test3") }
Eine lösung für die zweite wäre noch viel interessanter!
-
@PAD
Darum ist die "neue" auch schneller, weil nur 1 mal rumkopiert wird (könnte man sich übrigens auch sparen, wenn man es etwas anders verarbeitet -> noch schneller).Die zweite würde ich so lösen:
char *entfWSC(char *text) { char *pos; for(pos = text; *pos && isspace(*pos); ++pos); //kann man sich leider nicht ersparen ;) if(pos != text) strcpy(text, pos); return(text); }
-
Ich musste leider meine Aussage korrigieren die Orginal-Implementierung ist bei mir schneller.
Ergebnisse in Sekunden
Start of applikation part
Begin test1
End test1: 0.256003 Orginal
Begin test2
End test2: 0.329853 Neue Implementierung
Begin test3
End test3: 0.072492 Leer Schleife
Begin test4
End test4: 0.453790 entfWSC
Begin test5
End test5: 0.577858 StrRmLe
End of applikation part
ReturnCode: 0
System ShutdownDas lohnt sich
-
Wie oft hast du es denn probiert?
Möglicherweise bremst strcpy() das ganze etwas aus. Ich wäre aber eigentlich davon ausgegangen, dass es auch nicht viel mehr macht als deine Kopierschleife.
-
Das Testprogramm hat so um die 100 Läufe mit vergleichbaren Ergebnissen unter Win2000 gebracht.
Insgesamt habe ich diese 5 Testfunktionen jede 1 000 000 Mal aufgerufen in MSVC 6.0 release version speed optimiert.Die Funktion test3 sieht wie folgt aus und dient dazu den Overhead zu bestimmen.
Als Timer wird der HIGH-Performance Timer benutztint dummi(char *quelle, char *ziel, char suche) { return 0; } void test3(void) { int i; char Peter[129]; char Peter1[129]; APPLTraceB(APPLV1,"test3") for (i=0;i<NUM;i++) { strcpy(Peter,"Dies ist ein Test,hier der zweite Teil"); dummi(Peter,Peter1,','); } APPLTraceE(APPLV1,"test3") }
-
ich muss aber leider zu geben, dass der Code, bzw. die Funktionen von PAD wesentlich besser funktionieren. Wenn ich bei AJ's Code mir die einzelnen Teile ausgeben lasse, dann bekomme ich nur so ein Schmarn hier:
input : 1 A_ID=166 part1 : ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ 1 A_ID=166 part2 : ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
bei dem Code von PAD klappt es wunderbar (sprich: input wird genau in diese Teile zerlegt), der ist aber schwerer zu verstehen finde ich... Woran könnte das wohl liegen?
Und was ist eigentlich das hier? Da verstehe ich ja nur Bahnhof:#define NUM 1000000 void test3(void) {int i; char Peter[129]; char Peter1[129]; APPLTraceB(APPLV1,"test3") for (i=0;i<NUM;i++) { strcpy(Peter,"Dies ist ein Test,hier der zweite Teil"); _substr_(Peter,Peter1,','); //substr, substr_ } APPLTraceE(APPLV1,"test3") }
Hat das auch irgendwas mit meiner Frage zu tun? Würde mich über einige Kommentare mehr freuen. Danke
-
@Jerry
Wie ist denn der Aufruf bei meiner Funktion und die Ausgabe?
-
So rufe ich deine Funktion auf:
char input[MAX_LEN]="1 A_ID=166234"; char part1[80+1]; char part2[80+1]; printf("\ntestline: %s\n",input); sub(input,part1,' '); entfWSC(input); sub(input,part2,'='); printf("input : %s\n",input); printf("\npart1 : %s\n",part1); printf("part2 : %s\n",part2);
und wenn ich mir nun die Ausgabe angucke kommt genau das raus, was ich eben schon gepostet habe, nur dass "╠" immer ein seltsames Zeichen ist, d.h. dort steht nicht immer diese zahl, sondern ein Zeichen.
-
Seltsam, ich hab grad folgendes
#include <stdio.h> #include <string.h> int substr(char *quelle, char *ziel, char suche); int main(int argc, char **argv) { char text[100] = "Text=Wert"; char wert[20]; substr(text, wert, '='); printf("%s = %s", text, wert); return 0; } int substr(char *quelle, char *ziel, char suche) { char *pos; //Zeichen suchen pos = strchr(quelle, suche); //Zeichen gefunden? if(pos) { //gefundenes Zeichen überschreiben *pos++ = 0; //alles nach dem gefundenen Zeichen kopieren strcpy(ziel, pos); return(0); //Alles OK } else { return(-1); //Suchzeichen nicht gefunden! } }
hiermit compiliert und das Programm ausgeführt. Funktioniert problemlos.
-
das stimmt. wenn ich deinen Code compiliere klappt das auch. in meinem Programm klappt das nicht.
Naja, ich werde mal noch ein wenig rumfuchsen und denn mal sehen, ob ich es noch hinbekomme.
Auf jeden Fall schon mal Danke.
-
Die Funktionen von AJ funktionieren bei mir einwandfrei. nur sein substr liefert die Ergebnisse anders zurück als mein substr.
Die Funktion test3 sollte hat mit deinem Problem nichts zu tun. Sie dient nur dazu zu zeigen wie
ich den Overhead der Funktionen ermittelt habe um die Laufzeiten der Funktionen
substr alt, substr neu, StrRmLe und entfWSC zu ermitteln. in den Funktionen test1,test2,test4, test5 war jeweils eine der zu testenden funktionen anstelle der leerfunktion _substr_. Es ging nicht andersden wenn ich diese dummi Funktion weglasse ärgert mich der optimizer des Compilers.Danke AJ, zumindest habe ich jetzt eine schnellere Variante mit entfWSC
Diese zwei Funktionen sind zentraler Bestandteil einer großen Anzahl von Textmanipulationstools
bei zu Hause und in meinem Job, und meine Meinung ist je schneller desto besser solange die Verständlichkeit
nicht leidet.Damit die beiden substr Varianten sich gleich verhalten müssen bei AJ die mit /**/ markierten Zeilen geändert werden.
Denn leider ist es das entscheidende an dieser Funktioen das der Inputstring vom Anfang her um die gefundenen Zeichen verkürzt wird und diese in Ziel auftauchen. Somit kann man auf übersichlichste Weise einen Inputstring mit verschiedenen Trennzeichen in seine Bestandteile zerlegen.int substr_(char *quelle, char *ziel, char suche) { char *pos; char *tmp; //Zeichen suchen pos = strchr(quelle, suche); //Zeichen gefunden? if(pos) { //gefundenes Zeichen überschreiben *pos++ = 0; /**/ //Ergebnis d.h der Teil vor dem Trennzeichen nach Ziel kopieren /**/ strcpy(ziel,quelle); /**/ //alles nach dem gefundenen Zeichen kopieren /**/ strcpy(quelle, pos); return(0); //Alles OK } else { return(-1); //Suchzeichen nicht gefunden! } }
-
Habe jetzt noch einmal die Laufzeiten verglichen mit MS Visual C++ 6.0 professional, mit interessanten
Ergebnissen.Einmal in der Debugversion
Anzahl Durchlaeufe: 67108864 0x4000000
Begin test1 dummi (Overhead) End test1: 7.857198
Begin test2 substr alt PAD End test2: 48.689702
Begin test3 substr neu AJ End test3: 26.469494
Begin test4 entfWSC End test4: 21.819640
Begin test5 StrRmLe End test5: 56.789122
Test1 Ges: 7.857 Kor: 0.000 s, pro Run: 0.000 us
Test2 Ges:48.690 Kor:40.833 s, pro Run: 0.608 us
Test3 Ges:26.469 Kor:18.612 s, pro Run: 0.277 us
Test4 Ges:21.820 Kor:13.962 s, pro Run: 0.208 us
Test5 Ges:56.789 Kor:48.932 s, pro Run: 0.729 usEinmal in der Releasversion Speed Optimiert
Anzahl Durchlaeufe: 67108864 0x4000000
Begin test1 dummi (Overhead) End test1: 4.062547
Begin test2 substr alt PAD End test2: 16.711492
Begin test3 substr neu AJ End test3: 33.469272
Begin test4 entfWSC End test4: 29.972967
Begin test5 StrRmLe End test5: 37.763907
Test1 Ges: 4.063 Kor: 0.000 s, pro Run: 0.000 us
Test2 Ges:16.711 Kor:12.649 s, pro Run: 0.188 us
Test3 Ges:33.469 Kor:29.407 s, pro Run: 0.438 us
Test4 Ges:29.973 Kor:25.910 s, pro Run: 0.386 us
Test5 Ges:37.764 Kor:33.701 s, pro Run: 0.502 us