Was ist falsch ?



  • Habe eine Problem mit meinem Programm welches ich für die Schule schreiben soll.
    Geht darum, zwei Binäre Zahlen a und b mit den Grundoperatoren verschieden zu verknüpfen ( Shiften, and, or , etc.

    Mein Code schaut folgendermaßen aus :

    bm ist die Bitmaske für die Ausgabe der Binärzahl. Das funktioniert soweit auch alles.
    Aber im main funktioniert nur die erste Ausgabe.
    Danach zeigt er mir nichts mehr an.

    #include <stdio.h>
    
    unsigned char a = 0x1C;      //00011100
    unsigned char b = 0x55;     // 01010101
    unsigned char bm = 0x80;
    int i;
    
    void CharAlsBinaryAusgeben(unsigned char zahl)
    {
    
    	for (i=0; i<8; i++)
    	{
    		if ((zahl&bm)>0)
    			printf("1");
    		else
    			printf("0");
    
    		bm = bm>>1;
    
    	}		
    
    }
    
    void main()
    
    {
    
    //- a >> 1
    
    	printf("\na>>1   "); 
    	CharAlsBinaryAusgeben(a); 
    	printf("  >> 1 = "); 
    	CharAlsBinaryAusgeben(a>>1); 
    	printf("\n\n");	
    
    //- a << 2
    
    	printf("\na<<2:  ");
    	CharAlsBinaryAusgeben(a);
    	printf("  << 2 = ");
    	CharAlsBinaryAusgeben(a<<2);
    	printf("\n\n");	
    
    }
    


  • Nichts mehr, oder nur noch 00000000?

    Falls Letzteres, dann liegt es daran, daß nach dem ersten Aufruf der Ausgabefunktion bm den Wert 0 hat.



  • genau , 00000000

    Immer alles Nullen anstatt der geshifteten Werte.

    Naja die Bitmaske 10000000 wird ja geshiftet oben. und wenn ich direkt bei der ersten ausgabe (a>>1) ausgeben lasse dann funktioniert es auch.
    Aber ab der zweiten ausgabe kommt eben nur mehr 0.



  • bm ist ja auch global!
    Beim 2. Aufruf steht halt 0 drin.

    Das unsigned char bm = 0x80; gehört in deine Ausgabefunktion.



  • Das int i; gehört natürlich auch in die Funktion

    Zählvariablen global zu machen gibt mit die schönsten Fehler.

    Im Übrigen sollten auch a und b in main definiert werden.



  • Danke !
    Du hast natürlich recht .... fällt mir jetzt erst auf.
    Muss ich wohl etwas genauer arbeiten.

    Danke erstmal,funktioniert nun einwandfrei.



  • Habe nun noch ein Problem.
    Denke es liegt wieder an der Art der Variabel Deklaration.

    Der Code soll einen String 123456 in einen Integer wandeln, und dann wieder zurück in einen String.
    Funktioniert soweit auch alles, aber bei der Ausgabe habe ich ein Problem.

    Schaut so aus : http://www.abload.de/image.php?img=unbenannt4h6m.jpg

    Die Erste Zeile wo der String in TEXT gewandelt wird stimmt.
    Und das Ergebnis der zweiten Zeile bei der Rückwandlung auch, aber er schreibt mir in der zweiten Zeile statt dem Int Wert der Variable "zahl" nur eine 0 hin.

    Hier ist der Code :

    #include <stdio.h>
    
    unsigned int zahl;
    unsigned char t[6];
    unsigned char zahl_als_text[7] = {'1','2','3','4','5','6','\0'};
    
    int TextInZahlUmwandeln()
    {
    
    	unsigned int i;
    
    	i=0;
    	zahl=0;
    
    	for (i=0;i<6;i++)
    	{
    		zahl = zahl*10;	
    		zahl = (zahl + zahl_als_text[i]-0x30);
    
    	}	
    
    	return zahl;	
    }
    
    void ZahlInTextUmwandeln()
    {
    
    	unsigned int h;
    	int i;
    	unsigned int anzahl_stellen;
    
    	zahl = zahl;
    	anzahl_stellen=6;
    	t[6] = 0;
    
    	for (i=anzahl_stellen-1; i>=0; i--)
    	{
    		h = zahl % 10;
    		t[i] = h+'0';
    		zahl = ( zahl - h )/10;
    
    	}	
    
    }
    
    int main()
    
    {
    
    	TextInZahlUmwandeln();
    	printf("TEXT %s ergibt umgewandelt in eine Zahl %i\n",zahl_als_text, zahl);
    
    	ZahlInTextUmwandeln();
    	printf("%i umgewandelt in einen TEXT ergibt: %s\n", zahl,t);
    
    return 0;
    }
    

    Ich blicke bei den Funktionen nicht so richtig durch, deshalb hab ich die Variablen der Funktionen global definiert ... steckt da der Fehler dahinter ?



  • saabzero schrieb:

    ..global definiert ... steckt da der Fehler dahinter ?

    Im Zweifelfall immer. Warum machst du das denn überhaupt?

    int TextInZahlUmwandeln();
    // sollte so aussehen
    int TextInZahlUmwandeln(const char* text);
    void ZahlInTextUmwandeln();
    // sollte so aussehen
    int ZahlInTextUmwandeln(int zahl, char* buffer, int len);
    // Der Returnwert ist 0, wenn der Buffer zu klein ist, sonst 1
    // Die Anzahl der Stellen einer Zahl kannst du ganz leicht ausrechnen
    // Edit: Bei einer negativen Zahl muss 1 Stelle mehr für das Minuszeichen eingeplant werden.
    int stellen(int i)
    {
        int ret=1;
        while(i/=10) ++ret;
        return ret;
    }
    

    Wenn TextInZahlUmwandeln einen const char* entgegen nimmt, kannst du auch Folgendes machen.

    // statt
    unsigned char zahl_als_text[7] = {'1','2','3','4','5','6','\0'};
    // so etwas
    const char* pNr = "123456";
    zahl = TextInZahlUmwandeln(pNr);
    

    Probiere mal, ob du es so hinbekommst. Einige Dinge wie zahl = ( zahl - h )/10; sehen mir, nun ja, etwas komisch aus.



  • Ich möchte den Code ehrlich gesagt weitgehend so lassen wie er ist, eben nur diesen Fehler beseitigen.

    Das mit ( zahl - h ) / 10 stimmt schon , die Umwandlung selber funktioniert ja auch, nur zeigts mir vorne eben den int wert als 0 an beim ausführen.

    Aber danke schonmal.



  • wieso nummst du nicht atoi() und sprintf()?



  • Binggi schrieb:

    wieso nummst du nicht atoi() und sprintf()?

    Weil der Sinn der Übung eben ist die Funktion selber zu schreiben, sonst hätt ich schon längst atoi genommen.



  • saabzero schrieb:

    Binggi schrieb:

    wieso nummst du nicht atoi() und sprintf()?

    Weil der Sinn der Übung eben ist die Funktion selber zu schreiben, sonst hätt ich schon längst atoi genommen.

    Dann ist es nicht schlecht sich an atoi und itoa bezüglich der Parameter zu orientieren.

    Du hast in ZahlInTextUmwandeln

    zahl = ( zahl - h )/10;
    

    Dadurch wird zahl verändert. zahl ist global. Was erwartest du?

    Statt ( zahl - h ) / 10 reicht zahl/10 da das mit Integern gemacht wird. Dann aber bitte lokal.



  • [quote="saabzero"]

    unsigned char bm = 0x80;
    int i;
    
    void CharAlsBinaryAusgeben(unsigned char zahl)
    {
    
    	for (i=0; i<8; i++)
    	{
    		if ((zahl&bm)>0)
    			printf("1");
    		else
    			printf("0");
    
    		bm = bm>>1;
    
    	}		
    
    }
    

    also das ist schon mal sicher falsch... ich würde bm=1 nehmen und dann in einen string schreiben und dann den string drehen. das sollte das einfachste sein.

    zahl = (zahl + zahl_als_text[i]-0x30);
    

    ist auch falsch.

    @edit falls du bei deinem 0x80 bleiben willst musst du in die andere richtung shiften, und ne flag einführen weil die ausgabe erst nach der ersten 1 beginnen sollte..



  • [quote="_--"]

    saabzero schrieb:

    unsigned char bm = 0x80;
    int i;
    
    void CharAlsBinaryAusgeben(unsigned char zahl)
    {
    	
    
    	for (i=0; i<8; i++)
    	{
    		if ((zahl&bm)>0)
    			printf("1");
    		else
    			printf("0");
    
    		bm = bm>>1;
    		
    	}		
    		
    }
    

    also das ist schon mal sicher falsch... ich würde bm=1 nehmen und dann in einen string schreiben und dann den string drehen. das sollte das einfachste sein.

    zahl = (zahl + zahl_als_text[i]-0x30);
    

    ist auch falsch.

    @edit falls du bei deinem 0x80 bleiben willst musst du in die andere richtung shiften, und ne flag einführen weil die ausgabe erst nach der ersten 1 beginnen sollte..

    Warum soll das falsch sein ?
    Das Programm funktioniert so.



  • saabzero schrieb:

    Warum soll das falsch sein ?
    Das Programm funktioniert so.

    huch, ja hast natürlich recht, dachte du verschiebst die variable und nicht die maske 🤡



  • Das ist falsch. Versuch das mal mehrere Male hintereinander aufzurufen. Warum verwendest du für Alles globale Variablen?



  • Vicious Falcon schrieb:

    Das ist falsch. Versuch das mal mehrere Male hintereinander aufzurufen. Warum verwendest du für Alles globale Variablen?

    Inwiefern falsch ?

    Ich hab mir das auf einem Blatt Papier schön durchüberlegt, sollte ansich doch stimmen.
    Ich shifte die Maske 0x80 mit jedem Schleifendurchgang eine Stelle weiter nach rechts und Frage damit die Zahl a bzw. b mit & ab.

    Und das Programm lässt sich so auch ausführen und funktioniert.

    Das mit den Variablen ist so.
    Ich programmier jetzt seit ca. 2 Wochen ... bin also quasi ein n00b... und die Funktionen verstehe ich noch nicht wirklich ganz.
    Sprich wenn ich die jeweiligen Variablen in den Funktionen deklariere habe ich Probleme mit diese dann ins Main zu bringen bei der Ausgabe ... schwer zu erklären mein Problem, aber hoffe wenn ich mich weiter mit der Materie beschäftige wird das.



  • Beim ersten Aufruf ist das Ergebnis ja noch richtig. Ich hatte geschrieben, dass du die Funktion mal mehrere Male nacheinander aufrufen solltest:

    CharAlsBinaryAusgeben(32);
    CharAlsBinaryAusgeben(48);
    

    Du veränderst die global definierte Maske, initialisierst sie aber nicht wieder.
    Bei folgenden Aufrufen testest du also nur gegen 0. Dies ist wieder Mal ein Fall, der zeigt, dass globale Variablen zu fehleranfälligem Code führen können. Hättest du sie lokal definiert und gleich initialisiert, wäre alles in Ordnung.

    Nur am Rande: Eine Maske brauchst du auch nicht unbedingt, und da du den Rechtsshift schon verwendet hast:

    void Ausgabe(unsigned char c)
    {
        int i=7;
        for(;i>=0;--i)
            printf("%d",((c>>i) & 1));
        puts("");
    }
    

    c>>i verschiebt, wie du ja weißt, die Bits um i stellen nach rechts, von links werden Nullen aufgefüllt. & 1 testet nun, ob das niedrigstwertige Bit (20) gesetzt ist.
    Eine if-Abfrage braucht man auch nicht unbedingt. Die Ausgabe ist entweder
    1 & 1 = 1 -> Bit gesetzt.
    0 & 1 = 0 -> Bit nicht gesetzt.

    Edit: Falls du mit einem C99-fähigen Compiler arbeitest, kannst du int i = 7 auch direkt in den Schleifenkopf schreiben. i ist dann nur im Schleifenkörper sichtbar.


Anmelden zum Antworten