在C++中检查输入字符串是否具有前导或尾随空格?

3

我正在尝试使用C++11验证一个单行输入字符串,以查看它是否包含任何前导/尾随空格。我的代码现在看起来像这样:

bool is_valid(const std::string& s) {
    auto start = s.begin();
    auto end = s.end();
    if (std::isspace(*start) || std::isspace(*end)) {
        return false;
    } 
    return true;
}

int main() {
    std::string name{};
    std::getline(std::cin, name);
    if (!is_valid(name)) {
        std::cout << "Invalid!";
    }
    return 0;
}

但是现在程序只能检测前导空格。例如,对于 John它会打印 Invalid! 但对于Mary 它会将其分类为有效输入,这是不正确的。有谁知道我的程序出了什么问题吗?


3
使用 back() 来检查最后一个字符,不再使用 end() 迭代器。 - PaulMcKenzie
2
返回 s.empty() || (!std::isspace(s.front()) && !std::isspace(s.back())); - Jarod42
5个回答

6

在测试空字符串后,可以进行对 std::string::front()std::string::back() 的简单测试。

bool is_valid(const std::string& s) 
{
   return s.empty() || 
    (!std::isspace(static_cast<unsigned char>(s.front())) && 
     !std::isspace(static_cast<unsigned char>(s.back())));
}

您介意再解释一下为什么选择在语句中使用 static_cast<unsigned char> 吗?简单的 std::isspace(s.front()) 不足以吗? - demid
2
请查看此链接:https://en.cppreference.com/w/cpp/string/byte/isspace,并阅读其中的“Notes”部分。 - PaulMcKenzie
我想知道为什么C++不提供安全函数... - Jarod42
不确定——这可能与传统的 C 将字符视为 int 有关,而 C++ 采用了 C 的做法。很可能有一个很好的理由,因为表面上看,C++ 可以提供安全的函数。 - PaulMcKenzie

4

尾迭代器并不指向容器中的某个元素,而是指向最后一个元素之后的位置。您不能对尾迭代器进行解引用操作。对于 std::string ,您可以使用它的operator[]

char last_char = s[s.size()-1];

将起始迭代器向前移动:

auto it = s.begin() + s.size()-1;
char last_char = *it; 

或者减少结尾迭代器:

auto it = s.end() -1;
char last_char = *it;

其他替代方案包括back()或使用反向迭代器rbegin()

请注意,它们都需要s.size()!= 0。对于空字符串s.begin() == s.end()。您应该在函数中首先检查这一点,并为该情况返回true


3

s.end() 和 C++ 中的其它容器一样,都是表示字符串结束位置的迭代器。所以当访问它时会导致未定义行为。你需要使用 std::prev(s.end()) 来代替它(但仅在字符串包含至少1个字符时才有效,因此需要首先检查字符串长度)。


2

2
是的,.end()是指向超出末尾的元素。那么为什么不使用.back()呢?
bool is_valid(std::string const& str) {
    return str.empty() || !(std::isspace(str.front()) || std::isspace(str.back()));
}

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