将字符显示为整数而不需要显式转换

4
每次我向cout对象发送char时,它都会以ASCII字符显示,除非我将其转换为int类型。
问:有没有一种方法可以在没有显式转换的情况下显示char的数值?
我曾在某个地方读到,在代码中做太多的转换可能会导致程序完整性(of your program)丧失。我猜测chars以ASCII形式显示是有特定原因的,但我不确定。
本质上,我正在创建一个游戏。我使用小数字(无符号char),计划将其显示在控制台上。我可能有点多疑,但每当我在我的代码中到处使用static_cast时,我就感到不安。

1
你不能只使用 int 代替 unsigned char 吗?你不是在用 char 来节省内存吧? - jrok
2
你所读到的“完整性丢失”这个词可能并不足够准确地描述当前的使用情况。这取决于你使用强制转换的目的。糟糕的强制转换是为了避免设计和维护一组适当的类型,但这不是你在这里做的事情。流插入运算符<<的效果是明确定义和广泛理解的。将char转换为int以将其馈送到流中是标准技术。这里没有完整性威胁。 - thb
@jrok 是的,我正在使用无符号字符来节省内存。我不应该这样做吗? - Dasaru
@Dasaru:如果你有几百万个,那么内存节省会累加起来。但如果只有几十个,额外需要的代码将淹没数据节省。 - MSalters
2个回答

5

类型转换并没有错,尤其是如果你使用static_cast来进行转换。这是你应该使用的方式。它允许编译器验证类型转换并确保其安全性。

要改变<<运算符的行为,你需要重载默认的char<<运算符,例如:

std::ostream& operator <<(std::ostream &os, char c)
{
    os << static_cast<int>(c);
    return os;
}

char c = ...;
std::cout << c;

您可以创建一个自定义类型,该类型以char作为输入,然后为该类型实现<<运算符,例如:

struct CharToInt
{
    int val;
    CharToInt(char c) : val(static_cast<int>(c)) {}
};

std::ostream& operator <<(std::ostream &os, const CharToInt &c)
{
    os << c.val;
    return os;
}

char c = ...;
std::cout << CharToInt(c);

你可以创建一个类似的函数来实现相同的功能,这样就不需要重载<<运算符了,例如:
int CharToInt(char c)
{
    return c;
}

char c = ...;
std::cout << CharToInt(c);

更改默认流运算符通常不是一个好主意... 你现在可能想打印数字,但在代码的其他地方可能会想要打印字符。另外,operator<< 的正确返回类型是 std::ostream&(即应该是一个引用)。 - Tony Delroy
这就是为什么我提供了更明确的替代方案。而且我也更新了我的例子,谢谢。 - Remy Lebeau

0

就事论事而言,这是一种合理的类型转换使用方式,但是确实可以改进。所涉及的“完整性损失”仅仅是如果其中一个数据类型从char变为double,强制转换将继续编译但可能不会产生预期的结果。您可以创建一个辅助函数来代替:

inline int to_int(char c) { return static_cast<int>(c); }

与 static_cast 不同,只有当原始类型为 char 时才会触发此操作,因此如果您更改为类似 double 的内容,则会收到编译器警告 - 这实际上是提醒您审查代码的一种方式。

他问如何在没有CAST的情况下完成它。虽然我最近没有大量使用C ++,但我真的很喜欢这个。 :-) - trumpetlicks
我认为你也可以像这样做:template <typename T, typename U> T implicit_conversion(const U &u) { return u; }。使用时像这样:std::cout << implicit_conversion<int>(c);(未经测试,我记不清模板参数应该以什么顺序才能使类型推导起作用)。这样做适用于所有类型且不含任何转换,因此编译器会有机会警告您是否合法但可疑的转换。 - Steve Jessop
@trumpetlicks:“在你的代码中进行太多的转换”...这被称为因式分解...在一个受控制的地方做一些可能丑陋的事情。 - Tony Delroy
@Steve:在上面的代码中,如果您觉得 static_cast<int>() 没有增加文档价值,您可以省略它,并让返回语句自动将 char 推广为 int。 - Tony Delroy
@Tony:同意,我的函数的想法是当“你改变到像double这样的东西”时,只有在编译器认为将新类型转换为int需要警告时才会收到警告。因此,例如,您可以更改为short而无需更新代码,因为short->int转换不再比char->int令人担忧。 - Steve Jessop
显示剩余2条评论

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