首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >浮点二进制/十进制/八进制/十六进制转换器

浮点二进制/十进制/八进制/十六进制转换器
EN

Code Review用户
提问于 2013-05-05 01:52:39
回答 2查看 4.7K关注 0票数 5

我最终决定为这个程序设计一个类,但是有些代码看起来仍然很混乱。我也有点担心干,特别是在binaryToOctalHex()。这个程序看起来好多了,但我还是不喜欢我在上述功能中所做的事情。如果有必要的话,我不介意进行重构。

在这里应该做些什么?

驱动程序

代码语言:javascript
复制
#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();
    }
}

NumberSystemsConverter.h

代码语言:javascript
复制
#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

NumberSystemsConverter.cpp

代码语言:javascript
复制
#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";
}
EN

回答 2

Code Review用户

回答已采纳

发布于 2013-07-05 03:30:06

在所有ifs的main()后面,我看到了一个潜藏的参数:

代码语言:javascript
复制
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)也可以处理十进制和二进制。此时,构造函数将转换为

代码语言:javascript
复制
NumberSystemsConverter::NumberSystemsConverter(unsigned base, const std::string &str)
{
    strToDecimal(base, str);
    decimalToBinary();
    binaryToHex();
    binaryToOctal();
}

顺便说一句,我并不喜欢那些转换函数集导致对象,而不是返回一个值。

票数 3
EN

Code Review用户

发布于 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)
  • 这可以缩短: const std::string::iterator = std::find(binary.begin(),binary.end(),‘. '.');使用auto:const auto = std::find(binary.begin(),binary.end(),'.');
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/25824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档