NOTE: I have included updated code below the original code. Reviews are still welcome for any parts.
Driver (Original)
NumberSystemsConverter.h (ORIGINAL)
NumberSystemsConverter.cpp (Original)
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <sstream>
#include "NumberSystemsConverter.h"
NumberSystemsConverter::NumberSystemsConverter(const std::string &binary)
{
this->binary = binary;
stringToDecimal(2, binary);
binaryToOctal();
binaryToHex();
}
NumberSystemsConverter::NumberSystemsConverter(d32 decimal)
{
this->decimal = decimal;
decimalToBinary();
binaryToOctal();
binaryToHex();
}
NumberSystemsConverter::NumberSystemsConverter(unsigned base, const std::string &str)
{
if (base == 8)
{
octal = str;
stringToDecimal(base, octal);
decimalToBinary();
binaryToHex();
}
else if (base == 16)
{
hex = str;
stringToDecimal(base, hex);
decimalToBinary();
binaryToOctal();
}
}
int NumberSystemsConverter::findDecimalPoint(const std::string &str) const
{
int decimalPointIndex = str.find('.');
if (decimalPointIndex == std::string::npos)
decimalPointIndex = str.size(); // index identified as end if not found
return decimalPointIndex;
}
void NumberSystemsConverter::decimalToBinary()
{
binary = "";
u32 integerPart = static_cast<std::uint32_t>(decimal);
d32 decimalPart = decimal - integerPart;
do
{
binary += ((integerPart % 2 == 0) ? '0' : '1');
integerPart /= 2;
} while (integerPart > 0);
std::reverse(binary.begin(), binary.end());
if (decimalPart > 0.0)
{
binary += '.';
while (decimalPart != 1.0)
{
decimalPart *= 2.0;
binary += ((decimalPart < 1.0) ? '0' : '1');
if (decimalPart > 1.0) decimalPart -= 1.0;
}
}
}
void NumberSystemsConverter::stringToDecimal(unsigned base, const std::string &str)
{
int decimalPointIndex = findDecimalPoint(str);
d32 power = (d32)decimalPointIndex - 1;
decimal = 0.0;
// loops through entire string (not both sides of decimal point separately)
for (auto iter = str.cbegin(); iter != str.cend(); ++iter)
{
if (*iter != '.')
{
char strChar = toupper(*iter);
d32 charValue = strChar - ((isdigit(strChar)) ? '0' : '7');
decimal += charValue * (d32)std::pow(base, power);
}
else
power = 0.0;
power--;
}
}
void NumberSystemsConverter::binaryToOctal()
{
std::ostringstream octalSS;
std::string rightDecimal = "";
u32 rightValue = 0;
int decimalPointIndex = findDecimalPoint(binary);
const std::string::iterator iter = std::find(binary.begin(), binary.end(), '.');
std::string leftDecimal = binary.substr(0, decimalPointIndex);
u32 leftValue = std::stoul(leftDecimal, NULL, 2);
if (iter != binary.cend())
{
rightDecimal = binary.substr(decimalPointIndex+1, binary.size());
while (rightDecimal.size() % 3 != 0)
{
rightDecimal += '0';
}
rightValue = std::stoul(rightDecimal, NULL, 2);
}
octalSS << std::oct << leftValue << '.' << std::oct << rightValue;
octal = octalSS.str();
}
void NumberSystemsConverter::binaryToHex()
{
std::ostringstream hexSS;
std::string rightDecimal = "";
u32 rightValue = 0;
int decimalPointIndex = findDecimalPoint(binary);
const std::string::iterator iter = std::find(binary.begin(), binary.end(), '.');
std::string leftDecimal = binary.substr(0, decimalPointIndex);
u32 leftValue = std::stoul(leftDecimal, NULL, 2);
if (iter != binary.cend())
{
rightDecimal = binary.substr(decimalPointIndex+1, binary.size());
while (rightDecimal.size() % 4 != 0)
{
rightDecimal += '0';
}
rightValue = std::stoul(rightDecimal, NULL, 2);
}
hexSS << std::uppercase << std::hex << leftValue << '.' << std::hex << rightValue;
hex = hexSS.str();
}
void NumberSystemsConverter::display() const
{
std::cout << "\n * Binary : " << std::setprecision(10) << binary;
std::cout << "\n * Decimal: " << std::setprecision(10) << decimal;
std::cout << "\n * Octal : " << std::setprecision(10) << octal;
std::cout << "\n * Hex : 0x" << std::setprecision(10) << hex << "\n";
}
**Driver(UPDATED)**
#include <iostream>
#include <sstream>
#include "NumbersConverter.h"
int main()
{
std::cout << "\n\n(1) Binary -> Decimal/Octal/Hex\n";
std::cout << "(2) Decimal -> Binary/Octal/Hex\n";
std::cout << "(3) Octal -> Binary/Decimal/Hex\n";
std::cout << "(4) Hex -> Binary/Decimal/Octal\n\n";
std::string input;
std::stringstream ss;
unsigned choice;
std::cout << "> Choice: ";
std::getline(std::cin, input);
ss << input;
ss >> choice;
std::cout << ">> Value: ";
std::getline(std::cin, input);
unsigned inputBases[] = {2, 10, 8, 16};
unsigned inputBase = inputBases[choice-1];
NumbersConverter conversion(inputBase, input);
conversion.display();
}
NumbersConverter.h (UPDATED)
#ifndef NUBMERSCONVERTER_H
#define NUMBERSCONVERTER_H
#include <string>
#include <utility>
typedef std::pair<std::string, std::string> strPair;
class NumbersConverter
{
private:
double decimal;
bool valid(unsigned, const std::string&) const;
int decimalIndex(const std::string&) const;
void numberStringToDecimal(unsigned, const std::string&);
std::string decimalToBinary() const;
strPair binaryToOctalHex(const std::string&) const;
public:
NumbersConverter(unsigned, const std::string&);
void display() const;
};
#endif
NumbersConverter.cpp (UPDATED)
#include <cmath>
#include <cstdint>
#include <iostream>
#include <iomanip>
#include <map>
#include <sstream>
#include "NumbersConverter.h"
NumbersConverter::NumbersConverter(unsigned base, const std::string &input) : decimal(0.0)
{
if (valid(base, input)) numberStringToDecimal(base, input);
}
bool NumbersConverter::valid(unsigned base, const std::string &numStr) const
{
std::map<unsigned, std::string> validInputs;
validInputs[2] = "01.";
validInputs[8] = "0123456789.";
validInputs[10] = "0123456789.";
validInputs[16] = "0123456789AaBbCcDdEeFf.";
for (auto iter = validInputs.cbegin(); iter != validInputs.cend(); ++iter)
{
if (base == iter->first && numStr.find_first_not_of(iter->second) == std::string::npos)
{
return true;
}
}
return false;
}
int NumbersConverter::decimalIndex(const std::string &str) const
{
int index = str.find('.');
if (index == std::string::npos)
index = str.size();
return index;
}
void NumbersConverter::numberStringToDecimal(unsigned base, const std::string &numStr)
{
double power = decimalIndex(numStr) - 1;
for (auto iter = numStr.cbegin(); iter != numStr.cend(); ++iter)
{
if (*iter != '.')
{
char ch = toupper(*iter);
double chValue = ch - ((isdigit(ch)) ? 48 : 55);
decimal += chValue * std::pow(base, power);
power--;
}
}
}
std::string NumbersConverter::decimalToBinary() const
{
std::uint32_t integerPart = (std::uint32_t)decimal;
double decimalPart = decimal - integerPart;
std::string binary = "";
do
{
binary += ((integerPart % 2 == 0) ? '0' : '1');
integerPart /= 2;
} while (integerPart > 0);
std::reverse(binary.begin(), binary.end());
if (decimalPart > 0.0)
{
binary += '.';
while (decimalPart != 1.0)
{
decimalPart *= 2.0;
binary += ((decimalPart < 1.0) ? '0' : '1');
if (decimalPart > 1.0) decimalPart -= 1.0;
}
}
return binary;
}
strPair NumbersConverter::binaryToOctalHex(const std::string &binary) const
{
std::string leftBinary = binary.substr(0, decimalIndex(binary));
std::uint32_t leftValue = std::stoul(leftBinary, nullptr, 2);
std::ostringstream octal;
std::ostringstream hex;
octal << std::oct << leftValue;
hex << std::uppercase << std::hex << leftValue;
if (binary.find('.') != std::string::npos)
{
std::string rightBinary = binary.substr(decimalIndex(binary)+1);
std::uint64_t rightValue;
while (rightBinary.size() % 3 != 0)
rightBinary += '0';
rightValue = std::stoul(rightBinary, nullptr, 2);
octal << '.' << std::oct << rightValue;
while (rightBinary.size() % 4 != 0)
rightBinary += '0';
rightValue = std::stoul(rightBinary, nullptr, 2);
hex << '.' << std::hex << rightValue;
}
strPair octalHex = std::make_pair(octal.str(), hex.str());
return octalHex;
}
void NumbersConverter::display() const
{
std::string binary = decimalToBinary();
std::cout << "\n* Binary : " << binary;
std::cout << "\n* Decimal: " << decimal;
std::cout << "\n* Octal : " << binaryToOctalHex(binary).first;
std::cout << "\n* Hex : 0x" << binaryToOctalHex(binary).second;
}