toupper 返回整数而不是字符

Posted

技术标签:

【中文标题】toupper 返回整数而不是字符【英文标题】:toupper returns integer rather than char 【发布时间】:2014-11-15 18:42:53 【问题描述】:

对于下面的函数

void display()

    for (int i = 0; i < 8; i++)
    
        for (int j = 0; j < 8; j++)
        
            if (board[i][j] < 84 && (i+j)%2 == 0)
                SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0x70);
            else if (board[i][j] < 84 && (i+j)%2 == 1)
                SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xc0);
            else if (board[i][j] > 97 && (i+j)%2 == 0)
                SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0x7c);
            else if (board[i][j] > 97 && (i+j)%2 == 1)
                SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), 0xc7);
            cout << " " << toupper(board[i][j]) << " ";
        
        cout << endl;
    

而不是为字符板返回字符[8][8],它返回整数,所以我的输出看起来像

 82  78  66  81  75  66  78  82

 80  80  80  80  80  80  80  80 

 32  32  32  32  32  32  32  32 

 32  32  32  32  32  32  32  32 

 32  32  32  32  32  32  32  32 

 32  32  32  32  32  32  32  32 

 80  80  80  80  80  80  80  80 

 82  78  66  81  75  66  78  82 

而不是预期的输出

 R  N  B  Q  K  B  N  R

 P  P  P  P  P  P  P  P




 P  P  P  P  P  P  P  P

 R  N  B  Q  K  B  N  R

我也尝试过声明一个 char a = board[i][j]; cout

这是一个班级的作业,所以我不希望有太多帮助,我只想知道为什么我的函数返回整数而不是字符,以便我知道我的错误是什么以供将来参考,谷歌没有帮助很大。 toupper 是否存在某种范围问题?

【问题讨论】:

你试过转换toupper的返回值吗? 为什么不先google一下? 如果您只想要一个将 ASCII 大写字符转换为 ASCII 小写字符的函数,我建议使用(或编写)特定于该编码的函数。然后这样的函数可以是类型安全的,即处理chars 而不是ints,并且不需要处理语言环境(-> 更快)。 【参考方案1】:

toupper 的意图是它可以在英语以外的其他语言中工作,因此它必须支持大于 8 位 char 的输入和输出,因此应该返回可以转换为unicode 或 UTF 字符。

只是将其转换为 char 可能是错误代码的来源,这取决于您软件的用途。

查看这个问题,了解如何将它用于宽字符和 unicode。

Convert a unicode String In C++ To Upper Case

【讨论】:

C, §7.4 "标题&lt;ctype.h&gt; 声明了几个用于分类和映射字符的函数。在所有情况下参数都是int,其值应表示为unsigned char 或应等于宏 EOF 的值。如果参数具有任何其他值,则行为未定义。”该参数不是char 与Unicode 无关。它也可能与语言环境无关。见***.com/q/17452847 和***.com/q/5919735 您引用的是“C”标准,但问题是关于“C++”的,据***.com/questions/17991431/…报道,这些函数适用于std::wchar——我自己没有尝试过,如果 C 中的“未定义”行为是在 C++ 中定义的,我还没有查找 C++ 标准 这些是从 C 标准库“导入”到 C++ 中的函数。它们不是为 C++ 明确定义的,而是仅通过引用 C 标准来定义的。 wchar_t 等也不一定与 Unicode 相关。由于在典型实现中,unsigned char 可以表示 [0, 255] 中的值,因此它不能用于例如直接 UTF-8。 据我查看***.com/questions/17991431/… 的这些答案,他们都不能可靠或正常工作。 wchar_t 在大多数 *nix 系统中具有 32 位,因此 可以 用于存储 Unicode 代码点/UTF-32 代码单元。在 Windows 系统上,它有 16 位,因此不足以包含一个代码点。此外,适当的治疗,例如德语 ß 几乎是不可能的:BUSSE 可以是 bußebusse,具体取决于含义;前者不能在每个字符的基础上完成。 “由于在典型实现中,无符号字符可以表示 [0, 255] 中的值,因此不能直接用于例如 UTF-8。” 我必须限定那:它可用于存储一个 UTF-8 代码单元,但如果您将其用作参数类型(如其他代码单元以形成代码),则不能(可移植地)传递其他信息点)。【参考方案2】:

您需要使用 cout &lt;&lt; char(toupper(board[i][j])); 来解决 toupper 的愚蠢返回类型。

【讨论】:

【参考方案3】:

Toupper 函数返回等价于 c 的大写字母,如果该值存在,否则返回 c(未更改)。该值作为 int 值返回,可以隐式转换为 char。

http://www.cplusplus.com/reference/cctype/toupper/

【讨论】:

EOF 但是是一个int,可以传递给toupper,但不能转换为char(如果sizeof(int) &gt; sizeof(char))。 我没有将 char a 转换为 board[i][j],而是直接将其转换为 toupper(board[i][j]) ,这似乎跳过了将 char 转换为的步骤一个 int,我想是因为我在调用 toupper 的同时将它转换为 char,所以它可能从 char 到 int 再到 char? @dyp:当然EOF的值可以转换成char。如果char 是无符号的,则结果定义明确。如果char 是无符号的,那么只要EOF &gt;= CHAR_MIN(通常是这样),结果就可以很好地定义。但是,这种转换的结果并不是特别有用。 (通常是EOF == -1。) 顺便说一句,感谢您向我解释 toupper 的返回类型,而不是仅仅给我修复函数的代码,我想我现在更了解 toupper 定义:隐含:“暗示而非明示”implicit 没有关于执行 OP 所需行为所需的演员表。将int 作为char 发送到std::cout 所需的转换是显式,以便调用适当的重载operator &lt;&lt;。来自 cplusplus.com 的逐字文本在这种特殊情况下并没有什么帮助(有人对此感到惊讶吗?),无论是在这里还是在他们的网站上逐字复制。【参考方案4】:

文档很清楚:http://www.cplusplus.com/reference/cctype/toupper/

int toupper ( int c );

所以你只需要转换为char

cout << " " << (char) toupper(board[i][j]) << " ";

【讨论】:

旁注:“文档”只是 a 文档。这不是官方的。 对不起,我没有搜索规范。 我明白了,所以 toupper 转换为整数值,我的解决方法是 char a = toupper(board[i][j]);所以我相信数据类型从 char 到 int 到 char,但我认为您的解决方案会更好,因为它不需要创建不需要的变量

以上是关于toupper 返回整数而不是字符的主要内容,如果未能解决你的问题,请参考以下文章

为啥 putchar、toupper、tolow 等采用 int 而不是 char?

C函数tolower,与toupper

toupper字符串转换函数应用实例

f# System.Char.ToUpper

ccf 201409-3 字符串匹配(toupper,tolower)

在调用 toupper()、tolower() 等之前,我是不是需要转换为 unsigned char?