Beliebig langen String rückwärts ausgeben



  • Guten Tag,

    ich versuche nun seit zwei Stunden verzweifelt einen beliebig
    langen String rückwärts auszugeben, leider stürzt bei jedem
    Versuch meine cmd ab....

    Ich hab das mal so probiert:

    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
    	char* my_string;
    	int i;
    
    	printf("String eingeben:\n");
    	scanf("[^\n]s", my_string);
    
    	i = strlen(my_string) -1;
    
    	for(i; i >= 0; i--)
    	{	
    		printf("%c", my_string[i]);
    	}
    
    	return 0;
    }
    

    Ich soll weder getchar() noch putchar() noch sonst irgendwas
    verwenden. Einzig und allein strlen ist erlaubt.

    Weiß nicht wie ich das anstellen soll -.-


  • Mod

    Schon beim einlesen wird dies scheitern, denn du hast nirgendwo Speicherplatz für deine Zeichenkette, bloß einen Zeiger, der irgendwo ins Nirvana zeigt.



  • Wie soll ich Speicherplatz allokieren, wenn ich vorher gar nicht
    weiß wie groß mein String wird?

    Außerdem passiert beim einlesen nichts.
    Wenn ich die Schleife weg mache stattdessen nach dem einlesen
    eine Ausgabe, gibt er mir problemlos meinen String aus.



  • Beliebig lang kann dein String auch nicht werden, da er durch den Wertebereich des int eingeschränkt ist. 😉

    Mach doch erstmal ein festen Speicherbereich, dann liest du zeichenweise ein und gibst auch zeichenweise aus.
    Aber bitte nicht mit scanf und printf. Die sind für ein Zeichen viel zu aufgeblasen.

    In der nächsten Verion kannst du dann ja den Speicher mit realloc() dynamisch vergrößern lassen.



  • Das kann doch nicht im Ernst so viel Aufwandt sein
    einen beliebig langen String zu erzeugen^^

    Ich glaub ich bin viel zu verwöhnt von Java ❤



  • C-Verzweifler schrieb:

    Ich glaub ich bin viel zu verwöhnt von Java ❤

    Ja, bist du.

    Denn Strings gibt es nicht in C.
    Um Zeichenketten zu verarbeiten, wird der Umweg über Zeiger und/oder char-Arrays emacht.



  • Abwer warum funktioniert das hier problemlos, wenn der zeiger angeblich ins nichts zeigt?

    int main(void) 
    {
    	char* my_string;
    
    	printf("Zeichenkette eingeben:\n");
    	scanf("%[^\n]s", my_string);
    
    	printf("%s", my_string);
    }
    

    Aber jetzt mal zu dem was du gesagt hast,
    muss das dann so sein?

    {
    	char* my_string = (char*)malloc(sizeof(char));
    
    	printf("Zeichenkette eingeben:\n");
    	scanf("%[^\n]s", my_string);
    
    	printf("%s", my_string);
    }
    
    Und dann würde das rückwärts auslesen funktionieren?
    


  • So funktioniert:

    int main(void)
    {
    	char* my_string = (char*)malloc(sizeof(char));
    	int i;
    
    	printf("String eingeben:\n");
    	gets(my_string);
    
    	i = strlen(my_string) - 1;
    
    	for(i; i >= 0; i--)
    	{
    		printf("%c", my_string[i]);
    	}
    
    	free(my_string);
    
    	return 0;
    }
    

    Aber vielleicht kann mir noch einer erklären, was "dahinter" passiert 😉



  • Nein, so:

    char my_string[300]; //Reserviert Speicher für einen 299 Byte langen C-String + Null-Delimiter
    


  • C-Verzweifler schrieb:

    char* my_string = (char*)malloc(sizeof(char));
    

    Aber vielleicht kann mir noch einer erklären, was "dahinter" passiert 😉

    Du hast Platz für ein einziges Zeichen reserviert ...



  • C-Verzweifler schrieb:

    Abwer warum funktioniert das hier problemlos, wenn der zeiger angeblich ins nichts zeigt?
    ....

    Weil du Glück hast. (Und das am Freitag den 13.)

    C-Verzweifler schrieb:

    Aber jetzt mal zu dem was du gesagt hast,
    muss das dann so sein?

    {
    	char* my_string = (char*)malloc(sizeof(char));
    	
    	printf("Zeichenkette eingeben:\n");
    	scanf("%[^\n]s", my_string);
    	
    	printf("%s", my_string);
    }
    
    Und dann würde das rückwärts auslesen funktionieren?
    

    Dein, denn du reservierst Platz für ein Zeichen.
    Da aber Zeichenketten in C durch ein '\0' Zeichen beendet werden, kanns du dort nichts ablegen.

    Für den Anfang machts ein

    char* my_string = malloc(1000);
    

    sizeof(char) ist per definition 1.



  • Ah okay, aber wie kann ich das reallocieren, wenn mehr als 300 zeichen eingegeben werden?



  • Mit realloc

    Dazu gibt es hier im Unterforum auch reichlich Anfragen und Beispiele.



  • Wenn Du nur strlen verwenden darfst, ist das Vorhaben grundsätzlich zum Scheitern verurteilt 😃

    Aber Du benutzt ja auch printf und scanf. Angenommen also, Du darfst printf, scanf, strlen und malloc nutzen, müsstest Du in einer Schleife mit "%c" einzelne Zeichen einlesen, bis das Zeichen '\n' (Newline, ausgelöst durch Eingabetaste) gelesen wurde. Nur dann kannst Du darauf reagieren, dass mehr Zeichen eingegeben werden, als Speicher zur Verfügung steht.

    So grob könnte der Ablauf wie folgt aussehen:
    1. Allokieren von X Zeichen
    2. Einlesen mit %c in das jeweils nächste unbenutzte Zeichen
    3. Prüfen, ob eingelesenes Zeichen '\n' ist, wenn ja, durch '\0' ersetzen um den String zu terminieren
    4. Prüfen, ob die nächste Position noch in den allokierten Bereich passt, wenn nicht, allokieren von (z.B.) X*2 Zeichen und kopieren des bisherigen Strings in den neuen Bereich (realloc erledigt das für Dich)

    5. Rückwärts ausgeben (hierfür brauchst Du theoretisch nichtmal strlen, denn Du hast ja irgendwo mitgezählt, um 4 zu ermöglichen)



  • TADAAAA!!! 😃
    Danke für eure Hilfen 😉

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void) 
    {
    	int max = 10;
    	int input;
    	int counter = 0;
    	char* my_string;
    
    	my_string = malloc(max);
    
    	printf("Geben Sie nun Ihre Zeichenkette ein:\n");
    
    	do
    	{
    		input = getchar();
    		my_string[counter] = input;
    		counter++;
    
    		if(counter == max)
    		{
    			max += max;
    		}
    
    		my_string = realloc(my_string, max);
    
    	} while(input != '\n');
    
    	my_string[counter] = '\0';
    
    	printf("Ihre Zeichenkette war:\n");
    	printf("%s", my_string);
    
    	printf("Ihre Zeichenkette rueckwaerts ist:");
    
    	for(counter; counter >= 0; counter--)
    	{
    		printf("%c", my_string[counter]);
    	}
    }
    


  • Jetzt hast du ja doch getchar() 🙂

    Wenn realloc keinen Speicher mehr belegen konnte, gibt es NULL zurück und ändert nichts an dem Speicher.
    Dann ist bei dir der Ort des Speichers aber schon verloren gegangen, da dann in my_string NULL steht. (Dann stürzt dein Programm auch ab).

    Dir ist auch klar, das der belegte Speicher immer verdoppelt wird?
    10 -> 20 -> 40 -> 80 -> 160 ..



  • Jo hab getchar() verwendet.

    Das war ne alte Klausur-Aufgabe und ich denke mir: "Leck mich am Arsch Professor!" 😉 Dann gibts halt nen Punkt abzug 😉

    Wegen dem realloc = NULL:

    Reicht ja wenn ich das noch über nen If Abfange und dann ausgebe, dass keine
    reallocierung mehr möglich war.

    Und ja die Verdopplung ist mir klar, etwas unellegant aber es soll ja nicht wirklich ein "anwendbares" programm sein sondern nur eine Lösung für eine Klausur aufgabe 😉


  • Mod

    C-Verzweifler schrieb:

    Und ja die Verdopplung ist mir klar, etwas unellegant aber es soll ja nicht wirklich ein "anwendbares" programm sein sondern nur eine Lösung für eine Klausur aufgabe 😉

    Eigentlich ist das sogar eine sehr intelligente Strategie.



  • SeppJ schrieb:

    C-Verzweifler schrieb:

    Und ja die Verdopplung ist mir klar, etwas unellegant aber es soll ja nicht wirklich ein "anwendbares" programm sein sondern nur eine Lösung für eine Klausur aufgabe 😉

    Eigentlich ist das sogar eine sehr intelligente Strategie.

    Begründung: Bei Verdoppelung des vorhandenen Speicherplatzes (generell bei Vervielfachung um einen Faktor > 1) hat das Anfügen eines neuen Zeichens trotz gelegentlicher Hin- und Herkopiererei amortisiert konstante Laufzeitkomplexität. Bei einer Verdoppelung werden für jedes neue Zeichen im Durchschnitt zwei Schreiboperationen fällig.


Anmelden zum Antworten