Palindrom in C erkennen



  • ach ok, hab das geändert in %s und das & weggemacht. leider sagt er immer noch jedes mal das es kein palindrom ist, egal was ich eingebe.



  • Dann gib doch mal die beiden Strings aus. (Bsp. s.o)
    Evtl sind sie ja wirklich unterschiedlich.
    Möglicherweise kopierst du zu viel Zeichen beim Umdrehen.

    Mach mal bei der Umkehrschleife:

    for(;i>=0;i--, j++){
      string2[j]=string[i];
      printf("Zeichen bei %d|%d: %c, Wert: %d \n", i, j, string2[j], string[i]);
    }
    printf("Vergleiche <%s> mit <%s>\n", string, string2);
    


  • #include <ctype.h>
    #include <string.h>
    #include <stdio.h>
    
    int is_palindrome( char const *beg, char const *end )
    {
    	if( !( beg && end ) )
    		return 0;
    
    	--end;
    
    	if( !*end || !isprint( *end ) )
    		--end;
    
    	while( beg < end )
    		if( *beg++ != *end-- )
    			return 0;
    
    	return 1;
    }
    
    int main()
    {
    	char const *text = "abcba";
    	printf( "\"%s\" %s a palindrome.", text,
    		is_palindrome( text, text + strlen( text ) + 1 ) ? "is" : "isn't" );
    }
    


  • mm ok, kommt folgendes raus:

    Bitte geben Sie ein Wort ein, das Pr. ueberprueft, ob es sich um ein Palindrom h
    andelt:
    otto
    Zeichen bei 4|0: , Wert: 0
    Zeichen bei 3|1: o, Wert: 111
    Zeichen bei 2|2: t, Wert: 116
    Zeichen bei 1|3: t, Wert: 116
    Zeichen bei 0|4: o, Wert: 111
    Vergleiche <otto> mit <>
    Kein Palindrom
    Process returned 0 (0x0) execution time : 1.547 s
    Press any key to continue.

    er gleicht unten otto mit gar nichts, wieso das?



  • Das erste Zeichen das du kopierst, hat den Wert 0 (oder '\0') und ist an der Position 4.
    Wo kommt das her? und warum Position 4?

    Du hast:

    while (string[i] != '\0'){
                                    i++;
                                }
    

    Welchen Wert hat i, wenn du auf die '\0' triffst?



  • vfbf4n1893 du hast mit deiner schleife übrigens ein wert zu viel kopiert, die '\0' brauchst du nicht.

    for( ; i > 0; i--, j++) string2[j]=string[i];
    


  • akoww schrieb:

    vfbf4n1893 du hast mit deiner schleife übrigens ein wert zu viel kopiert, die '\0' brauchst du nicht.

    Doch, die '\0' braucht er. Aber an einer anderen Stelle.

    akoww schrieb:

    for( ; i > 0; i--, j++) string2[j]=string[i];
    

    Damit kopierst du aber auch die '\0' (Die steht an Stelle string[i] beim ersten Durchlauf)



  • vfbf4n1893 schrieb:

    ach ok, hab das geändert in %s und das & weggemacht. leider sagt er immer noch jedes mal das es kein palindrom ist, egal was ich eingebe.

    Noch zwei Fehler:

    1. Die Anzahl der Zeichen in string ist nicht der letzte Index in der Zeichenkette string. Füg mal hinter die While-Schleife noch ein
    i--;
    

    ein.

    1. string2 hat noch keine Abschlussnull. Füg mal hinter die For-Schleife noch ein
    string2[j]=0;
    

    ein.

    viele grüße
    ralph



  • ok das wars, nun geht es... das 1. ist mir klar. i war um 1 zu hoch.
    kannst du das 2. nochmal genau erkläre, was macht genau das =0?

    rkhb schrieb:

    vfbf4n1893 schrieb:

    ach ok, hab das geändert in %s und das & weggemacht. leider sagt er immer noch jedes mal das es kein palindrom ist, egal was ich eingebe.

    Noch zwei Fehler:

    1. Die Anzahl der Zeichen in string ist nicht der letzte Index in der Zeichenkette string. Füg mal hinter die While-Schleife noch ein
    i--;
    

    ein.

    1. string2 hat noch keine Abschlussnull. Füg mal hinter die For-Schleife noch ein
    string2[j]=0;
    

    ein.

    viele grüße
    ralph



  • Weißt du wofür die '\0' (oder 0) in einem String da ist?



  • das ist immer das letzte zeichen im string, das weiß ich. jedoch weiß ich nicht, was der befehl soll string2[j]=0;



  • vfbf4n1893 schrieb:

    das ist immer das letzte zeichen im string, das weiß ich. jedoch weiß ich nicht, was der befehl soll string2[j]=0;

    Welchen Wert hat denn j am Ende der for-Schleife?



  • vfbf4n1893 schrieb:

    kannst du das 2. nochmal genau erkläre, was macht genau das =0?

    rkhb schrieb:

    ...
    2) string2 hat noch keine Abschlussnull. Füg mal hinter die For-Schleife noch ein

    string2[j]=0;
    

    ein.

    Ein C-String besteht nicht nur aus den Buchstaben, sondern zusätzlich noch aus einer Null hintendran. Damit weiß man, wo der String zu Ende ist. Ein Wort aus 5 Buchstaben benötigt also ein Zeichenkettenarray mit (mindestens) 6 chars. Bei Deinem Programm zeigt j nach Beendigung der For-Schleife auf das Byte hinter den Buchstaben. Genau dort gehört eine Null hin und genau dorthin wird eine Null gespeichert.

    viele grüße
    ralph



  • 4?, ach da sagst du dem string, dass er hier fertig ist. ansonsten kommen irgendwelche werte da hin?



  • Genau.

    Die Erklärung hat schon rkhb geschrieben.



  • und wenn ich den scanf befehl ausführe wird beim 1. string die 0 automatisch drangehängt?



  • Swordfish schrieb:

    #include <ctype.h>
    #include <string.h>
    #include <stdio.h>
     
    int is_palindrome( char const *beg, char const *end )
    {
        if( !( beg && end ) )
            return 0;
     
        --end;
     
        if( !*end || !isprint( *end ) )
            --end;
     
        while( beg < end )
            if( *beg++ != *end-- )
                return 0;
     
        return 1;
    }
     
    int main()
    {
        char const *text = "abcba";
        printf( "\"%s\" %s a palindrome.", text,
            is_palindrome( text, text + strlen( text ) + 1 ) ? "is" : "isn't" );
    }
    

    Ähm, isprint in einem Wort? 🤡

    int is_palindrome ( const char* s )
    {
    	char* a = s, *b = a + strlen( s ) - 1;
    	while ( *a == *b && a < b )
    		a++, b--;
    	return *a == *b;
    }
    
    int main ( void )
    {
    	printf ("%d\n", is_palindrome ( "ABBA" ));
    	printf ("%d\n", is_palindrome ( "ABxBA" ));
    	printf ("%d\n", is_palindrome ( "A" ));
    	printf ("%d\n", is_palindrome ( "AA" ));
    	printf ("%d\n", is_palindrome ( "!AaaahhhaaaA!" ));
    	printf ("%d\n", is_palindrome ( "blubb" ));
    	return 0;
    }
    

    vfbf4n1893 schrieb:

    das ist immer das letzte zeichen im string, das weiß ich. jedoch weiß ich nicht, was der befehl soll string2[j]=0;

    Angenommen der string ist char string2[] = "Ottos Motto"; int j = 4;
    Dann verkürzt die Zuweisung string2[j] = 0; den String denn ein strlen(string2) liefert nun einen anderen Wert als vor der Zuweisung und ein puts(string2); zeigt Otto an. Alle Buchstaben bis auf das s, das durch die 0 ersetzt wurde, sind aber immer noch im char Array enthalten.



  • vfbf4n1893 schrieb:

    und wenn ich den scanf befehl ausführe wird beim 1. string die 0 automatisch drangehängt?

    Ja.
    Alle Stringfunktionen tun dies und verlassen sich auch darauf, das eine 0 am Ende ist.

    Alle? Nein! strncpy macht das nicht immer.



  • CJosef schrieb:

    Ähm, isprint in einem Wort? 🤡

    Denkfehler bei der Umsetzung oben, aber:

    #include <ctype.h>
    #include <string.h>
    #include <stdio.h>
    
    int my_is_palindrome( char const *beg, char const *end )
    {
    	if( !( beg && end ) )
    		return 0;
    
    	--end;
    
    	if( !*end )
    		--end;
    
    	while( !isprint( *end ) )
    		--end;
    
    	while( beg < end )
    		if( *beg++ != *end-- )
    			return 0;
    
    	return 1;
    }
    
    int your_is_palindrome( const char* s )
    {
        char const * a = s, *b = a + strlen( s ) - 1;
        while ( *a == *b && a < b )
            a++, b--;
        return *a == *b;
    }
    
    int main()
    {
    	char buffer[ 80 ];
    
    	fgets( buffer, sizeof( buffer ), stdin ); // <- ABBA
    
    	printf( "%s", buffer );
    
    	printf( "my_is_palindrome():   %d\n",   my_is_palindrome( buffer, buffer + strlen( buffer ) + 1 ) );
    	printf( "your_is_palindrome(): %d\n", your_is_palindrome( (char const*) buffer ) );
    }
    


  • Swordfish schrieb:

    CJosef schrieb:

    Ähm, isprint in einem Wort? 🤡

    printf( "my_is_palindrome():   %d\n",   my_is_palindrome( buffer, buffer + strlen( buffer ) + 1 ) );
    	printf( "your_is_palindrome(): %d\n", your_is_palindrome( (char const*) buffer ) );
    }
    

    🤡

    Das \n pult man vor der Benutzung des Puffers während der Eingabe in einer schnuckelig ausgelagerten Eingabefunktion raus.
    💡 Dann brauchen sich die zig Millionen Funktionen in deinem Projekt nicht ums \n zu kümmern und dein Code sowie die ausführbare Datei werden deutlich kleiner.

    // Entfernt, sofern vorhanden, den letzten Zeilenvorschub aus buf durch Überschreiben mit 0.
    char* remove_linefeed ( char* buf )
    {
    	char* p = strrchr ( buf, '\n' ); 
    	if ( p )
    		*p = 0; // Überschreibt den Zeilenvorschub mit 0.
    	return p;
    }
    
    int read_stdin ( char* buf, size_t bufsize )
    {
    	fgets ( buf, bufsize, stdin );
    	remove_linefeed ( buf );
    	return ferror ( stdin );
    }
    
    int main ( void )
    {  
    	char buf [ 80 ];
    	if ( read_stdin ( buf, sizeof ( buf )))
    	{
    		// Error handling ..
    	}
    	else
    	{
    		// Continue coding tidily, call slim functions ...
            process ( buf );
    	}
    
    	return 0;
    }
    

Anmelden zum Antworten