Dateien einlesen und vergleichen



  • @PAD

    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 Shutdown

    Das 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 benutzt

    int 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 us

    Einmal 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



  • @PAD
    Also wenn es dir um Schnelligkeit geht, dann hätt ich noch ne schnellere Variante für deine Teilerfunktion:

    void teiler(char **quelle, char **teil, char suche)
    {
       char *pos;
    
       for(pos = *quelle; *pos && *pos != suche; ++pos);
    
       if(*pos)
       {
          *pos++ = 0;
          *teil = *quelle;
          *quelle = pos;
       }
    }
    

    Allerdings musst du dann beim Aufruf mit variablen Zeigern arbeiten:

    ...
    char text[20] = "Text=Wert";
    char *name, *wert;
    
    wert = text;
    teiler(&wert, &name, '=');
    
    printf("Name: %s\nWert: %s\n", name, wert);
    

    Warum müssen die Parameter eigentlich in dieser unvorteilhaften Verteilung sein??

    PS: Die Schleife oben kann man auch durch strchr() ersetzen: pos = strchr(*quelle, suche);

    Also diese Geschwindigkeitsergebnisse finde ich sehr seltsam. Besonders, weil im Debugmodus meine Funktionen schneller sind. 😕


Anmelden zum Antworten