在C和C ++中将char转换为int


400

如何转换charintC和C ++?


1
@马特:更具体一点是个好主意。询问泛化只是邀请了对您的任务不适用甚至不正确的泛化答案。请记住,当您不得不问时,您可能不了解正确的概括。
干杯和健康。-Alf

@Alf P. Steinbach:最初的问题是关于哪种语言的。使用关键字cc++,我认为两种语言面对的答案都是合理的。
马特·乔纳

8
根据我在其他技术论坛上的丰富经验,我的直觉是,OP的真正含义是“我如何将数字的文字表示形式(以10为底)转换为相应的数字?” 一般而言,C和C ++新手通常对文本在这些语言中的工作方式及其真正含义具有令人难以置信的模糊观念char
Karl Knechtel

3
@KarlKnechtel:如果是真的(我给了它大约50/50,因为许多早期的教程也鼓励从字符中获取ASCII值,即使ASCII不能覆盖整个范围),OP需要明确说明-但这很愚蠢的stackoverflow.com/questions/439573/...
Fred Nurk

3
OP花费了三个小时来澄清这个问题,但没有这样做。事实是,无法知道实际要问什么。投票关闭。
2011年

Answers:


551

取决于您要做什么:

读取值作为ASCII代码,您可以编写

char a = 'a';
int ia = (int)a; 
/* note that the int cast is not necessary -- int ia = a would suffice */

转换字符'0' -> 0'1' -> 1等等,你可以写

char a = '4';
int ia = a - '0';
/* check here if ia is bounded by 0 and 9 */

说明
a - '0'等同于((int)a) - ((int)'0'),这意味着字符的ascii值彼此相减。由于0紧接1在ascii表中的前面(依此类推,直到9),因此两者之间的差异给出了该字符a代表的数字。


14
ia =(a-'0')%48;
Kshitij Banerjee

@KshitijBanerjee这不是一个好主意,有两个原因:它为您提供一个负的数字,表示'0'之前的ascii字符(如&-> -10),并且为您提供大于10的数字(如x-> 26)
SheetJS

2
int ia = a-'0'-这就是您所需要的
放克

5
@ kevin001如果要将char转换为int且字符'1'提供的ascii不是1,则需要删除偏移量'0'以将其重新对齐以从0-9开始计数。连续数字1-9在ascii整数数字中相邻。
krisdestruction

不需要/不需要演员
Craig Estey

97

好吧,在ASCII码中,数字(数字)从48开始。您需要做的只是:

int x = (int)character - 48;

19
@chad:不仅更具可读性,而且更便于携带。C和C ++不保证ASCII表示,但是它们保证无论使用哪种表示,十进制十进制的表示都是连续的,并且是数字顺序。
Ben Voigt

我唯一要更改的是将48 '0'
岁生日

59

C和C ++总是将类型至少提升为int。此外,字符文字int在C和charC ++中都是类型。

char只需分配一个即可转换类型int

char c = 'a'; // narrowing on C
int a = c;

3
为此,您也可以使用一度被低估的一元算法 operator+()
Cubbi

24
-1对于问题的唯一有意义的解释,答案是错误的。此(代码int a = c;)将保留C标准库函数无法处理的任何负值。C标准库函数设置了将char值处理为的标准int
干杯和健康。-Alf

6
@马特:我一直在投票。如果可能,我会加强!您和其他人认为的问题解释没有意义,因为它太微不足道了,并且由于OP的特定类型组合,存在一个非常重要的实际问题。您提供的建议对新手来说是直接危险的。对于使用C标准库字符分类功能的程序,最有可能导致未定义行为。重新参考 @Sayam的答案,他已删除该答案。
干杯和健康。-Alf

3
-1不正确:如果传递了1252个高位字符,则isupper()将具有未定义的结果。
克里斯·贝克

1
您“永远提升”是什么意思?在隐式转换,某些类型的参数传递(例如,传递给varargs函数)以及操作符必须使其操作数兼容的类型时,将提升值。但是肯定有些时候不提升值(例如,如果我将char传递给需要char的函数),否则我们不会有任何小于int的类型。
Adrian McCarthy

31

char只是1个字节的整数。char类型没有什么魔术!正如可以将int分配给short或将int分配给long一样,可以将char分配给int。

是的,原始数据类型的名称恰好是“ char”,这表明它只能包含字符。但实际上,“字符”只是一个糟糕的选择,以使每个尝试学习该语言的人感到困惑。更好的名称是int8_t,如果编译器遵循最新的C标准,则可以改用该名称。

尽管在进行字符串处理时当然应该使用char类型,因为经典ASCII表的索引适合1个字节。但是,您也可以使用常规int进行字符串处理,尽管在现实世界中没有实际的理由为什么您会这样做。例如,以下代码将完美运行:

  int str[] = {'h', 'e', 'l', 'l', 'o', '\0' };

  for(i=0; i<6; i++)
  {
    printf("%c", str[i]);
  }

您必须意识到,字符和字符串只是数字,就像计算机中的其他所有东西一样。在源代码中写入“ a”时,会将其预处理为数字97,这是一个整数常量。

所以如果你写一个像

char ch = '5';
ch = ch - '0';

这实际上相当于

char ch = (int)53;
ch = ch - (int)48;

然后通过C语言整数促销

ch = (int)ch - (int)48;

然后截断为char以适合结果类型

ch = (char)( (int)ch - (int)48 );

在行之间有很多这样的微妙的事情,其中​​char被隐式地视为一个int。


由于问题未使用标记ascii,因此您不应采用任何特定的编码。将charequal 设置为true int8_t是错误的,因为它可能同样是uint8_tor uint24_t
罗兰·伊利格

1
@RolandIllig否,a char始终为1个字节,如果给定系统上的类型int8_t/ uint8_t存在(很有可能),则它们将能够满足a的结果char,因为它将是8位。在高度陌生的系统(例如各种过时的DSP)上,char将为16位,并且uint8_t将不存在。编写与过时的DSP兼容的代码是胡说八道,为与一个人的补码或符号和幅度系统兼容而编写的代码也没有意义。因为这样的系统在现实世界中几乎不存在,所以浪费了大量时间。
隆丁

18

(此答案解决了C ++方面的问题,但C中也存在符号扩展问题。)

处理这三种char类型(signedunsignedchar)比它最初看起来要精致得多。介于0到SCHAR_MAX(8位为127 char)之间的值很容易:

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
int n = c;

但是,当somevalue超出该范围时,只有经过这三种类型unsigned char的“相同” char值,您才能获得一致的结果:

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
// Might not be true: int(c) == int(sc) and int(c) == int(uc).
int nc = (unsigned char)c;
int nsc = (unsigned char)sc;
int nuc = (unsigned char)uc;
// Always true: nc == nsc and nc == nuc.

当使用ctype.h中的函数(例如isupper或)时toupper,由于符号扩展,这一点很重要:

char c = negative_char;  // Assuming CHAR_MIN < 0.
int n = c;
bool b = isupper(n);  // Undefined behavior.

注意,通过int进行的转换是隐式的;这具有相同的UB:

char c = negative_char;
bool b = isupper(c);

要解决此问题,请仔细阅读unsigned char,这很容易通过使用safe_ctype包装ctype.h函数来完成

template<int (&F)(int)>
int safe_ctype(unsigned char c) { return F(c); }

//...
char c = CHAR_MIN;
bool b = safe_ctype<isupper>(c);  // No UB.

std::string s = "value that may contain negative chars; e.g. user input";
std::transform(s.begin(), s.end(), s.begin(), &safe_ctype<toupper>);
// Must wrap toupper to eliminate UB in this case, you can't cast
// to unsigned char because the function is called inside transform.

之所以可行,是因为任何采用三种字符类型的函数都可以采用另外两种字符类型。它导致两个可以处理任何类型的函数:

int ord(char c) { return (unsigned char)c; }
char chr(int n) {
  assert(0 <= n);  // Or other error-/sanity-checking.
  assert(n <= UCHAR_MAX);
  return (unsigned char)n;
}

// Ord and chr are named to match similar functions in other languages
// and libraries.

ord(c)始终会为您提供非负值(即使传递的是负值char或负值)signed char,并且chrord产生任何值并返回完全相同的值char

在实践中,我可能只是强制转换unsigned char而不是使用它们,但是它们确实简洁地包装了转换,提供了一个方便的位置来添加对int-to-的错误检查char,并且在需要多次使用它们时会更短,更清晰在附近。



7

它取决于您“转换”的含义。

如果您有一系列代表整数的字符,例如“ 123456”,那么在C语言中有两种典型的实现方法:使用特殊转换,例如atoi()strtol(),或通用sscanf ()。C ++(实际上是另一种伪装为升级的语言)添加了第三个字符串流。

如果您想将其中一个int变量的确切位模式视为,则会char更容易。在C语言中,不同的整数类型实际上比实际的单独“类型”更像是一种心态。只要在char要求s的地方开始使用它,就可以了。您可能需要进行显式转换,以使编译器偶尔退出抱怨状态,但是所有要做的就是丢弃超过256位的所有额外位。


6

我对nullC 有绝对的技能,但需要进行简单的分析:

char* something = "123456";

int number = parseInt(something);

...这对我有用:

int parseInt(char* chars)
{
    int sum = 0;
    int len = strlen(chars);
    for (int x = 0; x < len; x++)
    {
        int n = chars[len - (x + 1)] - '0';
        sum = sum + powInt(n, x);
    }
    return sum;
}

int powInt(int x, int y)
{
    for (int i = 0; i < y; i++)
    {
        x *= 10;
    }
    return x;
}

此代码快速调用未定义的行为,因此不适合复制和粘贴。(int溢出)
罗兰·伊利格

4

大概您希望使用C标准库中的函数进行此转换。

在这种情况下,请执行(C ++语法)

typedef unsigned char UChar;

char myCppFunc( char c )
{
    return char( someCFunc( UChar( c ) ) );
}

表达式UChar( c )转换为unsigned char以消除负值,C函数不支持EOF除外的负值。

然后,将该表达式的结果用作int形式参数的实际参数。您会自动升级到int。您也可以选择明确地写上最后一步,例如int( UChar( c ) ),但是个人觉得太冗长了。

干杯,……


0

我在将一个char数组转换"7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"为它的实际整数值时遇到问题,该值可以由7C表示为一个十六进制值。因此,在寻求帮助之后,我创建了这个,并认为分享是一件很酷的事情。

这会将char字符串分成正确的整数,这可能对不仅仅是我自己的人有更多帮助;)

unsigned int* char2int(char *a, int len)
{
    int i,u;
    unsigned int *val = malloc(len*sizeof(unsigned long));

    for(i=0,u=0;i<len;i++){
        if(i%2==0){
            if(a[i] <= 57)
                val[u] = (a[i]-50)<<4;
            else
                val[u] = (a[i]-55)<<4;
        }
        else{
            if(a[i] <= 57)
                val[u] += (a[i]-50);
            else
                val[u] += (a[i]-55);
            u++;
        }
    }
    return val;
}

希望能帮助到你!


您是否曾经测试过此代码?50应该是48,55仅适用于大写ASCII字母,而您的示例包含小写字母。
罗兰·伊利格

0

对于char或int的缩写,您只需要分配值即可。

char ch = 16;
int in = ch;

与int64相同。

long long lo = ch;

所有值均为16。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.