在C语言中将整型转换为字符型

9

我现在正在尝试在C编程中将一个整数转换为字符。经过研究,我发现应该可以像这样实现:

int value = 10;
char result = (char) value;

我希望这个函数返回“A”(0-9返回“0”-“9”),但它似乎返回了换行符。整个函数如下:
char int2char (int radix, int value) {
  if (value < 0 || value >= radix) {
    return '?';
  }

  char result = (char) value;

  return result;
}

3
将数字 10 转换为字母 'A',可能是基于十六进制数字的转换方式。您是否期望使用十六进制数字进行转换? - Barmar
可能是如何在C语言中将整数转换为字符?的重复问题。 - PM 77-1
2
@PM77-1:这个更好,因为问题表述更清晰。我已经将那个关闭并转移到这个问题下。 - Bathsheba
可能是在C和C++中将char转换为int的重复问题。 - phuclv
9个回答

8
将 int 转换为 char,您无需做任何操作。
char x;
int y;


/* do something */

x = y;

仅将一个整数转换为字符值,作为可打印字符(通常是ASCII码)数字,就像你的例子中一样:

const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

int inttochar(int val, int base)
{
    return digits[val % base];
}

如果您想将其转换为字符串(char *),那么您需要使用任何标准函数,如sprintf,itoa,ltoa,utoa,ultoa ....或编写自己的函数:

char *reverse(char *str);
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

char *convert(int number, char *buff, int base)
{
    char *result = (buff == NULL || base > strlen(digits) || base < 2) ? NULL : buff;
    char sign = 0;


    if (number < 0)
    {
         sign = '-';

    }
    if (result != NULL)
    {
        do
        {
            *buff++ = digits[abs(number % (base ))];
            number /= base;
        } while (number);
        if(sign) *buff++ = sign;
        if (!*result) *buff++ = '0';
        *buff = 0;
        reverse(result);
    }
    return result;
}

2
这不是他想要的。他想将数字9转换为字符'9',而不是'\11' - Barmar
1
“将int转换为char时,您无需做任何操作” - 这是什么意思?例如,如果char是有符号的,则如果int无法适应char,则行为将是实现定义的。多年来,在C语言教学中变得草率了。这些可移植性问题很重要。 - Bathsheba
@PeterJ_01 我的评论是在编辑之前,当时只有 x = y; - Barmar
边角案例失误:convert(INT_MAX, ...), convert(-INT_MAX, ...) 可以正常工作。 convert(INT_MIN, ..., 10), convert(INT_MIN, ..., 2) 失败了。有趣的是,最后两个失败了,并显示为 "" 和 "0000000000000000000000000000000"。可以确定 convert(INT_MIN... 在使用 number = -number;digits[number % (base )] 时会引发 UB。 - chux - Reinstate Monica
@chux yo- 排序完成 - 0___________
显示剩余7条评论

5
一种可移植的方法是定义一个
const char* foo = "0123456789ABC...";

其中 ... 是您想要考虑的其余字符。

然后,foo[value] 将计算特定的 char。例如,foo[0] 将是 '0'foo[10] 将是 'A'

如果您假设特定的 编码(如常见但并非普遍使用的 ASCII),则您的代码不是严格可移植的。


2

字符使用编码(通常是ASCII)将数字映射到特定字符。 字符'0''9'的代码是连续的,因此对于小于10的值,您需要将该值添加到字符常量'0'。 对于大于或等于10的值,则需要将该值减去10并添加到字符常量'A'

char result;
if (value >= 10) {
    result = 'A' + value - 10;
} else {
    result = '0' + value;
}

很奇怪,人们选择这种方式来做,考虑到便携式解决方案并不特别啰嗦,而且可能更快。我相信你知道这一点,但是为了让大家知道,C标准要求0到9连续,但对于字母字符则几乎没有限制。 - Bathsheba

1

将整数转换为字符

我想OP想要的不仅仅是1位数字的转换,因为提供了 radix


将一个int转换为string(不仅限于一个char),可以使用sprintf(buf, "%d", value)方法。
要将其转换为任何基数,需要处理字符串管理问题以及处理INT_MIN的特殊情况。
以下是C99解决方案,返回一个char*,其生命周期有效到块的结尾。通过宏提供复合字面量来实现这一点。
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

// Maximum buffer size needed
#define ITOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 2)

char *itoa_base(char *s, int x, int base) {
  s += ITOA_BASE_N - 1;
  *s = '\0';
  if (base >= 2 && base <= 36) {
    int x0 = x;
    do {
      *(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[abs(x % base)];
      x /= base;
    } while (x);
    if (x0 < 0) {
      *(--s) = '-';
    }
  }
  return s;
}

#define TO_BASE(x,b) itoa_base((char [ITOA_BASE_N]){0} , (x), (b))

使用示例和测试

void test(int x) {
  printf("base10:% 11d base2:%35s  base36:%7s ", x, TO_BASE(x, 2), TO_BASE(x, 36));
  printf("%ld\n", strtol(TO_BASE(x, 36), NULL, 36));
}

int main(void) {
  test(0);
  test(-1);
  test(42);
  test(INT_MAX);
  test(-INT_MAX);
  test(INT_MIN);
}

输出

base10:          0 base2:                                  0  base36:      0 0
base10:         -1 base2:                                 -1  base36:     -1 -1
base10:         42 base2:                             101010  base36:     16 42
base10: 2147483647 base2:    1111111111111111111111111111111  base36: ZIK0ZJ 2147483647
base10:-2147483647 base2:   -1111111111111111111111111111111  base36:-ZIK0ZJ -2147483647
base10:-2147483648 base2:  -10000000000000000000000000000000  base36:-ZIK0ZK -2147483648

参考 如何使用复合字面量以任意进制向fprintf()输出多个格式化数字?


1
我喜欢使用宏来提供一个复合字面量给函数的这个想法。 - ad absurdum

0

看看ASCII表

在char中存储的值被解释为与该表相对应的字符。 10的值是换行符


2
在进行此操作时,请同时检查此编码:https://en.wikipedia.org/wiki/EBCDIC - Bathsheba

0
借鉴现有答案的思路,即利用数组索引。 这里是一个“只管用”的简单演示,用于将整数转换为基数为10的char[],而不需要任何<stdio.h>printf家族接口。
测试:
$ cc -o testint2str testint2str.c && ./testint2str
Result: 234789

代码:

#include <stdio.h>
#include <string.h>

static char digits[] = "0123456789";

void int2str (char *buf, size_t sz, int num);


/*
  Test: 
        cc -o testint2str testint2str.c && ./testint2str
*/
int
main ()
{
  int num = 234789;
  char buf[1024] = { 0 };

  int2str (buf, sizeof buf, num);

  printf ("Result: %s\n", buf);


}

void
int2str (char *buf, size_t sz, int num)
{
  /*
     Convert integer type to char*, in base-10 form.
   */

  char *bufp = buf;
  int i = 0;

  // NOTE-1
  void __reverse (char *__buf, int __start, int __end)
  {
    char __bufclone[__end - __start];
    int i = 0;
    int __nchars = sizeof __bufclone;
    for (i = 0; i < __nchars; i++)
      {
    __bufclone[i] = __buf[__end - 1 - i];
      }
    memmove (__buf, __bufclone, __nchars);
  }

  while (num > 0)
    {
      bufp[i++] = digits[num % 10]; // NOTE-2
      num /= 10;
    }

  __reverse (buf, 0, i);

  // NOTE-3
  bufp[i] = '\0';
}

// NOTE-1:
//         "Nested function" is GNU's C Extension. Put it outside if not
//         compiled by GCC.
// NOTE-2:
//         10 can be replaced by any radix, like 16 for hexidecimal outputs.
//
// NOTE-3:
//         Make sure inserting trailing "null-terminator" after all things
//         done.

注意1:“嵌套函数”是GNU的C扩展。如果不由GCC编译,请将其放在外部。

注意2:10可以被替换为任何基数,例如16用于十六进制输出。

注意3:确保在完成所有事情后插入尾随的“空终止符号”。


0
所以在C语言中,字符是基于ASCII(或与ASCII代码向后兼容的UTF-8)进行编码。这意味着,在底层,“A”实际上是数字“65”(除了二进制而不是十进制)。在C语言中,“char”的作用仅仅是一个有足够字节数来表示每个ASCII字符的整数。如果你想要将一个int转换为char,你需要指示计算机将int的字节解释为ASCII值。但是自从我使用C以来已经很久了,我相信编译器会抱怨,因为charint容量小。这就意味着我们需要一个函数,就像你所编写的一样。
if(value < 10) return '0'+value;
return 'A'+value-10;

将是您希望从函数中返回的内容。像您所做的那样,使用“基数”保持边界检查,我认为这在C语言中是一个好的实践。


3
C语言中的字符基于ASCII(或UTF-8,它与ASCII代码兼容),但不一定如此。 - Bathsheba
2
我不同意。当我开始学习C语言时,就被灌输了可移植性的重要性。这是语言中非常重要的一个方面。不要养成坏习惯。不久之后,你的代码将充斥着未定义行为,并且在进行积极优化时无法正确编译。 - Bathsheba
1
C语言不能保证'A'-'Z'是连续的值 :) - Antti Haapala -- Слава Україні
@AnttiHaapala:绝对没错。但它确保了 '0' - '9' 是连续的。 - Bathsheba
1
彼得的代码不比这更复杂,但是它保证是可移植的。 - Antti Haapala -- Слава Україні
显示剩余2条评论

0

你可以做到

char a;
a = '0' + 5;

你将获得该数字的字符表示。


0

1. 通过类型转换将 int 转换为 char

源文件名为 charConvertByCasting.c

#include <stdio.h>

int main(){
    int i = 66;              // ~~Type Casting Syntax~~
    printf("%c", (char) i); //  (type_name) expression
    return 0;
}

可执行文件 charConvertByCasting.exe 命令行输出:

C:\Users\boqsc\Desktop\tcc>tcc -run charconvert.c
B

附加资源:
https://www.tutorialspoint.com/cprogramming/c_type_casting.htm https://www.tutorialspoint.com/cprogramming/c_data_types.htm

2. 通过赋值将 int 转换为 char

源文件 charConvertByAssignment.c

#include <stdio.h>

int main(){
    int i = 66;
    char c = i;
    printf("%c", c);
    return 0;
}

可执行文件 charConvertByAssignment.exe 命令行输出:

C:\Users\boqsc\Desktop\tcc>tcc -run charconvert.c
B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接