İlk, std::cin >> name
olacak kullanılarak Kullanıcı John Smith
girerse başarısız olur, çünkü >>
, boşluk karakterlerini böler. Sen adını almak için std::getline()
kullanmalısınız: bir dize yalnızca alfabetik karakterler içerip içermediğini kontrol yolları vardır
İşte
std::getline(std::cin, name);
başlıyoruz ...
. Ancak hızla hantal hale
bool contains_non_alpha
= name.find_first_not_of("abcdefghijklmnopqrstuvwxyz") != std::string::npos;
,: En basit t
değil s
ilk karakterin dizinini döndüren muhtemelen s.find_first_not_of(t)
olduğunu. Büyük harfli alfabetik karakterlerle de eşleştirmek için, bu dizeye 26 karakter daha eklemelisiniz! Bunun yerine, <cctype>
den <algorithm>
başlık ve std::isalpha
den find_if
bir arada kullanmak isteyebilirsiniz:
#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
aramalar bu durumda, bir yüklemi eşleşen bir değeri için aralık onun argüman olmadığını döndüren bir funktoru non_alpha
alfabetik olmayan bir karakterdir. find_if(name.begin(), name.end(), ...)
, name.end()
değerini döndürürse, eşleşme bulunamadı.
Ama dahası var!
Eğer
<functional>
başlıktan adaptörler kullanarak, tek astar olarak bunun için:
#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
girişinde mantıki ters döndüren bir işlev nesnesini oluşturur; std::ptr_fun(...)
ile bir işleve bir işaretçi sağlayarak,mantıksal tersini üretmek için std::not1
bildirebiliriz. (int(*)(int))
dökümü, int
(karakter olarak kabul edilir) alan ve int
(bir Boole olarak ele alınır) alan std::isalpha
'un aşırı yüklenmesini seçmek için vardır. Eğer bir C++ 11 derleyicisi kullanabilirsiniz eğer
Veya, bir lambda kullanarak bir çok bu temizler:
#include <cctype>
bool contains_non_alpha
= std::find_if(name.begin(), name.end(),
[](char c) { return !std::isalpha(c); }) != name.end();
[](char c) -> bool { ... }
bir karakteri kabul eder ve bir bool
döndüren bir işlev gösterir. Bizim durumumuzda fonksiyon gövdesi sadece bir return
ifadesinden oluşması nedeniyle -> bool
dönüş türünü atlayabiliriz. Bu, önceki örneklerle aynı şekilde çalışır, ancak işlev nesnesi çok daha kısa bir şekilde belirtilebilir.
Ve (neredeyse) son olarak ... C++ 11 de maçı gerçekleştirmek için normal bir ifade kullanabilirsiniz yılında
: Bu çözümlerin
#include <regex>
bool contains_non_alpha
= !std::regex_match(name, std::regex("^[A-Za-z]+$"));
Ama tabii ...
Yok yerel ayar veya karakter kodlaması sorununu giderir! isalpha()
olarak yerel bağımsız sürümünde, C++ başlık <locale>
kullanmanız gerekir:
#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);
}
İdeal biz char32_t
kullanırsınız, ancak sınıflandırmak mümkün ctype
görünmüyor, yani biz de char
ile sıkışmış. Bizim için şanslıyız, yerel olarak tamamen konuyla ilgilenebiliriz çünkü muhtemelen sadece İngilizce harflerle ilgileniyorsunuz. UTF8-CPP adında kullanışlı bir salt okunur kütüphane daha fazla şifreleme güvenli bir şekilde yapmamız gerekeni yapalım.
bool isalpha(uint32_t c) {
return (c >= 0x0041 && c <= 0x005A)
|| (c >= 0x0061 && c <= 0x007A);
}
Sonra UTF-32 kod noktalarını içine sekizliyi basic_string::iterator
adapte utf8::iterator
adaptörü kullanabilirsiniz::
#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();
için Önce UTF-32 kod noktalarını kullanan isalpha()
bizim sürümü tanımlamak hafifçe güvenliği pahasına daha iyi performans, sen utf8::unchecked::iterator
kullanabilirsiniz:
#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();
Bu, bazı geçersiz Inpu üzerinde başarısız olur t.
UTF8-CPP'yi bu şekilde kullanarak, ana makine kodlamanın UTF-8 veya ASCII gibi uyumlu bir kodlama olduğunu varsayar. Teoride bu yine de kusurlu bir çözümdür, ancak pratikte platformların büyük çoğunluğu üzerinde çalışacaktır.
Umarız bu cevap nihayet tamamlandı!
Bu ödev ise, bu şekilde işaretlenmelidir. –
Sorunuz nedir? Kodunuz yanlış mı yoksa ondan eksik bir şey mi? Hangi durumda? –
' * *. btw ayrıca bir dvorak düzeni ile deneyin. –