我最终决定为这个程序设计一个类,但是有些代码看起来仍然很混乱。我也有点担心干,特别是在binaryToOctalHex()。这个程序看起来好多了,但我还是不喜欢我在上述功能中所做的事情。如果有必要的话,我不介意进行重构。
在这里应该做些什么?
#include <iostream>
#include "NumberSystemsConverter.h"
int main()
{
unsigned choice;
std::string str;
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";
do
{
std::cout << "> Conversion #: ";
std::cin >> choice;
} while (choice < 1 || choice > 4);
std::cout << "\n> Value: ";
std::cin.ignore();
if (choice == 1)
{
std::string binary;
getline(std::cin, binary);
NumberSystemsConverter conversion(binary);
conversion.display();
}
else if (choice == 2)
{
d32 decimal;
std::cin >> decimal;
NumberSystemsConverter conversion(decimal);
conversion.display();
}
else if (choice == 3)
{
std::string octal;
getline(std::cin, octal);
NumberSystemsConverter conversion(8, octal);
conversion.display();
}
else if (choice == 4)
{
std::string hex;
getline(std::cin, hex);
NumberSystemsConverter conversion(16, hex);
conversion.display();
}
}#ifndef NUMBERSYSTEMSCONVERTER_H
#define NUMBERSYSTEMSCONVERTER_H
#include <cstdint>
#include <string>
typedef long double d32;
typedef std::uint32_t u32;
class NumberSystemsConverter
{
private:
d32 decimal;
std::string binary;
std::string octal;
std::string hex;
int findDecimalPoint(const std::string&) const;
void decimalToBinary();
void stringToDecimal(unsigned, const std::string&);
void binaryToOctal();
void binaryToHex();
public:
NumberSystemsConverter(const std::string&); // binary input
NumberSystemsConverter(d32); // decimal input
NumberSystemsConverter(unsigned, const std::string&); // octal/hex input
void display() const;
};
#endif#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";
}发布于 2013-07-05 03:30:06
在所有ifs的main()后面,我看到了一个潜藏的参数:
unsigned inputBases[] = { 2, 10, 8, 16 };
unsigned inputBase = inputBases[choice - 1];
std::string input;
std::getline(std::cin, input);
NumberSystemsConverter conversion(inputBase, input);
conversion.display();当然,为了使其工作,您需要确保所有的基在两个args构造函数中都是平等的。包含基-10或基-2中的数字的字符串应该可以在NumberSystemsConverter(base, input)中使用。这毕竟是个好生意;谁想要一个只知道如何转换的转换器?)
这可能意味着确保stringToDecimal(base, str)也可以处理十进制和二进制。此时,构造函数将转换为
NumberSystemsConverter::NumberSystemsConverter(unsigned base, const std::string &str)
{
strToDecimal(base, str);
decimalToBinary();
binaryToHex();
binaryToOctal();
}顺便说一句,我并不喜欢那些转换函数集导致对象,而不是返回一个值。
发布于 2014-08-04 16:36:50
这里有很多需要回顾的地方,尽管我仍然不太知道如何使它变得更好。我将提到一些可以改变的东西(除了@cHao的建议)。
typedefs在头球没有真正的帮助,所以他们可以被删除。findDecimalPoint()看起来更适合作为一个自由函数。它可以很容易地接受任何字符串,而不仅仅是成员字符串,并执行其操作。NULL正在std::stoul()中使用。因为这是C++11,所以最好使用nullptr。for循环: for (auto = str.cbegin();iter != str.cend();++iter)可以成为基于范围的for循环: for (auto& iter : str)auto:const auto = std::find(binary.begin(),binary.end(),'.');https://codereview.stackexchange.com/questions/25824
复制相似问题