在 C 和 C++ 中将 char 转换为 int
Posted
技术标签:
【中文标题】在 C 和 C++ 中将 char 转换为 int【英文标题】:Convert char to int in C and C++ 【发布时间】:2011-06-29 03:03:12 【问题描述】:如何在 C 和 C++ 中将 char
转换为 int
?
【问题讨论】:
@Matt:更具体一点是个好主意。询问概括只会邀请那些不适用甚至对您的任务正确的概括性答案。请记住,当你不得不问的时候,你可能没有足够的知识来正确概括。 @Alf P. Steinbach:最初的问题是关于哪种语言含糊不清。使用关键字c
和c++
,我认为两种语言的答案都是合理的。
根据我在其他技术论坛上的丰富经验,我的直觉是 OP really 的意思是“我如何获取数字的文本表示(以 10 为底)并转换对应的号码?”一般来说,C 和 C++ 新手通常对这些语言中的文本如何工作以及 char
的真正含义有难以置信模糊的想法。
@KarlKnechtel:如果这是真的(我给它大约 50/50,因为许多早期教程也鼓励从字符中获取 ASCII 值,即使 ASCII 没有覆盖全部范围),OP需要澄清 - 但这是***.com/questions/439573/…的欺骗。
OP 花了三个小时来澄清这个问题,但没有这样做。事实上,没有办法知道实际问的是什么。投票结束。
【参考方案1】:
取决于你想做什么:
要将值作为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
在ascii 表中直接出现在1
之前(依此类推直到9
),因此两者之间的差值就是字符a
所代表的数字。
【讨论】:
@KshitijBanerjee 这不是一个好主意,原因有两个:它为您在“0”之前的 ascii 字符提供了一个负数(例如&
-> -10),并且它为您提供了大于10(如x
-> 26)
int ia = a - '0' - 这就是你所需要的
@kevin001 如果要将 char 转换为 int 并且字符 '1'
提供的 ascii 数字不是 1
,则需要删除偏移量 '0'
以重新对齐以计数0-9。连续数字 1-9 在 ascii 整数中相邻。
不需要/不需要演员表
@foo-bah 但是我不明白为什么我们必须用字符'0'减去它,如果我们只将该字符类型转换为整数并将其存储为整数,为什么它会抛出错误。? 【参考方案2】:
嗯,在 ASCII 码中,数字(数字)从 48 开始。您需要做的就是:
int x = (int)character - 48;
或者,由于字符'0'的ASCII码是48,你可以这样写:
int x = character - '0'; // The (int) cast is not necessary.
【讨论】:
【参考方案3】:C 和 C++ 总是将类型提升到至少 int
。此外,字符文字在 C 中属于 int
类型,在 C++ 中属于 char
类型。
您可以简单地通过分配给int
来转换char
类型。
char c = 'a'; // narrowing on C
int a = c;
【讨论】:
你也可以使用被严重低估的 unaryoperator+()
来达到这个目的。
-1 对于问题的唯一有意义的解释,答案是不正确的。这(代码int a = c;
)将保留任何负值,这是C 标准库函数无法处理的。 C 标准库函数为将 char
值处理为 int
的含义设定了标准。
@Matt:我不赞成。如果可以的话,我会加强它!您和其他人假设的问题解释没有意义,因为它太微不足道了,并且因为对于 OP 的特定类型组合,存在一个不那么微不足道的非常重要的实际问题。你给出的建议对新手来说直接危险。对于他们使用 C 标准库字符分类函数的程序,它很可能会导致 Undefined Behavior。重新参考。对于@Sayam 的回答,他已经删除了那个回答。
-1 表示不正确:如果传递 1252 高位字符,isupper() 将产生未定义的结果。
你所说的“总是推广”是什么意思?在隐式转换、某些类型的参数传递(例如,传递给 varargs 函数)以及运算符必须使其操作数兼容类型时,值会被提升。但是肯定有一些时候一个值不会被提升(比如如果我将一个 char 传递给一个期望一个 char 的函数),否则我们不会有任何小于 int 的类型。【参考方案4】:
char 只是一个 1 字节的整数。 char 类型没有什么神奇之处!就像您可以将 short 分配给 int,或将 int 分配给 long 一样,您也可以将 char 分配给 int。
是的,原始数据类型的名称恰好是“char”,暗示它应该只包含字符。但实际上,“char”只是一个糟糕的名称选择,让所有试图学习该语言的人感到困惑。一个更好的名称是 int8_t,如果您的编译器遵循最新的 C 标准,您可以使用该名称。
当然,您在处理字符串时应该使用 char 类型,因为经典 ASCII 表的索引适合 1 个字节。您也可以使用常规整数进行字符串处理,尽管在现实世界中没有实际理由为什么您会想要这样做。例如,以下代码将完美运行:
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;
然后截断为字符以适应结果类型
ch = (char)( (int)ch - (int)48 );
字里行间有很多类似这样的微妙事情,其中 char 被隐式视为 int。
【讨论】:
由于该问题未使用ascii
标记,因此您不应假设任何特定编码。将char
设置为等于int8_t
是错误的,因为它同样可能是uint8_t
或uint24_t
。
@RolandIllig 不,char
始终为 1 个字节,如果给定系统上存在 int8_t
/uint8_t
类型(很可能),它们将能够适应char
的结果,因为它将是 8 位。在诸如各种过时的 DSP 等高度奇特的系统上,char
将是 16 位,而uint8_t
将不存在。为与过时的 DSP 兼容而编写代码是无稽之谈,为与补码或符号和幅度系统兼容而编写代码也是如此。非常浪费时间,因为这样的系统在现实世界中几乎不存在。【参考方案5】:
(这个答案解决了 C++ 方面的问题,但 C 中也存在符号扩展问题。)
处理所有三种char
类型(signed
、unsigned
和char
)比最初看起来要复杂得多。 0 到 SCHAR_MAX
(对于 8 位 char
为 127)范围内的值很简单:
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
,这很容易通过将 ctype.h 函数包装到safe_ctype 来完成:
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.
这是可行的,因为任何采用三种 char 类型中的任何一种的函数也可以采用其他两种 char 类型。它导致两个函数可以处理任何类型:
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
——并且chr
取任何值ord
产生并返回完全相同的char
。
在实践中,我可能只是通过unsigned char
进行转换而不是使用这些,但它们确实简洁地包装了转换,提供了一个方便的位置来为int
-to-char
添加错误检查,并且会是当您需要近距离使用它们多次时,它们会更短更清晰。
【讨论】:
【参考方案6】:使用static_cast<int>
:
int num = static_cast<int>(letter); // if letter='a', num=97
编辑:您可能应该尽量避免使用 (int)
int num = (int) 字母;
查看Why use static_cast<int>(x) instead of (int)x? 了解更多信息。
【讨论】:
【参考方案7】:我绝对有null
的 C 技能,但是对于一个简单的解析:
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;
【讨论】:
此代码快速调用未定义的行为,因此不适合复制和粘贴。 (整数溢出)【参考方案8】:这有点取决于您所说的“转换”是什么意思。
如果您有一系列表示整数的字符,例如“123456”,那么在 C 中有两种典型的方法可以做到这一点:使用特殊用途的转换,例如 atoi() 或 strtol(),或者通用-目的sscanf()。 C++(实际上是一种伪装成升级的不同语言)添加了第三个字符串流。
如果您的意思是希望将 int
变量之一中的确切位模式视为 char
,那就更容易了。在 C 中,不同的整数类型实际上更像是一种心态,而不是实际的单独“类型”。只需在要求char
s 的地方开始使用它,您应该就可以了。您可能需要显式转换以使编译器偶尔停止抱怨,但应该做的就是删除超过 256 的任何额外位。
【讨论】:
【参考方案9】:大概您希望这种转换用于使用 C 标准库中的函数。
在这种情况下,做(C++ 语法)
typedef unsigned char UChar;
char myCppFunc( char c )
return char( someCFunc( UChar( c ) ) );
表达式UChar( c )
转换为unsigned char
以消除除EOF 之外的C 函数不支持的负值。
然后将该表达式的结果用作int
形式参数的实际参数。您可以在哪里自动升级到int
。你也可以明确地写最后一步,比如int( UChar( c ) )
,但我个人觉得这太冗长了。
干杯,
【讨论】:
【参考方案10】:我在将"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 字母,而您的示例包含小写字母。【参考方案11】:对于 char 或 short to int,你只需要赋值即可。
char ch = 16;
int in = ch;
与 int64 相同。
long long lo = ch;
所有值都是 16。
【讨论】:
【参考方案12】:我推荐使用以下功能:
/* chartoint: convert char simbols to unsigned int*/
int chartoint(char s[])
int i, n;
n = 0;
for (i = 0; isdigit(s[i]); ++i)
n = 10 * n + (s[i] - '0');
return n;
函数的结果可以通过以下方式检查:
printf("char 00: %d \r\n", chartoint("00"));
printf("char 01: %d \r\n", chartoint("01"));
printf("char 255: %d \r\n", chartoint("255"));
【讨论】:
【参考方案13】:int charToint(char a)
char *p = &a;
int k = atoi(p);
return k;
您可以使用此 atoi 方法将 char 转换为 int。更多信息可以参考这个http://www.cplusplus.com/reference/cstdlib/atoi/,http://www.cplusplus.com/reference/string/stoi/。
【讨论】:
这是未定义的行为。获取 char 变量的地址会给你一个 char* 但不是 C 字符串,这是 atoi 所期望的。以上是关于在 C 和 C++ 中将 char 转换为 int的主要内容,如果未能解决你的问题,请参考以下文章
无法在赋值c ++中将char *转换为int * [关闭]
c++ 不使用 C 标准库将字符串和 int 转换为 char*