Dateien einlesen und vergleichen



  • und wie mache ich aus dem String drei Teilstrings?



  • 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?



  • @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!
       }
    }
    

Anmelden zum Antworten