BCD-Format



  • Siegfried101 schrieb:

    Wenn ich das mit double x umsetze, wie in der Aufgabenstellung beschrieben dann weiß ich nicht wie das bezüglich des Arrays funktionieren soll.

    Lass Dich nicht verwirren, Dein Gedankengang ist schon richtig: Erst Double nach String (Stichwort: sprintf) und dann String nach BCD.

    DirkB schrieb:

    Und der cast bei malloc ist in C auch niht nötig.

    Was genau meinst du damit?

    Probier mal aus, ob Dein Compiler meckert, wenn Du (struct bcd_number *) bzw. (unsigned char *) vor malloc weglässt. Das wäre nämlich richtiger. Sonst lass es dran.

    DirkB schrieb:

    Du prüfst nirgends, ob du wirklich Ziffern hast. (Tipp: isdigit())

    Ich darf nur stdio.h und stdlib.h benutzen. Gibt es noch eine Alternative zu isdigit()?

    Wenn Du das Double nach String richtig umgewandelt hast, musst Du nicht prüfen, ob da ein richtiger Double-String vorliegt. 🙂 Kümmere Dich besser um die andere Funktion!

    viele grüße
    ralph



  • Siegfried101 schrieb:

    DirkB schrieb:

    Und der cast bei malloc ist in C auch niht nötig.

    Was genau meinst du damit?

    Der Ausrduck in Klammern, der die explizite Typumwandlung angibt heisst cast. Der ist in C nicht nötig, da void-Zeiger in alle anderen implizit umgewandelt werden.
    Wenn dein Compiler da meckert, ist dein Compiler auf den C++ Modus eingestellt. C++ braucht den cast.

    Siegfried101 schrieb:

    DirkB schrieb:

    Überlesen von führenden Leerzeichen wäre nicht schlecht.

    Mit welchen Befehlen mache ich das?

    Dafür gibt es keinen Befehl. Selber machen.

    while (x[j]==' ')
            j++;
    

    Siegfried101 schrieb:

    DirkB schrieb:

    Du prüfst nirgends, ob du wirklich Ziffern hast. (Tipp: isdigit())

    Ich darf nur stdio.h und stdlib.h benutzen. Gibt es noch eine Alternative zu isdigit()?

    Ein Vergleich auf >='0' und <= '9' solltest du hinbekommen. Am besten in einer eigenen Funktion.

    Und double ist kein Array sonderen ein Zahlentyp für Fließkommazahlen.
    Da musst du ähnlich rechnen wie bei int, damit du an die einzelnen Stellen kommst.



  • Die double-to-string Umwandlung führe ich jetzt direkt in der Funktion aus.

    struct bcd_number * string2bcd(double x){
    
        struct bcd_number *b;
        int j,k;
    
        int deztren;
    
        const char *s;
    
        /* double in string umwandeln*/
        sprintf(*s,"%f",x);
    
        /* Speicher reservieren  */
        b=malloc(sizeof(struct bcd_number));
    
        b->laenge=0;
        b->nachkommastellen=0;
        b->vorzeichen=1;
    
        j=0;
        /* Negatives Vorzeichen detektieren */
        if (s[j]=='-'){
            b->vorzeichen*=-1;
            j++;
        }
    
        /* zunächst erforderliche Längen bestimmen */
        /* bislang kein Dezimaltrenner erkannt */
        deztren=0;
        /* durchlaufen bis zum Stringende */
        for (; s[j]!='\0'; j++){
            if (s[j]=='.')
            /* Flag für erkannten Dezimaltrenner setzen */
                deztren=1;
            else{
                b->laenge++;
                if (deztren)
                    b->nachkommastellen++;
            }
        }
    
        /* Ziffernarray dynamisch reservieren entsprechend den nun bekannten Längen */
        b->ziffern=malloc(b->laenge*sizeof(unsigned char));
        /* zurück auf Anfang */
        j=0;
    
        if (s[j]=='-')
            j++;
    
        /* String durchlaufen und BCD-Ziffern übernehmen */
        k=0;
        for (; s[j]!='\0'; j++)
            if (s[j]!='.')
                b->ziffern[k++]=s[j]-'0';
    
        return b;
    }
    

    Würde die Funktion, so wie sie hier steht, funktionieren? Der Compiler meckert nämlich bei den Zeilen mit den Pfeilen ("->") oder liegt es daran, dass ich noch kein richtiges Programm habe?
    Um die Feinheiten, wie Leerzeichen überlesen etc., kümmere ich mich dann am Ende.

    Nach welchem Schema muss ich in der zweiten Funktion vorgehen? Ich muss ja den BCD-Code wieder in double umwandeln. Da fehlt mir jetzt irgendwie der Ansatz, weil einfach das ganze rückwärts funktioniert ja nicht.



  • Siegfried101 schrieb:

    const char *s;
    
        /* double in string umwandeln*/
        sprintf(*s,"%f",x);
    

    s ist so ein Zeiger, der irgendwohin - wahrscheinlich ins Nirwana - zeigt. Deshalb würde sprintf irgendwohin - wahrscheinlich mit Absturz - schreiben. So ist es richtig:

    #include <stdio.h>
    #include <stdlib.h>
    
    struct bcd_number
    {
    	unsigned int laenge;
    	unsigned int nachkommastellen;
    	char vorzeichen;
    	unsigned char *ziffern;
    };
    
    struct bcd_number * string2bcd(double x){
    
        struct bcd_number *b;
        int j,k;
        int deztren;
    
        char s[512];
    
        /* double in string umwandeln*/
        sprintf(s,"%.10f",x);
    
        /* Speicher reservieren  */
        b=malloc(sizeof(struct bcd_number));
    
        b->laenge=0;
        b->nachkommastellen=0;
        b->vorzeichen=1;
    
        j=0;
        /* Negatives Vorzeichen detektieren */
        if (s[j]=='-'){
            b->vorzeichen*=-1;
            j++;
        }
    
        /* zunächst erforderliche Längen bestimmen */
        /* bislang kein Dezimaltrenner erkannt */
        deztren=0;
        /* durchlaufen bis zum Stringende */
        for (; s[j]!='\0'; j++){
            if (s[j]=='.')
            /* Flag für erkannten Dezimaltrenner setzen */
                deztren=1;
            else{
                b->laenge++;
                if (deztren)
                    b->nachkommastellen++;
            }
        }
    
        /* Ziffernarray dynamisch reservieren entsprechend den nun bekannten Längen */
        b->ziffern=malloc(b->laenge*sizeof(unsigned char));
        /* zurück auf Anfang */
        j=0;
    
        if (s[j]=='-')
            j++;
    
        /* String durchlaufen und BCD-Ziffern übernehmen */
        k=0;
        for (; s[j]!='\0'; j++)
            if (s[j]!='.')
                b->ziffern[k++]=s[j]-'0';
    
        return b;
    }
    
    int main( void )
    {
    	double eingabe = -2345.2;
        struct bcd_number* bcd;
    	size_t i;
    
    	bcd = string2bcd (eingabe);
    
    	printf ("Eingabe:              %f\n",eingabe);
    	printf ("bcd.laenge:           %u\n",bcd->laenge);
    	printf ("bcd.nachkommastellen: %u\n",bcd->nachkommastellen);
    	printf ("bcd.vorzeichen:       %i\n",bcd->vorzeichen);
    	printf ("bcd.ziffern:          ");
    	for (i=0; i<bcd->laenge; ++i) printf ("%i ",bcd->ziffern[i]);
    	puts ("\n");
    
    	free (bcd->ziffern);
    	free (bcd);
    
    	return 0;
    }
    

    Hier mal zu Weihnachten meine Version. Zwar mit math.h, aber vielleicht kannst Du ein paar Ideen verwerten:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
    struct bcd_number
    {
    	unsigned int laenge;
    	unsigned int nachkommastellen;
    	char vorzeichen;
    	unsigned char *ziffern;
    };
    
    struct bcd_number* double2bcd(double x)
    {
    	char tmp[512];
    	struct bcd_number* bcd = malloc (sizeof(struct bcd_number));
    	double vor, nach = modf (x, &vor);
    	bcd->ziffern = malloc (512);
    	char* z = (char*) bcd->ziffern;
    	sprintf (tmp,"%.f",fabs(vor));
    	bcd->laenge = strlen(tmp);
        bcd->vorzeichen = (vor < 0) ? '-' : '+';
    	for (size_t i=0; i<bcd->laenge; ++i) { *z++ = tmp[i] - '0';	}
    	sprintf (tmp,"%.40f",fabs(nach));
    	for (size_t i = strlen(tmp)-1; i!=0; --i) if (tmp[i] != '0') { tmp[i+1] = 0; break; }
    	bcd->nachkommastellen = strlen(tmp+2);
    	bcd->laenge += bcd->nachkommastellen;
    	for (char* t = tmp + 2; *t; *z++ = *t++ - '0');
    	bcd->ziffern = realloc (bcd->ziffern, bcd->laenge);
    	return bcd;
    }
    
    double bcd2double (struct bcd_number* b)
    {
    	char tmp[512];
    	char* t = tmp;
        unsigned char * z = b->ziffern;
    	unsigned i, imax;
    	*t++ = b->vorzeichen;
    	for (i = 0, imax = b->laenge - b->nachkommastellen; i < imax; ++i) sprintf (t++,"%u",*z++);
    	*t++ = '.';
    	for (imax = b->laenge; i < imax; ++i) sprintf (t++,"%u",*z++);
    	*t = 0;
    	return atof (tmp);
    }
    
    int main( void )
    {
    	double eingabe = -2345.2;
    	printf ("Eingabe: %f\n\n",eingabe);
    
    	struct bcd_number* bcd = double2bcd(eingabe);
    	printf ("bcd.laenge:           %u\n",bcd->laenge);
    	printf ("bcd.nachkommastellen: %u\n",bcd->nachkommastellen);
    	printf ("bcd.vorzeichen:       %c\n",bcd->vorzeichen);
    	printf ("bcd.ziffern:          ");
    	for (size_t i=0; i<bcd->laenge; ++i) printf ("%i ",bcd->ziffern[i]);
    	puts ("\n");
    
    	double dobbel = bcd2double (bcd);
    	printf ("Double (evtl von printf gerundet): %f\n",dobbel);
    
    	free (bcd->ziffern);
    	free (bcd);
    
    	return 0;
    }
    

    :xmas1:

    Frohe Weihnachten
    ralph



  • Der genaue Mecker (Wortlaut) vom Compiler wär schon interessant wenn man dir helfen soll.

    Und dein

    const char *s;
    
        /* double in string umwandeln*/
        sprintf(*s,"%f",x);
    

    funktioniert so nicht, da du weder s initialisiert hast und somit s auch auf keinen sinnvollen Speicher zeigt.
    Ein Array für genug ZEichen sollte reichen.

    Auch gibt das %f sechs Nachkommastellen aus, was für deinen Zweck auch nicht ausreicht. Du kannst auch mehr Nachkommstellen angeben, das ergibt für sehr kleine Werte trotzdem falsche Werte.

    Schau dir mal den Formatspecifier %g an oder Versuch es mal mit log10.



  • außer einer viel zu umständlichen 🙄 😃 und ungenauen aufteilung einer double zahl in ziffern hat das ja noch nicht allzu viel mit bcd zu tun, oder?
    😃



  • dr. arrogance schrieb:

    außer einer viel zu umständlichen 🙄 😃 und ungenauen aufteilung einer double zahl in ziffern...

    Besser machen, nicht nur Sprüche klopfen! :p

    rkhb schrieb:

    ...
    Hier mal zu Weihnachten meine Version.
    ...

    Okay, weil Weihnachten ist, 🤡
    lasse ich mich auch nicht lumpen.
    Kommt mit unter den Weihnachtsbaum. :xmas1: :xmas2:
    .oO Ein bisschen eigenartig die Aufgabe ... double to BCD ... .oO .oO .oO .. aber man gönnt sich ja sonst nichts! 😮

    #include <stdio.h>
    #include <stdlib.h>
    
    struct bcd_number
    {
        int laenge, nachkommastellen;
        char vorzeichen, *ziffern;
    };
    
    int double2bcd(struct bcd_number* pbcd, double x)
    {
        char buf[CHAR_BIT*sizeof(x)+2]; int len = sprintf(buf, "%lf", x); char *p = buf + len -1;
    	x < 0 ? pbcd->vorzeichen = -1 : (pbcd->vorzeichen = 1);
    	while ( p >= buf && '0' == *p )
    			p--;
    	for ( ; p >= buf && *p >= '0' && *p <= '9'; p-- )
    		pbcd->laenge++, pbcd->nachkommastellen++;
    	if ( p >= buf && '.' != *p )
    		pbcd->nachkommastellen = 0;
    	else if ( p >= buf && '.' == *p )
    		p--;
    	for ( ; p >= buf && *p >= '0' && *p <= '9'; p-- )
    		pbcd->laenge++;
    	if ( NULL != (pbcd->ziffern = malloc ( pbcd->laenge )))
    		for ( p = buf, len = 0; len < pbcd->laenge; p++ )
    			if ( *p >= '0' && *p <= '9' )
    				pbcd->ziffern[len++] = *p;
    	return NULL == pbcd->ziffern; // 1: Fehler, out of memory. 0: Okay.
    }
    
    double bcd2double(struct bcd_number* pbcd)
    {
    	double number = 0, exp = 1;
    	char* p = pbcd->ziffern + pbcd->laenge - pbcd->nachkommastellen -1, *q = p + 1;
    	for ( ; p >= pbcd->ziffern;  exp*=10, p--)
    		number += (*p - '0') * exp;
    	for ( exp = 1.0/10; q <= pbcd->ziffern + pbcd->laenge-1; q++, exp /= 10 )
    		number += (*q - '0') * exp;
    	return number * pbcd->vorzeichen;
    }
    
    int main( void )
    {
        double eingabe = -2345.2;
    	struct bcd_number bcd = {0};
    	if (double2bcd(&bcd, eingabe))
    		return 0;
    	else
    		printf("%lf", bcd2double(&bcd));
    	free (bcd.ziffern);
        return 0;
    }
    


  • CJosef schrieb:

    ...
    
    	if ( NULL != (pbcd->ziffern = malloc ( pbcd->laenge )))
    		for ( p = buf, len = 0; len < pbcd->laenge; p++ )
    			if ( *p >= '0' && *p <= '9' )
    				pbcd->ziffern[len++] = *p;
    	return NULL == pbcd->ziffern; // 1: Fehler, out of memory. 0: Okay.
    }
    

    Laut Wikipedia wird die Zahl 10 BCD mit (0001 0000) kodiert. Es handelt sich also um einen numerischen Code, der jede Ziffer einer Dezimalzahl einzeln dualkodiert.

    Der vorliegende Code gibt das Ergbnis offensichtlich hexadezimal aus 🙄

    Und da ausserdem Weihnachten ist sollte man auch etwas spendabler sein wenn
    man eine Zeichenkette kodiert:

    if( NULL != (pbcd->ziffern = malloc ( pbcd->laenge +1))) {
      for( p = buf, len = 0; len < pbcd->laenge; p++ ) 
         if( *p >= '0' && *p <= '9' ) 
            pbcd->ziffern[len++] = *p; 
    
      pbcd->ziffern[len] = 0; 
      }
    
    return NULL == pbcd->ziffern;  /* 1: Fehler, out of memory. 0: Okay. */
    }
    


  • merano schrieb:

    Der vorliegende Code gibt das Ergbnis offensichtlich hexadezimal aus 🙄

    Ach was, daran ist nichts hexadezimal. Das ist nur eine Vereinfachung, anstatt

    pbcd->ziffern[len++] = *p - '0';
    

    zu schreiben.
    Den Offset von '0' kann man sich ruhig gönnen(es ist Weihnachten :P), weil doch von den 8 Bit eines char sowieso nur 4 gebraucht werden.
    Passt also rein. 😉
    Ob ich den Offset jetzt oder später abziehe ist doch Wurscht.
    Okay, ein bisschen richtiger wäre es, ihn sofort zu subtrahieren. 🤡
    Dann ist das eben eine ASCII Offset Verschlüsselung 🙄

    merano schrieb:

    Und da ausserdem Weihnachten ist sollte man auch etwas spendabler sein wenn
    man eine Zeichenkette kodiert:

    if( NULL != (pbcd->ziffern = malloc ( pbcd->laenge +1))) {
    ...
    

    Wer bin ich mir anzumaßen ein bereits designtes, festgelegtes Datenformat zu ändern?

    Dabei soll jede einzelne Dezimalstelle einer Zahl n mit k Dezimalstellen separat gespeichert werden, 
    sodass eine k-stellige Dezimalzahl durch einen k- dimensionalen Vektor n dargestellt wird.
    

    :p



  • Vielen Dank für die tolle Hilfe! Ich hoffe ihr wurdet reichlich beschenkt! :xmas1:

    Wenn ich das jetzt richtig sehe, kann ich den BCD-Code nicht wie eine normale Zahl (wie z.B. einen double oder int) verwenden oder? Jede Ziffer hat ja ihre eigene Belegung im Array.

    Wie integriert man diesen BCD-Code, wenn ich noch eine erweiterte Funktion erstellen möchte bzw. muss, der mit diesem Code arbeiten soll?



  • kapitel funktionen in deinem c buch



  • Ich habe hier jetzt eine Funktion, mit der ich den BCD-Code von führenden und angehängten Nullen reinige.

    struct bcd_number * clean_bcd(struct bcd_number *b){
    
        int i,j=0,k=0;
    
        for (i=0; i < b->laenge; i++) {
    
            while (b->ziffern[i] == 0) {
    
                j++;
            }
        }
    
        for (i=0; i < b->laenge; i++){
    
            b->ziffern[i] = b->ziffern[i+j];
        }
    
        for (i=0; i < b->laenge; i++){
    
            if( b->ziffern[i] == 0){
                k++;
            }
            else k=0;
    
        }
        b->laenge = b->laenge - (j+k);
        b->nachkommastellen = j - k; 
    
        return b;
    }
    
    int main( void ) 
    { 
        double eingabe = -2345.2; 
        struct bcd_number* bcd; 
        int i; 
    
        bcd = string2bcd (eingabe); 
    
        printf ("Eingabe:              %f\n",eingabe); 
        printf ("bcd.laenge:           %u\n",bcd->laenge); 
        printf ("bcd.nachkommastellen: %u\n",bcd->nachkommastellen); 
        printf ("bcd.vorzeichen:       %i\n",bcd->vorzeichen); 
        printf ("bcd.ziffern:          "); 
        for (i=0; i<bcd->laenge; ++i) printf ("%i ",bcd->ziffern[i]); 
        puts ("\n"); 
    
        clean_bcd(bcd);
        printf ("Eingabe:              %f\n",eingabe); 
        printf ("bcd.laenge:           %u\n",bcd->laenge); 
        printf ("bcd.nachkommastellen: %u\n",bcd->nachkommastellen); 
        printf ("bcd.vorzeichen:       %i\n",bcd->vorzeichen); 
        printf ("bcd.ziffern:          "); 
        for (i=0; i<bcd->laenge; ++i) printf ("%i ",bcd->ziffern[i]); 
        puts ("\n"); 
    
        free (bcd->ziffern); 
        free (bcd); 
    
        return 0; 
    }
    

    Leider steht da nach dem compilieren nichts für die werte nach clean_bcd(bcd) . Weiß jemand wo ich hier den Fehler habe?



  • Deine Funktion kann nicht funktionieren.
    Wenn da wirklich ein 0 am Anfang ist, bleibst du bei dem j++ in einer Endlosschleife hängen.

    Die Nullen am Ende solltest du aber nur entfernen, wenn sie wirklich bei den Nachkommastellen sind.

    Benutze den Debbuger oder baue dir Zwischenausgaben in deine Funktion ein.



  • Siegfried101 schrieb:

    Ich habe hier jetzt eine Funktion, mit der ich den BCD-Code von führenden und angehängten Nullen reinige.

    Wer zwingt Dich nur, vor Jahresende so etwas zu tun? 😃
    Ich hab Dir mal ein Prüfprogramm entworfen, damit Du auch ein paar Nullen zum Herumspielen hast:

    #include <stdio.h>
    
    struct bcd_number
    {
    	unsigned int laenge;
    	unsigned int nachkommastellen;
    	signed char vorzeichen;
    	unsigned char *ziffern;
    };
    
    struct bcd_number * clean_bcd(struct bcd_number *b)
    {
        unsigned int i, j=0, imax, imin;
    
    	/* Führende Vorkomma-Nullen eliminieren */
    	imax = b->laenge - b->nachkommastellen - 1;
        for (i=0; i < imax; ++i)
    	{
            if (b->ziffern[i] == 0)
    		{
                j++;
            }
    		else break;
        }
    
    	imax = b->laenge - j;
        for (i=0; i < imax; ++i)
    	{
            b->ziffern[i] = b->ziffern[i+j];
        }
    
    	b->laenge -= j;
    
    	/* Nachlaufende Nachkomma-Nullen eliminieren */
    	imin = b->laenge - b->nachkommastellen;
    	for (i = b->laenge - 1; i >= imin; --i)
    	{
            if (b->ziffern[i] == 0)
    		{
    			--b->nachkommastellen;
    			--b->laenge;
    		}
    		else break;
    	}
    
        return b;
    }
    
    /* Testziffern */
    #define Z0 {0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0} /* 0.0 */
    #define Z1 {0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0} /* 0.2 (n=10)*/
    #define Z2 {0,0,0,0,0,5, 2,0,0,0,0,0,0,0,0,0} /* 5.2 (n=10)*/
    #define Z3 {0,0,0,0,0,5, 0,0,0,0,0,0,0,0,0,0} /* 5.0 (n=10)*/
    #define Z4 {0,0,0,5,0,5, 0,0,0,0,0,0,0,0,0,0} /* 505.0 (n=10)*/
    #define Z5 {0,0,0,5,0,5, 2,0,2,0,0,0,0,0,0,0} /* 505.202 (n=10)*/
    #define Z6 {2,3,4,0,6,0, 0,8,9,0,1,3,5,7,9,2} /* 234060.0890135792 (n=10)*/
    
    unsigned char testziffern[] = Z5;   /* hier Z0, Z1, Z2... einsetzen */
    
    int main( void )
    {
        unsigned int i;
    
        struct bcd_number bcd =	{ sizeof(testziffern), 10, -1, testziffern };
    
        clean_bcd(&bcd);
    
        printf ("bcd.laenge:           %u\n",bcd.laenge);
        printf ("bcd.nachkommastellen: %u\n",bcd.nachkommastellen);
        printf ("bcd.vorzeichen:       %i\n",bcd.vorzeichen);
        printf ("bcd.ziffern:          ");
        for (i=0; i<bcd.laenge; ++i) printf ("%i ",bcd.ziffern[i]);
        puts ("\n");
    
        return 0;
    }
    

    Wenn Du noch IDE/Compiler/Betriebssystem angeben würdest, dann könnte man Tipps zum Debuggen geben. Debuggen zu können ist so wichtig wie programmieren zu können.

    viele grüße
    ralph



  • Debuggen zu können ist so wichtig wie programmieren zu können.

    Ich würde fast behaupten, es ist noch wichtiger. Leider kann ichs auch nicht per Debugger 🤡



  • rkhb schrieb:

    Wenn Du noch IDE/Compiler/Betriebssystem angeben würdest, dann könnte man Tipps zum Debuggen geben. Debuggen zu können ist so wichtig wie programmieren zu können.

    Also ich benutze den qt creator auf mac os. Debuggen ist mir jetzt völlig neu. In meinem C Buch wird es auch nicht erwähnt. Kennt ihr eine Quelle wo man sich einlesen kann?



  • Siegfried101 schrieb:

    Also ich benutze den qt creator auf mac os.

    Aaarghhh, kalt erwischt: MacOS habe ich nicht. Und der QT-Creator-Debugger zickt auf meinem WinXP. Naja:

    1. Du hast in QT-Creator eine Hilfe-Funktion: Entweder links ein Icon oder oben: Hilfe-Inhalt. Nun im Fenster "Inhalt" (linksoben) "QT Creator Manual 2- Debugging and...-Debugging" klicken (Auswahl öffnet sich mit Klick auf das Plus-Zeichen). Viel Spaß bei der englischen Lektüre.

    2. Lade mal mein "Prüfprogramm" oben und lasse es kompilieren. Nun gehst Du mit dem Cursor in die Zeile 9 ( j++; ) und drückst auf F9. Damit hast Du einen Breakpoint (Haltepunkt) gesetzt. Du siehst einen roten Punkt an der linken Seite. Als nächstes drückst Du auf F5 (oder klickst oben auf Debuggen-Debuggen-Debuggen). Nach einer kleinen Weile stoppt das Programm und der Cursor blinkt Dich von Zeile 9 an. Im Fenster rechts daneben siehst Du, welche Werte die lokalen Variablen im Augenblick haben. Du kannst dort weitere Ausdrücke überwachen lassen, z.B: Rechtsklick in diesem Fenster, "Neuen Ausdruck einfügen", "b->ziffern[i]" eingeben. Nun kannst Du im "Einzelschritt" (immer nur eine Zeile per Tastendruck) mit F10 die Schleife durchgehen. Du siehst, wie sich die Werte für i, j und b->ziffern[i] verändern. Um hier einen eventuellen Fehler zu entdecken, musst Du Dir natürlich völlig im Klaren sein, was in der aktuellen Zeile passieren soll.

    3. Wenn Du dasselbe mit Deiner nicht funktionierenden clean_bcd -Funktion machst, wirst Du merken, dass Du Dich schnell in einer Endlosschleife befindest. Du weißt also schon mal, wo ein Fehler ist. Dann kannst Du Dir überlegen: Was tun?

    4. Ein Haltepunkt wird mit einem erneuten Druck auf F9 wieder gelöscht. Das nennt sich "Toggeln" oder "Umschalten". Haltepunkte kann man an jeder Zeile setzen, wo man einen Stop wünscht. Du kannst nach einem Stop das Programm auch mit F5 wieder anlaufen lassen, es hält dann wieder an, wenn es auf einen Haltepunkt stößt.

    viele grüße
    ralph



  • rkhb schrieb:

    Aaarghhh, kalt erwischt: MacOS habe ich nicht. Und der QT-Creator-Debugger zickt auf meinem WinXP. Naja:

    1. Du hast in QT-Creator eine Hilfe-Funktion: Entweder links ein Icon oder oben: Hilfe-Inhalt. Nun im Fenster "Inhalt" (linksoben) "QT Creator Manual 2- Debugging and...-Debugging" klicken (Auswahl öffnet sich mit Klick auf das Plus-Zeichen). Viel Spaß bei der englischen Lektüre.

    2. Lade mal mein "Prüfprogramm" oben und lasse es kompilieren. Nun gehst Du mit dem Cursor in die Zeile 9 ( j++; ) und drückst auf F9. Damit hast Du einen Breakpoint (Haltepunkt) gesetzt. Du siehst einen roten Punkt an der linken Seite. Als nächstes drückst Du auf F5 (oder klickst oben auf Debuggen-Debuggen-Debuggen). Nach einer kleinen Weile stoppt das Programm und der Cursor blinkt Dich von Zeile 9 an. Im Fenster rechts daneben siehst Du, welche Werte die lokalen Variablen im Augenblick haben. Du kannst dort weitere Ausdrücke überwachen lassen, z.B: Rechtsklick in diesem Fenster, "Neuen Ausdruck einfügen", "b->ziffern[i]" eingeben. Nun kannst Du im "Einzelschritt" (immer nur eine Zeile per Tastendruck) mit F10 die Schleife durchgehen. Du siehst, wie sich die Werte für i, j und b->ziffern[i] verändern. Um hier einen eventuellen Fehler zu entdecken, musst Du Dir natürlich völlig im Klaren sein, was in der aktuellen Zeile passieren soll.

    3. Wenn Du dasselbe mit Deiner nicht funktionierenden clean_bcd -Funktion machst, wirst Du merken, dass Du Dich schnell in einer Endlosschleife befindest. Du weißt also schon mal, wo ein Fehler ist. Dann kannst Du Dir überlegen: Was tun?

    4. Ein Haltepunkt wird mit einem erneuten Druck auf F9 wieder gelöscht. Das nennt sich "Toggeln" oder "Umschalten". Haltepunkte kann man an jeder Zeile setzen, wo man einen Stop wünscht. Du kannst nach einem Stop das Programm auch mit F5 wieder anlaufen lassen, es hält dann wieder an, wenn es auf einen Haltepunkt stößt.

    viele grüße
    ralph

    Besten Dank Ralph! Man muss sich daran erstmal gewöhnen, aber mit bisschen Routine ist das wohl eine sehr große Hilfe.

    Ich bastel hier an noch einer Funktion mit der ich zwei BCD-Codes addiere.

    struct bcd_number *addition(struct bcd_number *a, struct bcd_number *b){
    
        int maxkomma,minkomma,maxlaenge,minlaenge,i,k,m;
        struct bcd_number *c;
    
        if ((a->nachkommastellen > b->nachkommastellen) || (a->nachkommastellen == b->nachkommastellen)) {
            maxkomma = a->nachkommastellen;
            minkomma = b->nachkommastellen;
        }
        else
            maxkomma = b->nachkommastellen;
            minkomma = a->nachkommastellen;
    
        if ((a->laenge > b->laenge) || (a->laenge == b->laenge)) {
            maxlaenge = a->laenge;
            minlaenge = b->laenge;
        }
        else
            maxlaenge = b->laenge;
            minlaenge = a->laenge;
    
        k = (minlaenge-maxlaenge)+(maxkomma-minkomma);
        m = maxlaenge+k;
    
        for (i=0; i<m; i++) {
            if ((a->laenge > b->laenge) || (a->laenge == b->laenge))  {
    
                c->ziffern[m-i]=a->ziffern[maxlaenge-1-i]+b->ziffern[maxlaenge-1+i+k];
            }
    
            else c->ziffern[m-i]=b->ziffern[maxlaenge-1-i]+a->ziffern[maxlaenge-1+i+k];
    
            if (c->ziffern[maxlaenge - 1 -i] > 9) {
                c->ziffern[maxlaenge - 1 -i] = c->ziffern[maxlaenge - 1 -i] % 10;
                c->ziffern[maxlaenge - 2 -i] += c->ziffern[maxlaenge - 1 -i] / 10;
            }
        }
        c->nachkommastellen=maxkomma;
    
        return c;
    }
    

    Es wird zwar fehlerfrei combiliert, aber leider werden keine Ergebnisse angezeigt. Eine Endlosschleife wird's diesmal nicht sein.

    Ist das Prinzip nach dem ich hier vorgegangen bin vertretbar? Oder bin ich völlig auf dem Holzweg?



  • Initialisierung von c fehlt.



  • Bashar schrieb:

    Initialisierung von c fehlt.

    Oh Danke. Mit was für Werten sollte man c vorzugsweise initialisieren?


Anmelden zum Antworten