C程序设计2.1实验的字符显示异常问题
main()
{
char ch;
ch = '\362';
printf("%c\n", ch);
printf("china\n\101\t\\\n");
printf("%c,%c,%c,%c,%c\n", '\x40', '\101', '\\', '\'', '\"');
return 0;
}
这是书上的实验2.1在win10系统下的一般结果,可以看到\362代表的大于等于号在这里变成了问号。
这个问题的原因是编码标准的区别造成的,因为\362的值是242,在ASCII中,128-255是扩展的ASCII,所以目前对它们的使用需要在437(OEM-美国)标准下才能正确显示字符。
更改的办法是:
方法一
- WIN+R输入“cmd”打开命令行窗口,右击窗口选择“属性”
- 在属性界面点击“使用旧版控制台”后重新启动命令行窗口
- 右击窗口选择“默认值”
- 在默认值界面将936(ANSI\OEM-简体中文 GBK)改为437(OEM-美国)
- 再通过编辑器运行即可正常显示
配图:
或者采用另一种方法
方法二
采用以下代码:
#include <Windows.h>
#include <stdio.h>
main()
{
char ch;
ch = '\362';
SetConsoleOutputCP(437);
printf("%c\n", ch);
printf("china\n\101\t\\\n");
printf("%c,%c,%c,%c,%c\n", '\x40', '\101', '\\', '\'', '\"');
return 0;
}
可以看到我添加了
#include <Windows.h>
与
SetConsoleOutputCP(437);
它们的作用是在本程序中规定将代码的编译标准确定为美国的437标准,这样就可以无需前面的复杂操作就可以运行。
我个人更喜欢这种方式,因为它使得即使将程序发给其他未更改默认值的计算机也不会产生异常显示。
关于本题是否与代码溢出有关的讨论
这里我依然用实验说明
void main()
{
unsigned char ch;
signed char eh;
char ah,bh;//验证无标记时的数据类型自动被定义为unsigned还是signed,若为unsigned那么ah与bh均不会发生溢出,反之溢出
ah = 128;//127是char一定成立的极限,所以128就属于极限外的部分,
bh = 129;//连续实验找出分界点,证明不是溢出
eh = '\362' ;//这里我迫使的eh数据溢出
ch = '\362';
printf("%d\t%c\n", ah, ah);//若不溢出,显示128,若溢出显示-128
printf("%d\t%c\n", bh, bh);//若不溢出,显示129,若溢出显示-127
printf("%d\t%c\n", eh,eh);//同时输出eh的值和表示的符号,按照推断应该输出-14和溢出的对应显示
//溢出显示的字符是计算机在其标准中找不到对象时的乱码之一
printf("%d\t", ch);//输出ch表示的值,如果未发生溢出应该是242
printf("%c\n", ch);//输出ch表示的符号,如果正常将按书本上出现大于等于号
/*ch = 'A';
printf("%x,%x,%c\n", y, ch, ch);*/
return 0;
}
之所以最后一个值采用分开写是因为个人做重复步骤的时候喜欢最后一步不一样来提醒自己重复结束,与结果无关。
将
char ah,bh;
改为
unsigned char ah,bh;
后的结果
这里是在win10_936标准下进行的实验一
- 可以看到发生了数据溢出
数据溢出的部分将在范围内取反,取反仍然超出的部分将与取反值相加 - 虽然数据溢出,但是符号显示并未发生影响
- 当不对char标记无符号时将会是unsigned char
然后在win10_437美国标准下进行实验二
仍然使用相同的代码,并做出相同更改进行一次对比实验
结果是
可以看出字符显示正常,证明了输入值在ASCII码范围中,即使发生溢出也不会影响字符显示