String durchsuchen und ersetzen



  • Ich durchlaufe eine Textdatei:

    FILE * fpIn, * fpOut;
     char Zeile[300];
     while (( fgets( Zeile, 200, fpIn )) != NULL )		
        {
    
        }
    

    Wenn in einer Zeile folgendes steht:

    U200 V=AC(-11.5) RT=16500 R2

    dann möchte ich immer diesen Term --> V=AC(-11.5) entfernen . Mit Replace
    kein Problem allerdings kann sich der Wert in der Klammer ändern.

    Soweit bin ich:

    if(strstr (Zeile," V=AC("))
    {
    
    }
    

    Ich müsste jetzt von dem ersten V=AC( bis zum nächsten Leerzeichen ersetzen.
    Leider stehe ich auf dem Schlauch und habe keinen Ansatz.
    Kann mir jemand helfen ? Danke im Voraus !



  • Z.B.:
    strstr liefert die sogar die Position, ab der dein Suchtext steht.
    Von dort aus kannst du das nächste Leerzeichen suchen. (das geht mit strchr )
    Dann weißt du schon mal, was ersetzt werden soll.

    Dann schreibst du den Text bis zur Position vom strstr , dann deinen Ersatztext und dann den Rest ab strchr .

    OlafKam21 schrieb:

    Mit Replace kein Problem

    Welches Replace meinst du denn?



  • Hallo Dirk,
    Danke für die schnelle Antwort. Den Text versteh ich und die Vorgehensweise die ich machen soll. Allerdings kann ich mit dem Werkzeug (strstr,strchr) nicht so viel anfangen. Daher erst einmal der erste Term. Soweit ok ? Ich denke viel zu kompliziert.

    FILE * fpIn, * fpOut;
     char Zeile[300];
     while (( fgets( Zeile, 200, fpIn )) != NULL )     
        {
    
        if(strstr (Zeile," V=AC("))
        {
    
         char * Dummy;
         Dummy = strstr (Zeile," V=AC(");
         Dummy = strchr(Dummy,' ');
    
        }
       }
    


  • Du definierst ein Array mit 300 Elementen, liest dann aber über fgets nur 200 - 1 Zeichen ein. Sinn?

    Deine Einrückung ist unregelmäßig, und Variablen solltest du kleinschreiben.
    Deinen Code kann man auch kürzer fassen:

    FILE*fpIn; /*fpOut brauchst du in deinen Beispielen hier eh nie*/
    char line[300];
    char*start,*end;
    
    while(NULL != fgets(line,sizeof(line),fpIn))
    {
        if(NULL == (start = strstr(line,"V=AC(")))
            continue;
    
        if(NULL == (end = strchr(start,' ')))
            continue;
        ++end;
    
        /*Und hier kopierst du dann halt.*/
    }
    

    EDIT: Beispielcode hat von stdin eingelesen.



  • Danke....auch für die zusätzlichen Tipps.

    Wäre es jetzt nicht einfacher, das Ergebnis zwischen start und ende einfach durch ein Leerzeichen zu ersetzen und dann Zeile auszugeben ? Kopieren klingt aufwendig und ich wüsste auch nicht wie und von wo bis wo ich kopieren soll.



  • OlafKam21 schrieb:

    Wäre es jetzt nicht einfacher, das Ergebnis zwischen start und ende einfach durch ein Leerzeichen zu ersetzen und dann Zeile auszugeben ?

    1. Du plenkst.

    2. Das hier ist deine Aufgabenstellung:

    OlafKam21 schrieb:

    dann möchte ich immer diesen Term --> V=AC(-11.5) entfernen .

    Wenn du derzeit nur an der Ausgabe interessiert bist, kannst du auch einfach die Substrings ausgeben lassen, aber dann musst du ein bisschen mit Zeigerarithmetik rumspielen (wie viele Zeichen du nach beiden Adressen ausgeben willst), und natürlich kannst du dann mit dem Wert auch später nicht weiterarbeiten - vorausgesetzt, du brauchst das.

    OlafKam21 schrieb:

    Kopieren klingt aufwendig

    Aufwendig für wen? Für den Rechner?

    Allein die Kontextwechsel für die Ausgabe oder die Speicherverwaltung bei Verkettung der Strings sind aufwendiger als dein bisschen Stringkopiererei auf dem Stack, die wahrscheinlich noch im CPU-Cache erfolgen kann.

    Oder für dich? Du solltest deinen Lehrer/dein Lernbuch wegwerfen, wenn diese dir nicht die standardisierten Stringfunktionen nennen. Hier ein Beispiel. Da findest du noch ein paar mehr Funktionen weiter unten, die du dir anschauen könntest, alleine um deinen Horizont zu erweitern.



  • OlafKam21 schrieb:

    Wäre es jetzt nicht einfacher, das Ergebnis zwischen start und ende einfach durch ein Leerzeichen zu ersetzen und dann Zeile auszugeben ? Kopieren klingt aufwendig und ich wüsste auch nicht wie und von wo bis wo ich kopieren soll.

    Beim "löschen" oder ersetzen durch ein Leerzeichen, wird auch nur der hintere Teil nach Vorne verschoben/kopiert.

    Das ist, wenn du die Daten nur in eine andere Datei schreiben willst, eine überflüssig Operation.



  • ich habe jetzt spontan an sowas wie sed oder perl gedacht.

    Da ich die sed-Syntax nicht exakt auswendig kenne, würde ich vermutlich

    perl -pe 's/V=AC\(-?\d+(\.\d+)?\) //g' < datei-eingabe > datei-ausgabe
    

    machen (und nicht C verwenden).

    Ob es sinnvoll ist, das in C zu machen, hängt natürlich davon ab, wie oft du was machst, wie groß die Daten sind etc.



  • Ich habe es jetzt so gelöst.

    @Dachschaden Mir war das kopieren zu kompliziert, da ich nicht wusste wie ich start und ende da jetzt kopieren soll.

    @wob Danke für den Hinweis, habe schon öfters gehört das für solche Belange Perl gut sein soll. Ich sollte mich hier wirklich mal einlesen.

    if(strstr(Zeile, " V=AC(") && (strstr(Zeile, " RT")) && (strstr(Zeile, " U")))
    		{
    				char trennzeichen[] = " ";
    				char *wort;
        				wort = strtok(Zeile, trennzeichen);
    
    				while(wort != NULL) 
                            {
    						if (strstr(wort, "V=AC("))
    						{	
    
    						}else{
    							fprintf( fpOut, "%s ", wort );
    						}
    						wort = strtok(NULL, trennzeichen);
    				}
    
    			}
    

    Zum Code:

    Der ist sicher zu kompliziert und man kann die Anforderung auch einfacher gestalten. Auch ist es fragwürdig den String so zu zerstückeln.



  • Dein Code ignoriert evtl. mehrfach vorkommende Leerzeichen, außerdem muss immer RT und U vorkommen.
    strtok ist nicht reentrant und multithreadunfähig und gehört nicht in Anfängerhände. Wie du schon bemerkt hast, zerstückelst du den String.

    int main()
    {
    	FILE *f = fopen("test.txt", "r");
    	char z[300];
    
    	while (fgets(z, 300, f))
    	{
    		const char *q, *p = strstr(z, "V=AC(");
    		double d;
    		if (p &&
    			1 == sscanf(p + 5, "%lf", &d) &&
    			(q = strchr(p, ')')) != 0)
    		{
    			printf("%.*s%s", p - z, z, q + 1);
    		}
    		else
    		{
    			printf("%s", z);
    		}
    	}
    	fclose(f);
    }
    

Log in to reply