4

今天我只是在玩从一个基地到另一个基地的基本转换。我查看了一些用于从十六进制转换为八进制的代码,我注意到它主要使用中间转换为十进制或二进制然后再返回八进制。是否可以编写我自己的函数来将十六进制字符串转换为八进制字符串而不使用任何中间转换.另外我不想使用像or的内置printf选项。感谢您的投入。%x%o

4

7 回答 7

5

当然这是可能的。一个数字是一个数字,不管它在什么数字系统中。唯一的问题是人们习惯于十进制,这就是为什么他们更好地理解它的原因。您可以从任何基础转换为任何其他基础。

编辑:有关如何执行转换的更多信息。

首先请注意,3 个十六进制数字正好映射到 4 个八进制数字。因此,拥有十六进制数字的数量,您可以轻松找到八进制数字的数量:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int get_val(char hex_digit) {
  if (hex_digit >= '0' && hex_digit <= '9') {
    return hex_digit - '0';
  } else {
    return hex_digit - 'A' + 10;
  }
}
void convert_to_oct(const char* hex, char** res) {
  int hex_len = strlen(hex);
  int oct_len = (hex_len/3) * 4;
  int i;

  // One hex digit left that is 4 bits or 2 oct digits.
  if (hex_len%3 == 1) {
    oct_len += 2;
  } else if (hex_len%3 == 2) { // 2 hex digits map to 3 oct digits
    oct_len += 3;
  }

  (*res) = malloc((oct_len+1) * sizeof(char));
  (*res)[oct_len] = 0; // don't forget the terminating char.

  int oct_index = oct_len - 1; // position we are changing in the oct representation.
  for (i = hex_len - 1; i - 3 >= 0; i -= 3) {
    (*res)[oct_index] = get_val(hex[i]) % 8 + '0';
    (*res)[oct_index - 1] = (get_val(hex[i])/8+ (get_val(hex[i-1])%4) * 2) + '0';
    (*res)[oct_index - 2] = get_val(hex[i-1])/4 + (get_val(hex[i-2])%2)*4 + '0';
    (*res)[oct_index - 3] = get_val(hex[i-2])/2 + '0'; 
    oct_index -= 4;
  }

  // if hex_len is not divisible by 4 we have to take care of the extra digits:
  if (hex_len%3 == 1) {
     (*res)[oct_index] = get_val(hex[0])%8 + '0';
     (*res)[oct_index - 1] = get_val(hex[0])/8 + '0';
  } else if (hex_len%3 == 2) {
     (*res)[oct_index] = get_val(hex[1])%8 + '0';
     (*res)[oct_index - 1] = get_val(hex[1])/8 + (get_val(hex[0])%4)*4 + '0';
     (*res)[oct_index - 2] = get_val(hex[0])/4 + '0';
  }
}

这里还有关于 ideone 的示例,以便您可以使用它:example

于 2013-01-10T15:14:51.073 回答
3

这有点棘手,因为您将 4 位组转换为 3 位组 - 您可能希望一次使用 12 位,即 3 个十六进制数字到 4 个八进制数字,然后您必须处理任何剩余的位分开。

例如将 5274 八进制转换为十六进制:

5    2    7    4
101  010  111  100

|||/   \\//   \|||

1010   1011   1100
A      B      C
于 2013-01-10T15:31:15.003 回答
1

是的,您可以相对容易地做到这一点:四个八进制数字始终转换为三个十六进制数字,因此您可以将字符串分成三个十六进制数字的组,并从后面处理每个组。如果您没有足够的十六进制数字来完成一组三个,请添加前导零。

每个十六进制数字给你四位;取最后三个,并将它们转换为八进制。将接下来的四位相加,然后再取三位到八进制。添加最后一组四位 - 现在您总共有六位,因此将它们转换为两位八进制数字。

这避免了将整个数字转换为二进制,尽管在转换数字的过程中会使用一个“滑动”二进制窗口。

考虑一个例子:转换62ABC为八进制。分成三位数组:062ABC(注意前面加的零62组成三位数组)。

从后面开始:

  • C, or 1100, 被切成1and 100, 制作八进制4, 并1为下一步准备额外的位
  • B, 或1011, 被切入10下一步和11这一步。上1一步中的 附加在 的右侧11,形成八进制7
  • A, or 1010, 被砍成101and 0。上10一步中的 附加在右侧,making010或 octal 2101是八进制的55274所以到目前为止。
  • 2成为下一步20
  • 6成为下一步401
  • 0变成0and 1(因为01从上一步添加了)。

最后的结果是01425274

于 2013-01-10T15:18:41.257 回答
1

计算机内存中的所有数字都是以 2 为底的。因此,每当您想对这些值(数学运算)进行实际操作时,您都需要将它们作为整数、浮点数等。所以它很方便,或者将来可能会派上用场通过可计算类型进行转换。

我会避免直接进行字符串到字符串的转换,除非值可能太大而无法放入数字变量中。从头开始编写可靠的转换器非常困难。

(在二进制计算机中使用以 10 为底的意义不大。)

于 2013-01-10T15:26:02.497 回答
1

对我来说似乎是一个非常简单的任务......你想要一个十六进制字符串,你想将它转换为八进制字符串。让我们使用 ASCII 十六进制并将其转换为 int 类型以使用:

char hex_value[] = "0x123";

int value = strtol(hex_value,NULL,16);

在这一点上它仍然是十六进制,那么如果我们想从一个基础转换为另一个基础,可以完成简单的数学运算:

123 / 8 = 24 R 3
 24 / 8 =  4 R 4
  4 / 8 =  0 R 4

这告诉我们 123 16 == 443 8所以我们所要做的就是将数学写入基本函数并将最终值放回字符串中:

char * convert_to_oct(int hex)
{
    int ret = 0, quotient = 0, reminder = 0, dividend = hex, counter = 0, i;
    char * ret_str;   // returned string

    while(dividend > 0){             // while we have something to divide
        quotient = dividend / 0x8;   // get the quotient
        reminder = dividend - quotient * 0x8; // get the reminder

        ret += reminder * pow(10, counter);   // add the reminder (shifted) 
                                              // into our return value
        counter++;            // increment our shift
        dividend = quotient;  // get ready for the next divide operation
    }

    ret_str = malloc(counter);   // allocate the right number of characters
    sprintf(ret_str, "%d", ret); // store the result

    return ret_str;
}

所以这个函数会将一个十六进制(int)值转换成一个八进制字符串。你可以这样称呼它:

int main()
{
   char hex_value[] = "0x123";
   char * oct_value;
   int value = strtol(hex_value,NULL,16);

   // sanity check, see what the value should be before the convert
   printf("value is %x, auto convert via printf gives %o\n", value, value);

   oct_value = convert_to_oct(value);
   printf("value is %s\n", oct_value);
于 2013-01-10T19:13:13.437 回答
0

这是一个将字符转换为 javascript 的简单函数。对 ALERT 或您的页面有效,最高可达 65536 32BITS。您遇到的问题通常是超过 127 的代码文本。最安全的值是 OCTAL。ParseXX 避免。

谢谢你的喜欢(^_^)。免费享受。

 function enjoyOCTALJS (valuestr){
        var arrstr = valuestr.split('');
        arrstr = arrstr.map(f => (!isNaN(f.charCodeAt(0)))? (f.charCodeAt(0)>127)? '\\'+f.charCodeAt(0).toString(8):f:f);
        return arrstr.join('');
                                }

如果您只想获取字符的八进制值,请执行以下操作:Max = 65536 或 0XFFFF。

var mchar = "à";
var result = mchar.charCodeAt(0).toString(8);

或完全:

var mchar = 'à';
var result = mchar.codePointAt(0).toString(8);

如果值 > 65536,则返回 UNDEFINED。您可以使用函数参数来增加该值。charCodeAt(x) 或 codePointAt(x)。

您的计算机将所有内容视为 0 到 255。

我们不需要做很大的函数来转换字符,这很容易。

CHAR TO UNICIDE

var mchar = 'à';
var result = mchar.codePointAt(0);  or  mchar.charCodeAt();

UNICODE转八进制:

var mcode = 220;
var result = mcode.toString(8);

ETC... :)

于 2019-03-13T13:26:07.517 回答
0

所有八进制数字都包含 3 位信息。所有十六进制数字都包含 12 位信息。3和4的最小公倍数是12。

这意味着您可以构建一个简单的查找表

0000 = 0x000
0001 = 0x001
0002 = 0x002
...
0007 = 0x007
0010 = 0x008
0011 = 0x009
0012 = 0x00A
...
0017 = 0x00F
0020 = 0x010
...
5274 = 0xABC
...

现在有了这个想法,您有几种选择:

  1. 构建地图(查找表)

这里的例程将在八进制(字符串)数字中添加前导零,直到它长 4 位,然后从表中查找十六进制值。两种变体是静态输入表格或动态填充表格。

  1. 使用数学替换查找表

您可以计算它们,而不是输入每个解决方案

hexdigit1 = 01 & octaldigit8 + octaltdigit1;
hexdigit16 = 03 & octaldigit64 << 02 + 06 & octaldigit8 >> 01;
hexdigit256 = octaldigit512 << 01 + 01 & octaldigit64;

其中 octaldigit1 / hexdigit16 / octaldigit8 分别表示“八进制 1 的位置”、“十六进制 16 的位置”、“八进制 8 的位置”。

请注意,在这两种情况下,您都不会“使用二进制”或“使用十进制”,但由于这些数字可以在这两个系统中的任何一个中表示,因此无法避免有人落后并分析 (或任何)十进制或二进制的解决方案。

于 2019-03-13T13:41:44.170 回答