answersLogoWhite

0

The following program shows one way to convert to BCD using a variation of packed BCD 8421 encoding. Each digit is represented by 4 bits in the range 0x0 to 0x9. 0xa denotes a minus symbol (for negative values) while 0xb denotes a decimal point for floating point values. The unused value 0xf is used to pad a BCD to a full byte when the number of symbols is odd. Values 0xc, 0xd and 0xe are ignored, but could be used for other purposes such as when representing exponents or fractions/ratios.

Values may be any length, the BCD being represented by a vector of type unsigned char. Since the value of a BCD could easily exceed the range of a long double or a 64-bit integer, conversion to these types is disabled. BCD values are constructed from an input string and converted back to a string for output.

Arithmetic operations can be overloaded to handle a BCD (using decimal notation arithmetic), however this has been left as an exercise for the reader.

#include<iostream>

#include<sstream>

#include<vector>

#include<exception>

using uchar = unsigned char;

class BCD_8421

{

private:

std::vector<uchar> v;

static const uchar lo_mask {0x0f};

static const uchar hi_mask {0xf0};

public:

BCD_8421 (void);

BCD_8421 (const BCD_8421&);

BCD_8421 (BCD_8421&&);

BCD_8421 (const std::string&);

BCD_8421& operator= (const BCD_8421&);

BCD_8421& operator= (BCD_8421&&);

BCD_8421& operator= (const std::string&);

static bool is_valid (const std::string& s);

operator std::string (void) const;

friend std::ostream& operator<< (std::ostream&, const BCD_8421&);

};

BCD_8421::BCD_8421 (void): v(1, 0) {}

BCD_8421::BCD_8421 (const BCD_8421& bcd): v (bcd.v) {}

BCD_8421::BCD_8421 (BCD_8421&& bcd): v (std::move(bcd.v)) {}

BCD_8421::BCD_8421 (const std::string& s): v{} { *this = s; }

BCD_8421& BCD_8421::operator= (const BCD_8421& bcd) { v=bcd.v; return *this; }

BCD_8421& BCD_8421::operator= (BCD_8421&& bcd) { v=std::move(bcd.v); return *this; }

BCD_8421& BCD_8421::operator= (const std::string& s)

{

v.clear();

uchar c {};

bool msb {false};

bool minus {false};

bool point {false};

bool error {false};

bool digit {false};

for (auto i=s.begin(); i!=s.end(); ++i)

{

if (!msb)

c = hi_mask;

uchar x;

switch (*i)

{

case ('0'):

if (!digit)

continue;

case ('1'):

case ('2'):

case ('3'):

case ('4'):

case ('5'):

case ('6'):

case ('7'):

case ('8'):

case ('9'):

digit = true;

x = *i - '0';

break;

case ('.'):

if (!point)

{

point = !point;

x = 10;

break;

}

else

error = !error;

case ('-'):

if (!minus && i==s.begin())

{

minus = !minus;

x = 11;

break;

}

default:

error = !error;

}

if (error)

{

v.clear();

v.push_back (hi_mask);

std::stringstream ss;

ss << "Error: invalid argument in BCD_8421.operator= ("" << s << "")";

throw std::invalid_argument (ss.str());

}

if (msb)

v.push_back ((c & lo_mask) | (x << 4));

else

c |= x;

msb = !msb;

}

if (msb && c)

v.push_back (c);

else if (!digit)

{

v.clear();

v.push_back (hi_mask);

}

return *this;

}

bool BCD_8421::is_valid (const std::string& s)

{

const std::string valid_chars {"0123456789-."};

if (s.find_first_not_of (valid_chars) != valid_chars.npos)

return false;

auto f = s.find ('-');

if (f != s.rfind('-') (f && f!=s.npos))

return false;

if (s.find ('.') != s.rfind('.'))

return false;

return true;

}

BCD_8421::operator std::string (void) const

{

std::stringstream ss;

bool digit {false};

bool point {false};

for (auto i : v)

{

bool msb {false};

do

{

uchar c {};

uchar x = msb ? i >> 4 : i & lo_mask;

switch (x)

{

case (0x0):

case (0x1):

case (0x2):

case (0x3):

case (0x4):

case (0x5):

case (0x6):

case (0x7):

case (0x8):

case (0x9): c = '0' + x; digit = true; break;

case (0xa): c = '.'; point = true; break;

case (0xb): c = '-'; break;

default: break;

}

if (point && !digit)

ss << '0';

if (c) ss << c;

msb = !msb;

} while (msb);

}

if (ss.str().back()=='.')

ss << '0';

return ss.str();

}

std::ostream& operator<< (std::ostream& os, const BCD_8421& bcd)

{

return os << static_cast<std::string> (bcd);

}

int main()

{

for (unsigned loop=0; loop<10; ++loop)

{

std::string input;

while (true)

{

std::cout << "Enter a numeric value: ";

std::cin >> input;

if (BCD_8421::is_valid (input))

break;

std::cerr << "Invalid input.\n";

}

try

{

BCD_8421 a = input;

std::cout << "You entered the value: " << a << std::endl;

}

catch (std::range_error& e)

{

std::cerr << e.what() << std::endl;

}

}

}

User Avatar

Wiki User

10y ago

Still curious? Ask our experts.

Chat with our AI personalities

TaigaTaiga
Every great hero faces trials, and you—yes, YOU—are no exception!
Chat with Taiga
LaoLao
The path is yours to walk; I am only here to hold up a mirror.
Chat with Lao
ViviVivi
Your ride-or-die bestie who's seen you through every high and low.
Chat with Vivi

Add your answer:

Earn +20 pts
Q: How do you convert a decimal into a BCD in C plus plus?
Write your answer...
Submit
Still have questions?
magnify glass
imp