如何检查字符常量是否符合ASCII标准?

3
一篇我之前this answer的评论提醒我不能假设'A''B''C'等具有连续的数字值。我曾经认为C或C++语言标准保证了这一点。

那么,我应该如何确定连续字母字符的值本身是连续的呢?或者说,我如何确定我可以在单引号中表达的字符常量是否具有数值的ASCII代码?

我想知道如何在C和C++中实现这一点。显然,C的方法也适用于C++,但如果有C++特有的功能来实现这一点,我也很感兴趣。此外,我询问最新的相关标准(C11,C++17)。


或者说,我如何确定我可以在单引号内表示的字符常量是否具有其ASCII代码的数字值?为什么你想这样做呢? - user2100815
std::isdigit是什么?为什么同时有C++和C标签?它是哪一个?如果您能澄清您想要回答的标准版本,那就更好了。 - tambre
2
我怀疑在使用非ASCII兼容编码的系统上,任何人都不会考虑使用没有专门针对该系统编写的代码。如果发现C++编译器甚至存在于这样的系统中,我会感到惊讶。 - Benjamin Lindley
6
@BenjaminLindley,非ASCII计算机也有C++编译器。 https://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.cbclx01/charset.htm 可在EBCDIC上运行。 - Martin Bonner supports Monica
6
不要过于依赖ASCII码,编写无需考虑字符集的代码。 - Pete Becker
显示剩余8条评论
2个回答

6
您可以使用预处理器来检查特定字符是否与字符集映射:

您可以使用预处理器来检查特定字符是否与字符集映射:

#include <iostream>
using namespace std;

int main() {
    #if ('A' == 65 && 'Z' - 'A' == 25)
    std::cout << "ASCII" << std::endl;
    #else
    std::cout << "Other charset" << std::endl;
    #endif
    return 0;
}

缺点是,您需要预先知道映射的值。
顺便说一下,数字字符 '0' - '9' 保证按连续顺序出现。

哎呀,这不是我能想到的最健壮的检查方式 :-( - einpoklum
1
没有任何理由不检查每个字符。如果你不想一个一个打出来,你可以很容易地自动生成这段代码。 - Benjamin Lindley
2
@BenjaminLindley:你可以检查每个字符,但在实际操作中,一个字符就足够了。 - Martin Bonner supports Monica
1
从技术上讲,ASCII是一个7位字符集。Prime小型计算机使用ASCII,但设置了第8位。因此,'A'是193。是否将Primes视为使用ASCII取决于OP(原始发布者),或者他是否在意他的代码是否能在Primes上运行。 - Martin Bonner supports Monica
2
@πάνταῥεῖ 更加健壮的检查可以是 #if ('A' == 65 && 'Z' - 'A' == 25) - Weather Vane
显示剩余5条评论

0
(2)我希望能够获得两个字母之间的字母数距离...
这个目标说明比你实际提出的问题更有意义!为什么不问这个呢?您可以在字符数组上使用strchr,而strchr不关心本地字符集是什么,这意味着您的代码不会关心本地字符集是什么...例如:
char alphabet[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
ptrdiff_t fubar = strchr(alphabet, 'y') - strchr(alphabet, 'X');
printf("'X' and 'y' have a distance of %tu and a case difference of %tu\n", fubar / 2, fubar % 2);

“如何确定连续字母字符的值是否本身连续?”
按定义,连续字母字符的值是连续的,因为它们是“连续字母字符”。我知道这不是你的意思,但你实际上的问题说明了缺乏计划和思考,而一个愚蠢的问题应该有一个愚蠢的答案。
您最好编写程序的方式是,“您不关心”它们具有的值。尽管如此,创建一个包含您关心的字符的数组,循环遍历元素并测试其一致性。例如:
int is_consecutive(char const *alphabet) {
    for (size_t x = 0; alphabet[x] && alphabet[x] + 1 == alphabet[x + 1]; x++);
    return !alphabet[x];
}

...我怎样才能确定我可以在单引号内表达的字符常量是否具有它们的 ASCII 代码作为数字值? 再次缺乏意义,又关心值...或者,构建两个翻译表 native_to_ascii 和 ascii_to_native,并从那里解决问题。我不会帮你做这个,因为这是一个愚蠢的练习,涉及使用魔术数字,这很可能对你实际目标没有必要。

你所写的是当无法假设'Z' - 'A'与实际字母表中的值不同时,必须采取的措施。但这并不是我问题的答案。 - einpoklum
使用 strchr 会为了一个简单的减法,在几乎任何生产系统上,对于拉丁字母表中的两组26个字符而言,增加了很多源代码复杂性、生成的代码和运行时工作。我认为,与52个拉丁字母以外的字符相比,它们更有可能引起问题,而非ASCII系统会这样做,而且 strchr 无法解决 Unicode 的所有不确定性。 - supercat
@Seb:虽然实现优化对strchr的调用可能是允许的,而且有些实现确实会这样做,但这绝不是一种普遍的做法。拉丁字母表的52个字符在Unicode中并没有直接的问题,但代码可能需要接受例如土耳其的大写"I"或小写"i"这样的多字节字符。 - supercat
@supercat ...在这种情况下,将其适应为使用另一种类型(如char32_t)和strchr的修订版本不是微不足道吗?这个问题是否仅仅涉及字母字符?虽然我理解你想要解决所有问题的愿望,但这并非总是可能或切实可行的... 我提供了几个选项中的一个。不喜欢它?认为自己可以做得更好?当然,请自便! - autistic
@supercat,您是否更喜欢更受欢迎的答案?如果是这样,您如何调整该代码以处理您提供的土耳其示例? - autistic
显示剩余3条评论

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