我怎么能只对字母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.从理论上讲,这仍然是一个不完美的解决方案,但在实践中它将适用于绝大多数平台.
我希望这个答案终于完成了!
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)
如果使用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()实际上是对字符进行操作.
希望,我帮了.
| 归档时间: |
|
| 查看次数: |
65035 次 |
| 最近记录: |