如何仅为字母测试字符串

mia*_*ech 16 c++

我怎么能只对字母az这样的有效字符测试一个字符串?...

string name;

cout << "Enter your name"
cin >> name;

string letters = "qwertyuiopasdfghjklzxcvbnm";

string::iterator it;

for(it = name.begin(); it = name.end(); it++)
{
  size_t found = letters.find(it);
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*rdy 49

首先,std::cin >> name如果用户输入,则使用将失败,John Smith因为>>在空格字符上拆分输入.您应该使用std::getline()获取名称:

std::getline(std::cin, name);
Run Code Online (Sandbox Code Playgroud)

开始了…

有许多方法可以检查字符串是否只包含字母字符.最简单的可能是s.find_first_not_of(t),它返回的第一个字符的索引s不在t:

bool contains_non_alpha
    = name.find_first_not_of("abcdefghijklmnopqrstuvwxyz") != std::string::npos;
Run Code Online (Sandbox Code Playgroud)

然而,这很快变得麻烦.要匹配大写字母字符,您还需要为该字符串添加26个字符!相反,你可能需要使用的组合find_if<algorithm>标题和std::isalpha来自<cctype>:

#include <algorithm>
#include <cctype>

struct non_alpha {
    bool operator()(char c) {
        return !std::isalpha(c);
    }
};

bool contains_non_alpha
    = std::find_if(name.begin(), name.end(), non_alpha()) != name.end();
Run Code Online (Sandbox Code Playgroud)

find_if在一个范围内搜索与谓词匹配的值,在这种情况下是一个函数non_alpha,它返回其参数是否为非字母字符.如果find_if(name.begin(), name.end(), ...)返回name.end(),则找不到匹配项.

但还有更多!

要以单行方式执行此操作,您可以使用<functional>标题中的适配器:

#include <algorithm>
#include <cctype>
#include <functional>

bool contains_non_alpha
    = std::find_if(name.begin(), name.end(),
                   std::not1(std::ptr_fun((int(*)(int))std::isalpha))) != name.end();
Run Code Online (Sandbox Code Playgroud)

std::not1产生一个函数对象返回其输入的逻辑逆; 通过提供一个指向函数的指针std::ptr_fun(...),我们可以告诉std::not1它产生逻辑逆std::isalpha.铸造(int(*)(int))是有选择的过载std::isalpha它接受一个int(作为一个字符处理的),并返回一个int(作为布尔处理的).

或者,如果你可以使用C++ 11编译器,使用lambda可以清除它:

#include <cctype>

bool contains_non_alpha
    = std::find_if(name.begin(), name.end(),
                   [](char c) { return !std::isalpha(c); }) != name.end();
Run Code Online (Sandbox Code Playgroud)

[](char c) -> bool { ... }表示接受一个字符并返回一个字符的函数bool.在我们的例子中,我们可以省略-> bool返回类型,因为函数体只包含一个return语句.这与前面的示例相同,只是可以更简洁地指定函数对象.

而且(差不多)最后......

在C++ 11中,您还可以使用正则表达式来执行匹配:

#include <regex>

bool contains_non_alpha
    = !std::regex_match(name, std::regex("^[A-Za-z]+$"));
Run Code Online (Sandbox Code Playgroud)

但是当然…

这些解决方案都没有解决区域设置或字符编码的问题!对于与语言环境无关的版本isalpha(),您需要使用C++标头<locale>:

#include <locale>

bool isalpha(char c) {
    std::locale locale; // Default locale.
    return std::use_facet<std::ctype<char> >(locale).is(std::ctype<char>::alpha, c);
}
Run Code Online (Sandbox Code Playgroud)

理想情况下我们会使用char32_t,但ctype似乎无法对其进行分类,因此我们坚持使用char.幸运的是,我们可以完全围绕语言环境问题跳舞,因为你可能只对英文字母感兴趣.有一个方便的仅限头文件库,名为UTF8-CPP,它将让我们以更加编码安全的方式完成我们需要做的事情.首先,我们定义我们的版本isalpha()使用UTF-32代码点:

bool isalpha(uint32_t c) {
    return (c >= 0x0041 && c <= 0x005A)
        || (c >= 0x0061 && c <= 0x007A);
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以使用utf8::iterator适配器来调整basic_string::iterator八位字节到UTF-32代码点:

#include <utf8.h>

bool contains_non_alpha
    = std::find_if(utf8::iterator(name.begin(), name.begin(), name.end()),
                   utf8::iterator(name.end(), name.begin(), name.end()),
                   [](uint32_t c) { return !isalpha(c); }) != name.end();
Run Code Online (Sandbox Code Playgroud)

为了安全起见,性能稍好一些,您可以使用utf8::unchecked::iterator:

#include <utf8.h>

bool contains_non_alpha
    = std::find_if(utf8::unchecked::iterator(name.begin()),
                   utf8::unchecked::iterator(name.end()),
                   [](uint32_t c) { return !isalpha(c); }) != name.end();
Run Code Online (Sandbox Code Playgroud)

这将在某些无效输入上失败.

以这种方式使用UTF8-CPP假设主机编码是UTF-8,或者是兼容的编码,例如ASCII.从理论上讲,这仍然是一个不完美的解决方案,但在实践中它将适用于绝大多数平台.

我希望这个答案终于完成了!


Gre*_*ape 6

STL方式:

struct TestFunctor
{
  bool stringIsCorrect;
  TestFunctor()
  :stringIsCorrect(true)
  {}

  void operator() (char ch)
  {
    if(stringIsCorrect && !((ch <= 'z' && ch >= 'a') || (ch <= 'Z' && ch >= 'A')))
      stringIsCorrect = false;
  }
}

TestFunctor functor;

for_each(name.begin(), name.end(), functor);

if(functor.stringIsCorrect)
  cout << "Yay";
Run Code Online (Sandbox Code Playgroud)

  • 将 `if(stringIsCorrect &amp;&amp; !((ch &lt;= 'z' &amp;&amp; ch &gt;= 'a') || (ch &lt;= 'Z' &amp;&amp; ch &gt;= 'A')))` 替换为 `if(stringIsCorrect &amp;&amp; ! ((ch &lt;= 'z' &amp;&amp; ch &gt;= 'a') || (ch &lt;= 'Z' &amp;&amp; ch &gt;= 'A') || (ch == ' ')))` (2认同)

Lev*_*Lev 5

如果使用Boost,则可以使用boost :: algorithm :: is_alpha谓词来执行此检查.以下是如何使用它:

const char* text = "hello world";
bool isAlpha = all( text1, is_alpha() );
Run Code Online (Sandbox Code Playgroud)

更新:正如文档所述,"all()检查容器的所有元素以满足谓词指定的条件".这里需要调用all(),因为is_alpha()实际上是对字符进行操作.

希望,我帮了.