u.a. Strings/Arrays



  • hab heut in ner doku gelesen das es den befehl memmove gibt. kannte ich noch gar nicht und da viel mir gleich wieder dein beispiel ein. damit gehts dann super easy

    Ich habs diesmal auch extra mit kommentaren versehen, jetzt sollte ja hoffentlich alles klar sein und AJ ist hoffentlich auch zufrieden 😃

    int ersetzen(char *such, char *neu, char **inp,int *inp_l){ 
    int offset,x=strlen(neu),y=strlen(such),z=strlen(*inp),rv=0; 
    char *str,*tmp; 
    
        while(str=strstr(*inp,such)){ //substring such im string *inp suchen
    		++rv;					//inkrementieren der anzahl der gefundenen ersetzungen
    		z+=x-y;					//neue zeichenanzahl von *inp errechnen					
    
    		if(*inp_l<=z){			//wenn *inp nicht gross genu
    			offset=str-*inp;	//offset merken
    			tmp=(char*)realloc(*inp,sizeof(char)*(z+1));	//feld entsprechneder grösse allokieren
    			if(tmp){*inp=tmp;*inp_l=z+1;str=*inp+offset;}	//ursprungszustand der zeiger herstellen
    			else return -1;
    		}
    
           	memmove(str+x,str+y,sizeof(char)*strlen(str+y-1));	//werte im array nach dem zu ersetzenden verschieben 
    		memcpy(str,neu,sizeof(char)*x);						//neu zeichenfolge in *inp kopieren
    
    	}
    
        return rv; //fertisch
    }
    


  • Kann man im Großen und Ganzen durchgehen lassen ;). Bis auf das, dass du teilweise immer noch deinen Code etwas unübersichtlich (zusammengepresst) schreibst:

    ...
    			if(tmp){*inp=tmp;*inp_l=z+1;str=*inp+offset;}	//ursprungszustand der zeiger herstellen
    			else return -1;
    ...
    

    Außerdem sind deine sizeof(char) total überflüssig.

    @evil
    Trotzdem solltest du bei deinem eigenen Code bleiben, den du auch wahrscheinlich besser verstehen wirst. Aber im Endeffekt ist es deine Entscheidung.



  • Warum kann ich mit meinem Code lediglich einen String ersetzen? Sobald zwei zu ersetzende Strings drin sind gehts schon nicht mehr 😞



  • Zeig mal deinen jetzigen Quellcode. Du könntest auch mal den Debugger starten und schaun, wo was schief läuft.



  • Hab jetzt noch einiges verändert, weil mein zu ersetzender String länger ist als der ersetzte.
    Aber guck mal selbst. So richtig haut das nicht mehr hin:

    char* ersetzen(const char* re, const char* repl, char* in, char* buffer)
    {
    	char *pos, *oldpos ;
    	long len_buf;
    
    	pos = strstr(in , re);		// suche den Suchstring im Input
    
    	if(!pos) 
    	{ 
            return in;
    
    	}
    
    	oldpos = in;				// die alte Position speichern (hier noch Anfang)
    	*buffer=0;					// buffer mit 0 initialisieren
    
    	while(pos)					// sobald der Suchstring gefunden wurde
    	{
    
    		len_buf = strlen(buffer);			// len_buf wird die Länge vom Buffer zugeordnet
    
    		strncpy(buffer, in, pos-oldpos);			// Kopiere von alter Position bis Position des Suchstrings nach buffer
    
    		buffer[len_buf +pos - oldpos] = '\0';		// Stringendezeichen setzen
    
    		oldpos = pos+strlen(re);	// Position nach Suchstring im Text ermitteln
    
    		char buffer2[STR_MAX];  // buffer2 für Rest erzeugen
    
    		memset(buffer2,0,strlen(buffer2));
    
    		strncpy(buffer2, oldpos, len_buf);		// den Rest in buffer2 kopieren
    
    		strcat(buffer, repl);		// kopiere den zu ersetzenden String an die Stelle wo der alte gefunden wurde
    
    		oldpos = pos+strlen(repl);	//Position nach dem ersetzten String ermitteln
    
    		strcat(buffer, buffer2);	
    
    		memset(buffer2,0,strlen(buffer2));
    
    		oldpos =pos + strlen(re);	// Position nach Suchstring im Text ermitteln
    
    		pos = strstr(oldpos,re);	//Suche nach weiteren Suchstring in Text hinter letzten gefundenen Suchstring 
    
    	}
    
    	strcat(buffer, oldpos);		// den Rest an die Position nach der Ersetzung kopieren		
    
    	return buffer;
    }
    


  • Außerdem sind deine sizeof(char) total überflüssig

    aber auch nur weil im standard steht das sizeof(char) 1 ist. wenn das mal geändert werden sollte, ist mein code anpassungfähiger 😃 (ok flache begründung ich habs mir halt so angewöhnt weils nicht schadet.

    sizeof wird ja auch schon zur kompilzeit ausgewertet so das der code in der ausführung nicht langsamer wird

    greetz Windalf



  • Naja, so richtig rennt es noch nicht... Vielleicht findet ja noch jemand ein oder zwei Fehler in meinem zuletzt geposteten Code. Würde mich auf jeden Fall freuen.



  • Also wenn ich jetzt nochmal deinen Parameter "in" in der while()-Schleife finde, dann bekommst du Anschiss. 😉

    evil411 schrieb:

    ...
    		strncpy(buffer, in, pos-oldpos);			// Kopiere von alter Position bis Position des Suchstrings nach buffer
    ...
    

    Da gehört nicht in hin sondern oldpos! Dein Parameter in gehört überhaupt nicht in die Schleife rein, dafür hast du ja oldpos.



  • Also ich habe den Code jetzt folgendermaßen:

    char* ersetzen(const char* re, const char* repl, char* in, char* buffer)
    {
    	char *pos, *oldpos, buffer2[STR_MAX];
    	long len_buf;
    
    	pos = strstr(in , re);		// suche den Suchstring im Input
    
    	if(!pos) 
    	{ 
            return in;
    
    	}
    
    	oldpos = in;				// die alte Position speichern (hier noch Anfang)
    
    	*buffer=0;					// buffer mit 0 initialisieren
    	*buffer2=0;
    	 while(pos)                    // sobald der Suchstring gefunden wurde 
        { 
    		printf("--->pos---->%s\n",pos);
            len_buf = strlen(buffer);			// len_buf wird die Länge vom Buffer zugeordnet 
    
            strncpy(buffer, oldpos, pos-oldpos);            // Kopiere von alter Position bis Position des Suchstrings nach buffer 
    
            buffer[len_buf +pos - oldpos] = '\0';        // Stringendezeichen setzen 
    
            oldpos = pos+strlen(re);    // Position nach Suchstring im Text ermitteln 
    
            char buffer2[STR_MAX];  // buffer2 für Rest erzeugen 
    
            memset(buffer2,0,strlen(buffer2)); //mit 0 vorbelegen
            printf("--->buffer---->%s\n",buffer);
    
    		strcpy(buffer2,strstr(in,re)+strlen(re));        // den Rest in buffer2 kopieren 
            printf("--->buffer2--->%s\n",buffer2);
    
    		strcat(buffer, repl);        // kopiere den zu ersetzenden String an die Stelle wo der alte gefunden wurde 
    
            strcat(buffer, buffer2);    
    
            memset(buffer2,0,strlen(buffer2)); 
    
            oldpos =pos + strlen(re);    // Position nach Suchstring im Text ermitteln 
    
            pos = strstr(oldpos,re);    //Suche nach weiteren Suchstring in Text hinter letzten gefundenen Suchstring 
    
            printf("\n");
        } 
    
        strcat(buffer, oldpos);        // den Rest an die Position nach der Ersetzung kopieren        
    
        return buffer; 
    
    }
    

    Aber wenn ich jetzt z.B. so einen String übergebe:

    Dieser String ist ein Test ist
    

    ...und versuche das ist durch ERSETZT zu ersetzen, dann kommt das raus:

    ein Test ing ERSETZT ein Test istERSETZT ein Test ist
    

    ...WARUM??? 😕



  • Du produzierst ja immer mehr Chaos rein. 😮

    Was soll dieser buffer2 und dann auch noch mitten im Kontext deklariert. 😮

    Fang nochmal mit deinem 1. Code hier drin an:

    char* ersetzen(const char* re, const char* repl, char* in, char* buffer)
    {
        char *pos, *oldpos;
        int len_buf;
    
        pos = strstr(in , re);        // suche den Suchstring im Input
        printf("Position: %s\n", pos);
        if(!pos)
        {
           strcpy(buffer, in);
    
            return(buffer);
    
        }
    
        oldpos = in;                // die alte Position speichern (hier noch Anfang)
        printf("Alte Position: %s\n", oldpos);
    
        *buffer=0;                    // buffer mit 0 initialisieren
    
        while(pos)                    // sobald der Suchstring gefunden wurde
        {
            printf("Testausgabe");
            len_buf = strlen(buffer);    // len_buf wird die Länge vom Buffer zugeordnet
            printf("Bufferlänge: %d\n", len_buf);
    
            strncpy(buffer+len_buf, oldpos, pos-oldpos);    // Kopiere von alter Position bis Position des Suchstrings nach buffer
            //printf(buffer);                                       
            buffer[len_buf+pos-oldpos] = 0;        // Stringendezeichen setzen
    
            strcat(buffer, repl);    // kopiere den zu ersetzenden String an die Stelle wo der alte gefunden wurde
    
            oldpos = pos + strlen(re);    // Position nach Suchstring im Text ermitteln
    
            pos = strstr(oldpos,re);    //Suche nach weiteren Suchstring in Text hinter letzten gefundenen Suchstring
    
        }
    
        strcat(buffer, oldpos);        // den Rest an die Position nach der Ersetzung kopieren
        return(buffer);
    }
    

    Die Fehler, die ich damals schon gesehen habe, hab ich gleich rausgemacht. Der Code sollte also funktionieren. Wenn nicht, schreib nochmal.



  • Funktioniert aber leider immer noch nicht...
    Wenn ich immer noch diesen String hier eingebe und "ist" durch "ERSETZT" ersetzen will:

    Dieser String ist ein Test ist
    

    Dann kommt dieser raus:

    ein Test ing ERSETZTERSETZT
    

    Wenn ich das aber mit dem gleichen String ohne dem letzten "ist" probiere, dann klappts. Ich weiß auch nicht warum...



  • Hab anscheinend doch noch einen Fehler übersehen.
    Du hast mit strncpy() immer an den Anfang von buffer was kopiert, was ja nicht immer richtig ist ;). Hab es oben korrigiert, probiers nochmal.



  • Danke 😉
    Genauso sollte es funktionieren. Es hat wirklich daran gelegen... 🤡



  • habe jetzt nur noch ein Problem:
    und zwar haut das mit dem ersetzen jetzt gut hin, aber wenn ich jetzt anstatt dem inp (das ja kurz vor Funktionsaufruf generiert wurde:

    char inp[]="das ist ein Test";
    

    )
    ... einen anderen InputString nehme, in meinem Beispiel ein String der aus einer Datei eingelesen wurde,funktioniert es nicht.
    Dieser InputString besteht nur aus einer Zeile, sollte also Problemlos klappen. Es klappt aber nur wenn der zu ersetzende String länger bzw. gleich lang ist wie der einzusetzende. Andererseits haut es nicht hin wenn ich z.B. in diesem InputString "ist" durch "ist2" ersetzen will. (wenn ich es andersherum ersetzen würde, dann würde es klappen)
    Woran kann das noch liegen?
    P.S. mein Input hat vorher 100000 Zeichen. Selbst wenn ich anschließend mit buffer weiterarbeite, klappts nicht. Nur wenn der zu ersetzende String kürzer ist... 😕 😕 😕 😕 😕 😕 😕 😕 😕 😕



  • Zeig mal bitte die Aufrufe von ersetzen() und die Deklarationen der verwendeten Variablen.



  • OK, hier ein paar Ausschnitte, die wichtig sein sollten:

    #define MAX_LEN 100000
    char inputline[MAX_LEN];
    ...
    

    inputline wird aus einer Datei ausgelesen...
    und dann folgender Funktionsaufruf:

    char buffer[STR_MAX];
    ersetzen("\"|\"|","qm|",inputline, buffer);
    		printf(buffer);
    

    ... und mein Inputline ist genau 1 Zeile mit ziemlich vielen Zeichen und Buchstaben (MAX. 100000)



  • Wie groß ist STR_MAX?

    Möglicherweise ist len_buf das Problem bzw. dessen Typ. Verwende mal anstatt int den Typ long.
    Ansonsten solltest du mal den Debugger anschmeissen (dein bester Freund).

    Übrigens noch was:

    printf(buffer); => falsch bzw. kann leicht zu Fehlern führen (man bedenke nur, da steht ein % im String drin ;))
    printf("%s", buffer); => richtig



  • Klappt so leider auch nicht wenn ich aus int long mache...
    Mein STR_MAX ist auch 100000 groß... Woran könnte es noch liegen??? 😕



  • Was genau funktioniert bzw. klappt eigentlich nicht?



  • na wie bereits gesagt habe ich ein char inp[100000] und ein char buffer[100000]. In inp wird ne Datei eingelesen, welche nur aus einer zeile besteht.
    Wenn ich jetzt meine ersetzen-Funktion so aufrufe:

    ersetzen("hallo","Tag",inp,buffer);
    

    dann funktioniert es, weil hallo(5 Zeichen) entfernt und Tag (3 Zeichen) hinzugefügt wird. Wenn ich aber jetzt die Funktion z.B. so aufrufen würde:

    ersetzen("hallo","Guten_Tag",inp,buffer);
    

    ... dann würde es nicht klappen und ein Speicherfehler entstehen... Vielleicht ist irgendein Array zu klein oder so 😕 , aber ich habe alle Größen schon mal versucht zu ändern... Der Debugger hilft mir auch nicht weiter...

    P.S. Also wie gesagt ist mein inp relativ gross, wenn ich z.B. anstatt Inp einen String (char test[]="hallo sie, ja sie, hallo";) übergeben würde, dann gibt es keinen Speicherfehler und ich kann hallo ohne Probleme durch Guten_Tag ersetzen.


Anmelden zum Antworten