【问题标题】:Convert int to ASCII characters in C在 C 中将 int 转换为 ASCII 字符
【发布时间】:2018-06-10 01:59:53
【问题描述】:

如何在 C 语言中将整数值转换为 ASCII 字符? 我想将字符分配给字符数组。

char buff[10];

假设我们有:

int = 93  (HEX: 5D) -> result should be - buff = {']'} 

int = 13398 (HEX: 3456) -> result should be buff = {'4', 'V'}

类似here

我不需要关心不可打印的字符。总会有可打印的字符。

【问题讨论】:

  • 5D(十六进制)是']'....不确定你想用尾随'C'做什么......你可能想更清楚你打算如何处理多个int 中的 char 值
  • 5DC 转换为']' 时。 C 去哪儿了。
  • @alk 它应该和here 一样做,所以它总是需要 8 口,如果剩下的 8 口少,它什么也不会返回。
  • 0x10000 呢?
  • 你怎么知道1500应该是{']'}而不是{'\x05', '\xDC'}

标签: c converter


【解决方案1】:

只需使用位移来获取单个字节。

假设int的大小为4的架构:

int someInt = ...

uint8_t first = (someInt >> 24);
uint8_t second = (someInt >> 16);
uint8_t third = (someInt >> 8);
uint8_t fourth = someInt;

现在您可以将生成的字节放入您的数组中。确保首先检查firstsecondthird 以确保它们不是0,如果是则跳过它们。确保按照 C 字符串的要求以空终止符结束您的数组。

此答案假定大端顺序,因为这就是您在示例中所指出的。如果你想要 little-endian,只需在将字节放入数组时颠倒它们的顺序即可。

请注意,这会将5DC 转换为05DC。如果您想要5D,则应检查原始int 中的第一个数字是否为0。您可以使用& 运算符来执行此操作,针对0xf00000000x00f00000 等测试int。如果您发现第一个数字是0,请将int 向右移动4 位在从中提取字节之前。

所以,是这样的:

void ExtractBytes(int anInt, uint8_t *buf, size_t bufSize) {
    // passing an empty buffer to this function would be stupid,
    // but hey, doesn't hurt to be idiot-proof
    if (bufSize == 0) { return; }

    // Get our sizes
    const int intSize = sizeof(anInt);
    const int digitCount = intSize * 2;

    // find first non-zero digit
    int firstNonZero = -1;
    for (int i = 0; i < digitCount; i++) {
        if ((anInt & (0xf << ((digitCount - 1 - i) * 4))) != 0) {
            firstNonZero = i;
            break;
        }
    }

    if (firstNonZero < 0) {
        // empty string; just bail out.
        buf[0] = 0;
        return;
    }

    // check whether first non-zero digit is even or odd;
    // shift if it's odd
    int intToUse = (firstNonZero % 2 != 0) ? (anInt >> 4) : anInt;

    // now, just extract our bytes to the buffer
    int bufPtr = 0;
    for (int i = intSize - 1; i >= 0; i--) {
        // shift over the appropriate amount, mask against 0xff
        uint8_t byte = (intToUse >> (i * 8));

        // If the byte is 0, we can just skip it
        if (byte == 0) {
            continue;
        }

        // always check to make sure we don't overflow our buffer.
        // if we're on the last byte, make it a null terminator and bail.
        if (bufPtr == bufSize - 1) {
            buf[bufPtr] = 0;
            return;
        }

        // Copy our byte into the buffer
        buf[bufPtr++] = byte;
    }

    // Now, just terminate our string.
    // We can be sure that bufPtr will be less than bufSize,
    // since we checked for that in the loop. So:
    buf[bufPtr] = 0;

    // Aaaaaand we're done
}

现在让我们试一试:

uint8_t buf[10];

ExtractBytes(0x41424344, buf, 10);
printf("%s\n", buf);

ExtractBytes(0x4142434, buf, 10);
printf("%s\n", buf);

和输出:

ABCD
ABC

【讨论】:

  • 谢谢。这似乎是正确的解决方案,但我想自动执行...是否有任何内置功能?
  • @Joozty 有一些技巧似乎会奏效,但当你真正尝试它们时,它们不会奏效。例如,您可以使用 memcpy 和指向您的 int 的指针并将其复制到您的字符串中,但如果您使用的是 little-endian 架构(并且您可能是),那会将 0x12345678 变成{ 0x78, 0x56, 0x34, 0x12 }。您可以使用适合您平台 API 的函数首先将 int 交换为 big-endian,但是您仍然不会像您想要的那样删除最后一个数字。老实说,IMO 自己做是最简单的。
  • @Joozty 我为你充实了一点;检查编辑。
  • 很好奇,为什么uint8_t first = (someInt &gt;&gt; 24); 中没有&amp; 0xff 像接下来的 3 行代码一样?如果someInt == -1 那么someInt &gt;&gt; 24 仍然有24 个高位可以忽略。 IAC,4 个中的任何一个都不需要。
  • @chux 你是对的;因为它们被存储在uint8_t 中,所以无论如何都会被砍掉。我最近一直在做很多 Swift,试图存储比类型可以容纳的更大的东西会导致运行时错误,而不是仅仅将其砍掉,这在我的脑海中现在有点(第一个会无论如何也需要被屏蔽;那是我的错。我在想我通常对无符号整数做什么)。我已经编辑了答案;谢谢。
【解决方案2】:

将整数值转换为 C 语言中的 ASCII 字符?...

引用 ASCII table,C 中 ']' 的值将始终被解释为 0x5D,或十进制值 93。而 C 中的“]”值将始终被解释作为NULL 终止的字符数组,即由值组成的字符串表示:

|93|\0|  

(如 This Answer 所示,类似的解释对所有 ASCII 字符都有效。)

要将任何整数 (char) 值转换为类似于“]”的值,您可以使用字符串函数将 char 值转换为字符串表示形式。例如,所有这些变体都将执行该转换:

char strChar[2] = {0};

sprintf(strChar, "%c", ']'); 
sprintf(strChar, "%c", 0x5D); 
sprintf(strChar, "%c", 93);  

每个生成相同的 C 字符串:"]"

我想将字符分配给字符数组...

如何创建以NULL char 结尾的char 数组的示例,例如“ABC...Z”:

int i;
char strArray[27] = {0};
for(i=0;i<26;i++)
{
     strArray[i] = i+'A';
}
strArray[i] = 0;
printf("Null terminated array of char: %s\n", strArray);

【讨论】:

    【解决方案3】:
    unsigned u = ...;
    
    if (0x10 > u)
      exit(EXIT_FAILURE);
    
    while (0x10000 < u) u /= 2;
    while (0x1000 > u) u *= 2;
    
    char c[2] = {u / 0x100, u % 0x100);
    

    【讨论】:

    • DEC(1212696648), HEX(48484848) - ASCII(FFFF) 更大的数字怎么样?
    • @Joozty:回答我的问题时,您评论说将 0x10000 与 0x100000 视为 0x1000000 ....
    猜你喜欢
    • 2011-07-16
    • 2023-03-24
    • 1970-01-01
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-03
    相关资源
    最近更新 更多