string rückwärts speichern



  • Liebe Community,

    ich habe, so zumindest glaube ich, mit einem Verständnisproblem zu kämpfen. Die Frage ist jetzt, wo genau es da bei mir hängt. Ich möchte euch gerne die Funktion vorstellen und schilden wie das Programm "Aus meinen Augen" heraus funktioniert. Und wo sich der Fehler bei mir eingeschlichen hat.

    Es handelt sich hier um ein Programm das einen String Rückwärts auslesen soll und Ihn anschließen mit zwei verschiedenen Variablen Vor- und rückwärts darstellt.

    Fehler: char textrueck bleibt leer, trotz der zuweisung...

    Ansonsten läuft das Problem und lässt sich auch starten wenn man die Funktion aufruft.

    void freader()
    {
    
    		char textvor[100];     //string zum speichern des textes deklariert
    		char textrueck[100];
    
    		int textlaenge;       // integer für die laenge des textes deklariert
    		int zaehler;         //ende des gegebenen strings
    		int zaehlervor = 0; //anfang des neuen strings
    
    		fflush(stdout);  
    		fgets(textvor, sizeof(textvor), stdin); //nimmt den eingegeben Text entgegen und speichert diesen in textvor.
    		textlaenge = strlen(textvor); //ermittelt die größe des eingegeben strings und speichert diese in einem int für die forschleife
    
    		printf("\ntextlaenge: %i ",textlaenge); //Kontrolle für die laenge. Kommt später raus
    		for(zaehler=textlaenge; zaehler>0; zaehler--) // schleife läuft solange bis die laenge des strings größer als 0 ist.
    		{
    			textrueck[zaehlervor] = textvor[zaehler];  //Dadurch das wir den zaehler runterzählen bekommen wir die Buchstaben des Strings textvor die ganz hinten stehen 
    			zaehlervor++; //und weisen jeden Buchstaben dem neuen string textrueck zur, dessen zaehlervor immer um 1 erhöht wird und den string damit rückwärts speichern sollte.
    		}
    
    		printf("\nVorwaertsgeschrieben lautet der gespeicherte Text: %s", textvor);
    		printf("\nRuekwaertsgeschrieben lautet der gespeicherte Text: %s", textrueck);
    }
    

    Der Grund warum ich textlaenge und zaehler habe ist der, das sich bei mir textlange ohne zuweisung in der Forschleife als Fehler entpumpt hat und ich deswegen einfach noch eine zuweisung durchführe. Vielleicht kann man das auch besser lösen, eingefallen ist mir da nichts.

    Ich hoffe ihr könnt mir dabei helfen. Die Suche bei google hat viele hinweise geliefert und bestimmt auch mal die Lösung des Problems, allerdings war ich nicht in der Lage diese zu erkennen.



  • Weißt du wie C-strings aufgebaut sind und wie bei Arrays der Index läuft?

    Arrays fangen in C mit dem Index 0 an. Immer.
    Und sie haben soviel Elemente wie bei der Definition angegeben.
    Bei textvor und textrueck sind das 100 Element, die von 0 bis 99 durchnummeriert sind.

    In C sind Strings Arrays, die nullterminiert sind. Sie haben als Endekennung das Zeichen mit dem Wert 0: '\0'

    Bsp:
    char text[3] = "AB";
    Dann liegt das im Speicher als
    `text[0] = 'A'

    text[1] = 'B'

    text[2] = '\0' // Endekennung

    `
    textlaenge ist dann 2 (zwei Zeichen)

    Was passiert jetzt in deiner Schleife?
    Du setzt zaehler auf 2, zaehlervor auf 0.
    und dann
    textrueck[0] = text[2]; // Du schreibst die Endekennung an den Anfang von textrueck
    zaehler-- (1) zaehlervor++ (1);
    zaehelr ist größer als 0, die Schleife geht weiter.
    textrueck[0] = text[2]; // Das 'B' wird kopiert
    zaehler-- (0) zaehlervor++ (2);
    Jetzt ist zaehler nicht mehr größer als 0 und die Schleife ist vorbei.
    Du hast das 'A' noch nicht kopiert.

    Das textrueck leer ist, liegt daran, dass du die Endekennung an den Anfang kopiert hast.



  • Vielen Dank Dirk B.

    Jetzt ist zaehler nicht mehr größer als 0 und die Schleife ist vorbei.
    Du hast das 'A' noch nicht kopiert.

    Ich denke das Problem kann man lösen wenn man "zaehler >= 0" setzt.

    Das textrueck leer ist, liegt daran, dass du die Endekennung an den Anfang kopiert hast.

    Jetzt tut das Programm das was es tun sollte. Allerdings bin ich mit dem Ergebnis nicht zufrieden. Ich habe es durch den Beitrag von DirkB und ein wenig experimentelen Glück hingekriegt, aber nicht wirklich verstanden.

    Ich habe, egal wo ich es mache, den zaehler für textvor "-2" gerechnet, um dem Nullbyte und irgendeinem anderen zeichen, von dem ich glaube das es ein \n ist, zu hintergehen und die Restbuchstaben dann in richtiger Reihenfolge einzutragen.

    for(zaehler=(textlaenge-2); zaehler>=0; zaehler--)
    

    Zum Verständnis, wenn das der richtige Werdegang ist, den ich hier eingeschlagen habe um ein sauberes Ergebnis zu erhalten, muss ich also darauf achten das ich die "nullterminierung" nicht mit ins neue Array übergebe, weil für das Array ein Übertrag des zeichens \0 das Ende heißen würde und ich deshalb immer einen leeren "string" hatte.



  • Das '\n' kommt von der Entertaste bei der Eingabe und wird von fgets abgelegt.
    Das solltest du vor dem Umdrehen schon entfernen.

    Und die Nullterminierung muss auch in das neue Array. Allerdinga an das neue Ende.
    Es ändert die Position nicht.
    Und du kannst nicht davon ausgehen, dass da immer zufällig eine 0 steht.
    Du musst die extra rein schreiben.



  • Nochmals danke DirkB,

    Das '\n' kommt von der Entertaste bei der Eingabe und wird von fgets abgelegt.
    Das solltest du vor dem Umdrehen schon entfernen.

    Wie bekomme ich das denn geschickt weg? Ich habe das jetzt wie schon im Post vorher angekündigt mit -2 gerechnet. Gibt es eine Möglichkeit das schon im textvor array zu entfernen ohne das ich eine ganze vorschleife machen muss die das \n rausfiltert?

    Und die Nullterminierung muss auch in das neue Array. Allerdinga an das neue Ende.
    Es ändert die Position nicht.... Du musst die extra rein schreiben.

    Ich bin deinem Ratschlag mal gefolgt und habe das ganze wie folgt aussehen lassen.

    void freader()
    {
    
    		char textvor[100];
    		char textrueck[100];
    
    		int textlaenge;
    		int zaehler;
    		int zaehlervor = 0;
    
    		fflush(stdout);
    		fgets(textvor, sizeof(textvor), stdin);
    		textlaenge = (strlen(textvor));       
    
    		printf("\ntextlaenge: %i ",textlaenge);
    		for(zaehler=textlaenge; zaehler>=0; zaehler--)
    		{
    
    			if(textvor[zaehler] == '\0')
    			{
    				textrueck[zaehler] = '\0';	//\0 an die selbe Stelle schreiben wie im alten Array
    				printf("0 hinzugefügt");
    			}
    			else
    			{
    				textrueck[zaehlervor] = textvor[zaehler-2]; //-2 nimmt einmal das \n das von fgets gegeben wird weg und einmal das \0
    				zaehlervor++;
    			}
    		}
    
    		printf("\nVorwaertsgeschrieben lautet der gespeicherte Text: %s", textvor);
    		printf("\nRuekwaertsgeschrieben lautet der gespeicherte Text: %s", textrueck);
    }
    

    Hier überspringe ich also den \n und \0 und schreibe meine Buchstaben rein und sage dem Programm, wenn du im Array auf '\0' stoßt, dann schreibe an genau die selbe Stelle im neuen Array das \0 rein.

    Bin ich da nun auf dem richtigen Weg? Also an sich funktioniert es ja, doch gefällt es mir mit dem gecheatet -2 nicht...



  • for(zaehler=textlaenge - 2; zaehler>=0; zaehler--)
            {
    
                    textrueck[zaehlervor] = textvor[zaehler];
                    zaehlervor++;
    
            }
            textrueck[zaehlervor] = '\0'; //oder einfach  .... = 0
    


  • Du kannst

    for (zaehler=0; textvor[zaehler] != '\0'; zaehler++) // solange es nicht das Endezeichen
    { if (textvor[zaehler] == '\n')  // ist es Newline?
      {  textvor[zaehler] = '\0';    // Ja, dann ersetzen
         break;                      // und fertig mit der Schleife
      }
    }
    

    nach dem fgets und vor dem strlen machen.
    oder du nimmst statt fgets(...)

    scanf("%99[^\n]", textvor);
    


  • Alles klar, vielen Dank.
    Ich denke ich habe es vorerst verstanden. Zumindest das was ich verstehen wollte.
    Ich lasse diese Aufgabe dann mal hinter mir und witme mich der nächsten Herausforderung. Dort wird sich dann zeigen ob ich es wirklich verstanden habe und wenn nicht dann werde ich es spätestens da verstehen.

    @DirkB

    oder du nimmst statt fgets(...)
    C:
    scanf("%99[^\n]", textvor);
    

    mit dem '^' sagst du scanf das du es nicht drin haben willst?
    Haben es mal getestet und find ich klasse. Aber warum gibt es sowas nicht für fgets()?
    Ich hab das jetzt so gelernt das man fgets statt scanf benutzen soll, weil "Schlag mich Tod" (Ich habe keine Ahnung mehr warum).

    Ist das nun was dran oder kann ich beruhigt auch scanf() in kleineren funktionienen wie diesen nutzen?

    @Belli
    Ah wusste nicht das es auch so geht. Danke



  • Die wenigsten kennen bei scanf den %[ Specifier.
    Und %s hört bei Whitespaces (Leerzeichen und so) auf zu lesen.
    Zudem ist es schwierig die 99 da reinzubasteln. Und die sollte da stehen, sonst kannst du gleich gets nehmen.

    Am '\n' von fgets kannst du übrigens erkennen, ob du alle Daten gelesen hast oder der Puffer zu klein war. (ist es nicht im String, wurden noch mehr Daten eingegeben).



  • Semreh schrieb:

    @Belli
    Ah wusste nicht das es auch so geht. Danke

    Naja, wenn Du genau weißt, dass Du die letzten zwei Zeichen nicht haben willst, fängst Du einfach zwei Zeichen vom Ende weg an, rückwärts zu zählen. In Deinem konkreten Fall weißt Du dann auch genau, dass Du damit das 0 - Zeichen und das Zeilenende - Zeichen schon eliminiert hast, und brauchst Dich deshalb in der Schleife nicht mehr drum zu kümmern.
    Nach der Schleife muss dann das Stringterminierungszeichen '\0' (oder 0) noch hinten angehängt werden.



  • Verstehe, also sollte ich fgets die Kontrolle mit \n zutrauen und einfach einen \n Filter mit reinbaue wenn dieser mich stört.

    Wieso ist es schwer die %99 in den Scanf einzubauen?
    Steht die 99 nicht für 99 von 100 Plätzen im Array?
    Wenn ich also ein Array von 10 habe würde es %9 heißen oder nicht?
    Oder verstehe ich da was falsch



  • Der Vorteil von scanf gegenüber fgets ist:

    char s[100];
    scanf("%99[^\n]",s);
    fgets(s,100,stdin);
    

    mit scanf ist \n niemals in s enthalten;
    mit fgets kann \n enthalten sein oder auch nicht;
    Je nach Anwendungsfall bedeutet das mehr Code,
    außerdem liest scanf (mit %s statt %[]) immer nur das erste Wort zwischen Whitespaces, auch hier ist es eine Frage des Anwendungsfalles, ob man dies sonderbehandeln muss/will oder nicht.

    Die Antwort, ob scanf/fgets besser als fgets/scanf ist, gibt der Deutsche-Bank Chef (Jain).
    Es gibt auch noch die Möglichkeit, fgets und sscanf gemeinsam zu verwenden; da stellt sich aber die Frage aber natürlich erst gar nicht.



  • mit scanf ist \n niemals in s enthalten;
    mit fgets kann \n enthalten sein oder auch nicht;
    Je nach Anwendungsfall bedeutet das mehr Code,
    außerdem liest scanf nur das erste Wort zwischen Whitespaces, auch hier ist es eine Frage des Anwendungsfalles, ob man dies sonderbehandeln muss/will oder nicht.

    Sehr schön. Und wieder schlauer geworden. Vielen Danke
    Auch den anderen nochmals danke. Das Forum gefällt mir, ich denke bei weiteren Fragen werde ich mich direkt ans Forums wenden.



  • Semreh schrieb:

    Wieso ist es schwer die %99 in den Scanf einzubauen?
    Steht die 99 nicht für 99 von 100 Plätzen im Array?
    Wenn ich also ein Array von 10 habe würde es %9 heißen oder nicht?
    Oder verstehe ich da was falsch

    Das ist schon richtig.
    Du hast hier aber auch statische Arrays, deren Größe beim Compilerlauf bekannt ist, und die sich zur Laufzeit auch nicht ändert.

    Wenn du die Größe ändern willst, musst du überall im Code die 100 bzw. 99 ändern. Das ist aufwendig.

    Makros wären eine Idee.
    `#define TEXTSIZE 100

    char textvor[TEXTSIZE];Aber da musst du dann den Wert von TEXTSIZE in einen String bekommen.scanf("%"#TEXTSIZE"s", ...);`
    Aber halt, da soll ja der Wert von TEXTSIZE-1 hin. Blöd.

    Und ganz variabel wird es noch schwieriger


Anmelden zum Antworten