我怎么能只针对像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);
}
答案 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。