【问题标题】:isalpha(<mychar>) == true evaluates to false?isalpha(<mychar>) == true 计算结果为 false?
【发布时间】:2010-03-25 21:43:42
【问题描述】:

string temp 等于调试器中的“ZERO:\t.WORD\t1”。 (我文件的第一行)

string temp = RemoveWhiteSpace(data);
int i = 0;
if ( temp.length() > 0 && isalpha(temp[0]) )
    cout << "without true worked" << endl;
if ( temp.length() > 0 && isalpha(temp[0]) == true )
    cout << "with true worked" << endl;

这是我检查 temp 的第一个字符是否为 a-z、A-Z 的代码。第一个 if 语句将评估为 true,第二个为 false。为什么?!?!?!即使没有“temp.length() > 0 &&”,我也试过这个,它仍然评估为假。它只是讨厌“== true”。我唯一能想到的是 isalpha() 返回 != 0 和 true == 1。然后,你可以得到 isalpha() == 2 != 1。但是,我不知道 C++ 是否是这样的......很奇怪。

顺便说一句,我不需要知道“== true”在逻辑上毫无意义。我知道。

输出是

without true worked

在 Ubuntu 9.10 上使用 GNU GCC 与 CodeBlock 一起编译(如果这很重要的话)

【问题讨论】:

  • 你试过cout &lt;&lt; isalpha(temp[0]) &lt;&lt; endl;吗?
  • “我不知道 C++ 是不是……很奇怪”。查阅参考手册会给你一个想法。 cplusplus.com 说,“如果确实 c 是一个字母,则一个不同于零的值(即true)”。这就是为什么您不应该使用 cplusplus.com:true 在 C++ 中的含义与他们复制的 C 标准中的描述中的“真实”不同。 opengroup.org 说,“如果 c 是字母字符,isalpha() 函数应返回非零值”,这样更好。
  • 另外,请注意 &lt;cctype&gt;&lt;ctype.h&gt; 中的 isalpha 函数与 &lt;locale&gt; 中的函数模板 std::isalpha 之间的混淆。后者返回bool,所以如果你调用它,那么你的代码就可以工作。
  • 哦,还有一件事,isalpha(temp[0]) 是错误的。如果你坚持,你应该写isalpha((unsigned char)(temp[0])),或者一个static_cast。由于我不清楚的原因,isalpha 需要一个 int 参数,该参数必须是非负数(或 EOF),而 char 可能是编译器上的签名类型(我相信如果你在 Ubuntu 上x86)。没有多大意义,但你去吧。我想调用者在从字符串读取时进行转换比从流中读取时检查 EOF 更容易。
  • 从风格的角度解决这个问题的其他问题:stackoverflow.com/questions/1535397/…stackoverflow.com/questions/356217/… 我的看法是,与 true/false 进行比较是不好的风格,因为它会导致像你这样的陷阱遇到了。

标签: c++


【解决方案1】:

is* 函数只保证在 true 时返回非零值,不一定是 1。典型的实现是基于表的,表中每个字符值都有一个条目,一组位定义哪个位意味着什么。 is* 函数只会将正确的位掩码与表值进行 AND 运算,然后返回该值,对于恰好被赋予位位置 0 的类型,该值只会是值 1。

例如:

#define __digit 1
#define __lower 2
#define __upper 4
extern int __type_table[];

int isdigit(int c) { 
    return __type_table[c+1] & __digit;
}

int isalpha(int c) { 
    return __type_table[c+1] & (__lower | __upper);
}

int islower(int c) { 
    return __type_table[c+1] & __lower;
}

int isupper(int c) { 
    return __type_table[c+1] & __upper;
}

其中__type_table 被定义为int __type_table[UINT_MAX+1]; 之类的东西,并将被初始化为(例如)__type_table['0'+1] == __digit__type_table['A'+1] == __upper

如果您关心,“+1”部分是在表格的开头为EOF(通常定义为-1)留一个位置。

【讨论】:

  • @Buttink:既然你提到它,那看起来确实很奇怪...... :-)
  • @Buttink:喜欢 C# 是让你陷入困境的原因 - 如果不是 C#,你会很乐意在条件中使用整数,而不是将其与一个单一的“真实”值,这不是因为 C 函数不是为您设计的。喜欢 C# 很好,但是当你真的在写 C++ 时,假装你在写 C# 就不好了 ;-)
  • @steve 不,一群懒惰的 f**ks 决定让逻辑上的 bool 函数返回一个 int。如果 C 不允许将 bool 隐式转换为 int,这甚至不会发生。在汇编程序中,您至少假设没有类型。 C 是高级语言。
  • @Buttink:C 在发明这些时也没有布尔类型。设计也不是关于懒惰,而是关于效率。请记住,C 最初旨在取代手写的汇编语言,并且他们非常重视使其尽可能接近相同的效率。将每个非零值转换为 1 根本不适合。 The C Programming Language(第 1 版)的序言明确指出“C 不是一种非常高级的语言……”
  • 虽然没有那么糟糕。只需要关心范围0 .. UCHAR_MAXEOF :)
【解决方案2】:

isalpha 不返回 true,它返回非零值。这对于为 C 设计的 API 很常见。

请注意,在表达式 isalpha(ch) == true 中,子表达式 true 被提升为类型 int,值为 1。

【讨论】:

    【解决方案3】:

    好吧,文档建议它返回零或非零,不一定只是假或真。所以你最好检查一下 (isalpha(temp[0]) != 0)。

    【讨论】:

    • @mmyers: 或isalpha(temp[0])!
    • @UncleBens:嘘,你会扼杀我的优越感。
    【解决方案4】:

    不要isalpha(ch) == true,而是!!isalpha(ch) == true

    【讨论】:

    • 如果您要将布尔值与真值进行比较(从而产生另一个布尔值),您确定一次就足够了吗?也许它真的应该是(!!isalpha(ch)==true)==true,或者甚至是(((((!!isalpha(ch)==true)==true)==true)==true)==true?嘿,看,我发明了 Lisp! :-)
    • 任何带有 double 的表达式!迹象需要死。这不是意识形态,它很丑陋,而且几乎可以肯定这不是你想要做的。 -1.
    • @Jerry:我认为布尔表达式的真正鉴赏家是从(!!isalpha(ch)==(!!true==!!true)) 开始的,然后随着情绪的袭来。
    猜你喜欢
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    相关资源
    最近更新 更多