如何仅为字母测试字符串

时间:2011-09-30 22:56:26

标签: c++

我怎么能只针对像a-z这样的有效字符测试一个字符串?...

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);
}

6 个答案:

答案 0 :(得分:48)

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

std::getline(std::cin, name);

我们走了......

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

bool contains_non_alpha
    = name.find_first_not_of("abcdefghijklmnopqrstuvwxyz") != std::string::npos;
然而,这很快变得麻烦。要匹配大写字母字符,您还必须为该字符串添加26个字符!相反,您可能希望使用find_if标题中的<algorithm>和来自std::isalpha的{​​{1}}的组合:

<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(); 在范围内搜索与谓词匹配的值,在本例中为仿函数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(); 生成一个函数对象,返回其输入的逻辑反转;通过提供指向具有std::not1的函数的指针,我们可以告诉std::ptr_fun(...)生成std::not1的逻辑反转。强制转换std::isalpha用于选择(int(*)(int))的重载,它接受std::isalpha(视为字符)并返回int(视为布尔值)。

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

int

#include <cctype> bool contains_non_alpha = std::find_if(name.begin(), name.end(), [](char c) { return !std::isalpha(c); }) != name.end(); 表示接受一个字符并返回[](char c) -> bool { ... }的函数。在我们的例子中,我们可以省略bool返回类型,因为函数体只包含-> bool语句。这与前面的示例相同,只是可以更简洁地指定函数对象。

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

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

return

但当然......

这些解决方案都没有解决区域设置或字符编码的问题!对于与语言环境无关的#include <regex> bool contains_non_alpha = !std::regex_match(name, std::regex("^[A-Za-z]+$")); 版本,您需要使用C ++标题isalpha()

<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); } ,但char32_t似乎无法对其进行分类,因此我们会遇到ctype。幸运的是,我们可以完全围绕语言环境问题跳舞,因为你可能只对英文字母感兴趣。有一个方便的仅限标题的库UTF8-CPP,它将让我们以更加编码安全的方式完成我们需要做的事情。首先,我们定义使用UTF-32代码点的char版本:

isalpha()

然后我们可以使用bool isalpha(uint32_t c) { return (c >= 0x0041 && c <= 0x005A) || (c >= 0x0061 && c <= 0x007A); } 适配器将utf8::iterator从八位字节调整为UTF-32代码点:

basic_string::iterator

为了以安全为代价获得更好的性能,您可以使用#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();

utf8::unchecked::iterator

这会因某些无效输入而失败。

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

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

答案 1 :(得分:5)

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

const char* text = "hello world";
bool isAlpha = all( text1, is_alpha() );

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

希望,我帮忙。

答案 2 :(得分:4)

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";

答案 3 :(得分:2)

我建议调查ctype库: http://www.cplusplus.com/reference/std/locale/ctype/

例如,函数is(请参阅ctype.is)是一种以区域设置敏感方式检查字母属性的方法:

#include <locale>
using namespace std;
bool is_alpha(char c) {
    locale loc;
    bool upper = use_facet< ctype<char> >(loc).is( ctype<char>::alpha, quote[0]);
    return upper;
}

答案 4 :(得分:2)

  for (string::iterator it=name.begin(); it!=name.end(); ++it)
  {
    if ((*it) < 0x61 || (*it) > 0x71) 
      // string contains characters other than a-z
  }

答案 5 :(得分:0)

C++11使用std::all_of的方法:

std::all_of(std::begin(name), std::end(name),
    [](char c){ return std::isalpha(c); });
根据提供的谓词函数,

std::all_of仅在所有个元素为true时返回true。