BCD-Format



  • Scheppertreiber schrieb:

    So what ? Den Assembler angeworfen und los ... 🤡

    :xmas2: Assembler? Hier! Hier:

    http://dcla.rkhb.de/umwandlung/float2dez.html

    🤡 🤡

    viele grüße
    ralph



  • ... und der6502 konnte das noch besser:

    http://www.6502.org/tutorials/decimal_mode.html



  • DirkB schrieb:

    Du möchtest nicht, du musst. 😃

    😃

    Wenn ich jetzt die Funktion struct bcd_number * double2bcd(double x) erstellen will, dann müsste das grob so aufgebaut sein:

    struct bcd_number * string2bcd(const char *s){ 
    
        struct bcd_number *b;  
        int j,k; 
    
        int deztren; 
    
        /* Speicher reservieren  */ 
        b=(struct bcd_number *)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 */ 
                dezflag=1; 
            else{  
                b->laenge++; 
                if (dezflag) 
                    b->nachkommastellen++; 
            }       
        } 
    
        /* Ziffernarray dynamisch reservieren entsprechend den nun bekannten Längen */ 
        b->ziffern=(unsigned char *)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]!=deztrenner) 
                b->ziffern[k++]=s[j]-'0'; 
    
        return b; 
    }
    

    Gibt es hierzu was zu meckern? Wenn ja, was kann man noch besser machen?

    Die Assembler-Sache ist mir übrigens zu hoch aber trotzdem danke 😃



  • Solltest du nicht eine Umwandlung von/nach double machen?

    sizeof(unsigned char) ist per Default 1.
    Und der cast bei malloc ist in C auch niht nötig.

    Überlesen von führernden Leerzeichen wäre nicht schlecht.
    + ist auch ein gültiges Vorzeichen.
    Du prüfst nirgends, ob du wirklich Ziffern hast. (Tipp: isdigit())



  • Erstmal vielen Dank für die Hilfe!

    DirkB schrieb:

    Solltest du nicht eine Umwandlung von/nach double machen?

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

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

    ich hab das jetzt alles nach double x codiert, aber so kann das ja nicht funktionieren. Ich muss x ja irgendwie als Array drin haben. Wie mache ich das?

    DirkB schrieb:

    sizeof(unsigned char) ist per Default 1.

    Das hab ich jetzt ganz weggelassen.

    DirkB schrieb:

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

    Was genau meinst du damit?

    DirkB schrieb:

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

    Mit welchen Befehlen mache ich das?

    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()?



  • 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 🤡


Anmelden zum Antworten