Die Idee für eine ASCII-Darstellung einer Zahl in BCD zu konvertieren ist eigentlich die „richtige“. Bei BCD müssen Sie nur '0'
zu jeder Ziffer hinzufügen, um den entsprechenden ASCII-Wert zu erhalten.
Aber Ihr Code hat mehrere Probleme. Der wichtigste ist, dass Sie versuchen, einen um 8 Bits nach links verschobenen Wert in einen 8-Bit-Typ zu stopfen. Das kann nie funktionieren, diese 8 Bits sind Null, denke darüber nach! Dann mache ich absolut nicht verstehen, was Ihre dec2bin()
Funktion soll tun.
So werde ich Ihnen eine mögliche richtige Lösung für Ihr Problem vorstellen. Die Schlüsselidee ist die Verwendung einer char
für jede einzelne BCD-Ziffer. Natürlich benötigt eine BCD-Ziffer nur 4 Bits und eine char
hat mindestens 8 von ihnen - aber Sie brauchen char
sowieso für Ihre ASCII-Darstellung und wenn Ihre BCD-Ziffern bereits in einzelnen char
s sind, alles, was Sie tun müssen, ist tatsächlich hinzuzufügen '0'
zu jedem.
Während es bei: Umwandlung in BCD durch Teilen und Multiplizieren ist eine Verschwendung von Ressourcen. Es gibt einen netten Algorithmus namens Double dabble für die Umwandlung in BCD nur mit Bitverschiebung und Additionen. Ich verwende es in dem folgenden Beispielcode:
#include <stdio.h>
#include <string.h>
// for determining the number of value bits in an integer type,
// see https://stackoverflow.com/a/4589384/2371524 for this nice trick:
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \
+ (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3))
// number of bits in unsigned int:
#define UNSIGNEDINT_BITS IMAX_BITS((unsigned)-1)
// convert to ASCII using BCD, return the number of digits:
int toAscii(char *buf, int bufsize, unsigned val)
{
// sanity check, a buffer smaller than one digit is pointless
if (bufsize < 1) return -1;
// initialize output buffer to zero
// if you don't have memset, use a loop here
memset(buf, 0, bufsize);
int scanstart = bufsize - 1;
int i;
// mask for single bits in value, start at most significant bit
unsigned mask = 1U << (UNSIGNEDINT_BITS - 1);
while (mask)
{
// extract single bit
int bit = !!(val & mask);
for (i = scanstart; i < bufsize; ++i)
{
// this is the "double dabble" trick -- in each iteration,
// add 3 to each element that is greater than 4. This will
// generate the correct overflowing bits while shifting for
// BCD
if (buf[i] > 4) buf[i] += 3;
}
// if we have filled the output buffer from the right far enough,
// we have to scan one position earlier in the next iteration
if (buf[scanstart] > 7) --scanstart;
// check for overflow of our buffer:
if (scanstart < 0) return -1;
// now just shift the bits in the BCD digits:
for (i = scanstart; i < bufsize - 1; ++i)
{
buf[i] <<= 1;
buf[i] &= 0xf;
buf[i] |= (buf[i+1] > 7);
}
// shift in the new bit from our value:
buf[bufsize-1] <<= 1;
buf[bufsize-1] &= 0xf;
buf[bufsize-1] |= bit;
// next bit:
mask >>= 1;
}
// find first non-zero digit:
for (i = 0; i < bufsize - 1; ++i) if (buf[i]) break;
int digits = bufsize - i;
// eliminate leading zero digits
// (again, use a loop if you don't have memmove)
// (or, if you're converting to a fixed number of digits and *want*
// the leading zeros, just skip this step entirely, including the
// loop above)
memmove(buf, buf + i, digits);
// convert to ascii:
for (i = 0; i < digits; ++i) buf[i] += '0';
return digits;
}
int main(void)
{
// some simple test code:
char buf[10];
int digits = toAscii(buf, 10, 471142);
for (int i = 0; i < digits; ++i)
{
putchar(buf[i]);
}
puts("");
}
Sie nicht brauchen diese IMAX_BITS()
„magic Makro“, wenn Sie tatsächlich Ihre Zielplattform kennen und wie viele Bits gibt es in der Integer-Typ Sie wollen umwandeln.
Mit Bezug auf Ihre Frage, wie denken Sie, ASCII unterscheidet sich von dezimal, binär usw.? Warum in BCD konvertieren und dann in ASCII, wenn Sie diesen Wert bereits haben? –
Ich verstehe, ASCII ist einfach 48 (Dez) über einer bestimmten Ziffer, aber ich habe keine Ahnung, wie Sie das hier implementieren. Ich verstehe, dass dies eine riesige Anfängerfrage ist, aber ich bin seit Stunden damit beschäftigt, ohne Glück –
Können Sie bitte definieren, was ist Ihre Eingabe und was sollte die Ausgabe sein? Einschließlich ihrer Arten. –