扩展ASCII字符的十进制值

时间:2014-08-23 23:47:32

标签: c++ character-encoding internationalization ascii

我写了一个函数来测试一个字符串是否只包含字母,并且效果很好:

bool is_all_letters(const char* src) {
  while (*src) {
    // A-Z, a-z
    if ((*src>64 && *src<91) || (*src>96 && *src<123)) {
      *src++;
    }
    else {
      return false;
    }
  }
  return true;
}

我的下一步是包含“扩展ASCII代码”,我认为这将非常简单,但那是我遇到麻烦的地方。例如:

std::cout << (unsigned int)'A' // 65          <-- decimal ascii value
std::cout << (unsigned int)'ñ'; // 4294967281 <-- what?

我认为'ñ'的十进制值将是164,如ASCII网站www.asciitable.com所列。

我的目标是将用户输入限制为仅ISO 8859-1(拉丁语1)中的字母。我只使用单字节字符,并希望尽可能避免使用多字节字符。

我猜我可以比较上面的unsigned int值,即:4294967281,但它对我来说感觉不对,而且,我不知道那个大整数是否是'8.0'的VC 8.0表示并且更改从编译器到编译器。

请告知

更新 - 根据Christophe提出的一些建议,我运行了以下代码:

locale loc("spanish") ;
cout<<loc.name() << endl;                   // Spanish_Spain.1252
for (int i = 0; i < 255; i++) {
  cout << i << " " << isalpha(i, loc)<< " " << (isprint(i,loc) ? (char)(i):'?') << endl; 
}

它确实返回Spanish_Spain.1252但不幸的是,循环迭代打印的内容与默认的C语言环境相同(使用VC ++ 8 / VS 2005)。

Christophe展示了不同的(期望的)结果,你可以在下面的屏幕截图中看到,但他使用了更新版本的VC ++。

4 个答案:

答案 0 :(得分:3)

您在互联网上找到的代码图表实际上是Windows OEM code page 437,它从未被认可为标准。虽然它有时被称为&#34;扩展的ASCII&#34;,但这种描述极具误导性。 (参见the Wikipedia article Extended ASCII:&#34;该术语的使用有时会受到批评,因为可能会错误地将其解释为ASCII标准已更新为包含超过128个字符或该术语明确标识单个编码,两者都是不真实的。&#34;

您可以在维基百科上找到各种版本的OEM437的历史记录。

标准的8位编码被认可为ISO-8859-1,后来成为Unicode中的前256个代码点。 (它是为世界不同地区设计的一系列8位编码之一; ISO-8859-1指定用于美洲和西欧。)这就是你会发现的在本世纪在这些地区生产的大多数计算机中,虽然最近越来越多的操作系统正在转换为完全的Unicode支持。

您在(unsigned int)'ñ'中看到的值是将ISO-8859-1代码0xF1从(签名)char(即-15)转换为{的结果{1}}。如果你把它投到unsigned int,你会看到-15。

答案 1 :(得分:3)

  

我认为'ñ'的十进制值将是164,如ASCII网站www.asciitable.com所列。

Asciitable.com似乎提供旧IBM437 DOS字符集的代码(仍然在Windows命令提示符中使用),其中ñ确实是164.但这只是数百个的“扩展ASCII”变体。

你得到的值4294967281 = 0xFFFFFFF1是(带符号)char值0xF1的符号扩展,这是ISO-8859-1ñ的编码方式以及{{}}等关闭变体3}}

答案 2 :(得分:2)

首先,您正在尝试重新发明std::isalpha。但是你需要通过ISO-8859-1语言环境IIRC,默认只检查ASCII。

您看到的行为是因为char已签名(因为您没有使用/J进行编译,当您使用的不仅仅是ASCII时这是明智之举 - VC ++默认使用signed char )。

答案 3 :(得分:0)

这里已有很多信息。但是,我想提出一些想法来解决你的初始问题,即扩展字符集的分类。

为此,我建议使用<locale>(国家/地区特定主题),尤其是isalpha(),isspace(),isprint(),...的新区域设置感知形式。

这里有一小段代码可以帮助您找出字符可能是您当地字母表中的字母:

std::locale::global(std::locale(""));               // sets the environment default locale currently in place 
std::cout << std::locale().name() << std::endl;     // display name of current locale 

std::locale loc ;                                   // use a copy of the active global locale (you could use another)
for (int i = 0; i < 255; i++) {
    cout << i << " " << isalpha(i, loc)<< " " << (isprint(i,loc) ? (char)(i):'?') << endl; 
}

这将打印出从0到255的ascii代码,如果是根据本地设置的字母,则显示指示符,如果是可打印的,则打印字符本身。

例如,在我的电脑上,我得到:
screenshot because of char encoding differences 并且所有重音字符,以及ñ和希腊字母都被视为alpha,而£和数学符号被视为非alpha可打印。