在C ++中将任何基数转换为基数10

时间:2016-03-02 05:37:27

标签: c++

我有这段代码:

#include <stdio.h>
#include <ctype.h>

int validnumber(int b, char* p);
unsigned long base2dec(int b,char *p);
void dec2base (int b,unsigned long x);

char *number;


main() {
    int base,temp=0,count;
    unsigned long Decimal_number;

    do {
        printf ("Give the base of the number you want to tranform:");
        scanf ("%d", &base);
        if (base<2 || base>16)
            printf("Not acceptable base number, numbers should be in range from 2 to 16\n\n");
    } while (base<2 || base>16);


    printf ("Give the number you want to tranform:");
    scanf("%s", number);

    for (count=0;count<32;count++) {
        number [count]= toupper(number[count]);
    }

    temp=validnumber(base, number);

    if (temp==0)
        printf ("O arithmpos pou eisagatai periexei MH egkira symbola\n");
    else 
        if (temp==1)
            printf ("O arithmpos pou eisagatai periexei egkira symbola\n");

    if (temp==1) {
        Decimal_number =  base2dec( base , number);     
    }

int validnumber(int b, char *p){

    int  count, a[32];

    for (count=0;count<32;count++)
            a[count]=p[count];

    if (b>=2 && b<=10) {
        for (count=0;count<32;count++) {
            if (a[count]<48 || a[count]>48+b)
                return 0;

            break;
        }
    }

    if (b>=11 && b<=16) {
        for (count=0;count<32;count++) {
            if ((a[count]>=48 && a[count]<=57) || (a[count]>=65 && a[count]<=70)) {
                return 1;
            }

        }
    }   

}   

从这一点开始,主程序必须调用函数:

unsigned long base2dec (int b, char * p)

接受基数b和字符表中的指针p作为参数 对应于导入的字符串s并返回表示十进制系统中表示的s的数字。 此外,它应该调用函数:

void dec2base (int b, unsigned long x)

接受基数b和十进制系统中数字x的值作为参数,并在此基数中显示基数值和数字x的表示。主程序将所有基值的函数调用为2到16。

有关于如何开始的任何想法吗?任何指导将不胜感激。

2 个答案:

答案 0 :(得分:1)

在您的base2dec中,您只需调用此方法并传入&#39; b&#39;因为它是和x应该是转换后的字符串。

这是dec2base的一个实现。它是递归实现的。

void dec2base(int b, unsigned long x){
  if (x == 0)
     return;
  int y = x % b;
  x /= b;
  if (y < 0)
     x += 1; 
  dec2base(b, x);
  //converted digits to hex after realizing this solution doesn't work 
  //for bases greater than 10. Credits to Trevor pointing this out.
  cout<< hex << y < 0 ? y + (b * -1) : y;
  return;
 }

答案 1 :(得分:0)

首先,请查看您的格式,因为编写代码的方式使其更难以遵循。

以下是我要做的事情:

#include <stdexcept>
#include <iostream>

void dec2base(int b, long x)
{
    // Quick check for zero
    if (x == 0)
    {
        std::cout << '0';
        return;
    }

    // Print the negative sign if present, also negate
    if (x < 0)
    {
        std::cout << '-';
        x = -x;
    }

    char buf[12];
    int i = 0;

    // Convert to a backwards BCD
    do {
        buf[i++] = static_cast<char>(x % b);
    } while (x /= b);

    // Print it starting from the last digit (really the first)
    do {
        if (buf[--i] <= 9) std::cout << static_cast<char>(buf[i] + '0');
        else std::cout << static_cast<char>(buf[i] + ('a' - 10));
    } while (i);
}

long base2dec(int b, char * p)
{
    long digit;           // Current digit
    long mul = 1;         // Current multiplier
    char *pos = p;        // Current position
    bool neg = false;     // Sign
    long ret = 0;         // The return value

    // Find the last digit
    while (*pos) pos++;

    // Continue until the start of the string is reached
    while (pos-- != p)
    {
        if (*pos < '0')
        {
            if (*pos == '-')
            {
                // Sign reached, save it an break out
                neg = true;
                break;
            }
            else  // Shouldn't happen
            {
                throw std::invalid_argument("Not a number");
            }
        }
        if (*pos > 'f')
            throw std::invalid_argument("Not a number");

        // Get a digit
        if (*pos <= '9') digit = *pos - '0';
        else if (*pos >= 'a') digit = *pos - ('a' - 10);
        else if (*pos >= 'A' && *pos <= 'F')
            digit = *pos - ('A' - 10);
        else
            throw std::invalid_argument("Not a number");

        // Make sure it is not larger than or equal to the base
        if (digit >= b)
            throw std::invalid_argument("Not a number");

        // Add the digit
        ret += digit * mul;

        // Increase the multiplier
        mul *= b;
    }
    return neg ? -ret : ret;
}

int main()
{
    long val = base2dec(16, "123f");
    dec2base(16, val);
    return 0;
}

我意识到你没有要求签名版本但是因为它很容易实现我已经完成了。如果您真的不需要处理签名值,那么从函数中删除相关部分就很简单。

这是一个非常快速和肮脏的问题,这无疑会在可读性和性能方面得到改善,但我认为这是一个很好的起点。

以下是base2dec()的略微改进版本:

long base2dec(int b, char * p)
{
    long digit;           // Current digit
    bool neg = false;     // Sign
    long ret = 0;         // The return value

    // Check for negative number
    if (*p == '-')
    {
        neg = true;
        p++;
    }

    // Continue until the end of the string is reached
    for (; *p != 0; p++)
    {
        // Rough range check
        if (*p < '0' || *p > 'f')
            throw std::invalid_argument("Not a number");

        // Get a digit
        if (*p <= '9') digit = *p - '0';
        else if (*p >= 'a') digit = *p - ('a' - 10);
        else if (*p >= 'A' && *p <= 'F')
            digit = *p - ('A' - 10);
        else
            throw std::invalid_argument("Not a number");

        // Make sure it is not larger than or equal to the base
        if (digit >= b)
            throw std::invalid_argument("Not a number");

        // Add the digit
        ret = ret * b + digit;
    }
    return neg ? -ret : ret;
}

关于validnumber()函数。这个检查最好在转换期间执行,以避免必须读取整个字符串两次,因为base2dec()确实应该检查有效输入。如果您仍需要单独检查,则需要修复validnumber()。不需要将字符串复制到数组中,并且最好对所有基础使用相同的代码。这是一个建议:

bool validnumber(int b, char *p)
{
    // Check for valid base
    if (b < 2 || b > 16) return false;

    // Extract numeric and alpha parts of the base
    int b_numeric = b <= 10 ? b : 10;
    int b_alpha = b - 11;

    // Ignore any sign
    if (*p == '-') p++;

    // Continue until the end of the string
    for (; *p != 0; p++)
    {
        // Digits < 0 are always bad
        if (*p < '0') return false;

        // Check for valid numeric digits
        if (*p > ('0' + b_numeric))
        {
            // Check for valid alpha digits
            if (b <= 10) return false;
            if (*p < 'A' || *p > ('a' + b_alpha)) return false;
            if (*p > ('A' + b_alpha) && *p < 'a') return false;
        }
    }
    return true;
}