字符串类的接口(interface)通常具有名为 IsEmpty
( VCL ) 或 empty
( STL ) 的方法。这是绝对合理的,因为它是一种特殊情况,但是使用这些方法的代码通常不得不否定这个谓词,这会导致“视觉上的(甚至心理上的)开销” (感叹号不是很明显,尤其是在左括号之后)。参见例如这个(简化的)代码:
/// format an optional time specification for output
std::string fmtTime(const std::string& start, const std::string& end)
{
std::string time;
if (!start.empty() || !end.empty()) {
if (!start.empty() && !end.empty()) {
time = "from "+start+" to "+end;
} else {
if (end.empty()) {
time = "since "+start;
} else {
time = "until "+end;
}
}
}
return time;
}
它有四个否定,因为空的情况是要跳过的。我经常观察到这种否定,在设计界面时也是如此,这不是大问题,但很烦人。我只希望支持编写易于理解和易于阅读的代码。我希望你能明白我的意思。
也许我只是对盲目感到震惊:您将如何解决上述问题?
编辑: 看了一些评论,我觉得应该说原代码使用了VCL的System::AnsiString
类。这个类提供了一个IsEmpty
方法,可读性很强:
if (text.IsEmpty()) { /* ... */ } // read: if text is empty ...
如果没有否定:
if (!text.IsEmpty()) { /* ... */} // read: if not text is empty ...
...而不是 如果文本不为空。我认为文字 is
最好留给读者的幻想,让否定也能正常工作。好吧,也许不是一个普遍的问题......
最佳答案
在大多数情况下,您可以颠倒 if
和 else
的顺序来清理代码:
const std::string fmtTime(const std::string& start, const std::string& end)
{
std::string time;
if (start.empty() && end.empty()) {
return time;
}
if (start.empty() || end.empty()) {
if (end.empty()) {
time = "since "+start;
} else {
time = "until "+end;
}
} else {
time = "from "+start+" to "+end;
}
return time;
}
或者在一些更多的重构之后甚至更干净:
std::string fmtTime(const std::string& start, const std::string& end)
{
if (start.empty() && end.empty()) {
return std::string();
}
if (start.empty()) {
return "until "+end;
}
if (end.empty()) {
return "since "+start;
}
return "from "+start+" to "+end;
}
为了最终的紧凑性(虽然我更喜欢以前的版本,因为它的可读性):
std::string fmtTime(const std::string& start, const std::string& end)
{
return start.empty() && end.empty() ? std::string()
: start.empty() ? "until "+end
: end.empty() ? "since "+start
: "from "+start+" to "+end;
}
另一种可能性是创建一个辅助函数:
inline bool non_empty(const std::string &str) {
return !str.empty();
}
if (non_empty(start) || non_empty(end)) {
...
}
关于c++ - "empty"有简洁的反义词吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21882655/