sadece

2011-09-30 13 views
14

Ben az mektupları gibi tek geçerli karakterler karşı bir dize ...sadece

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

Bu ödev ise, bu şekilde işaretlenmelidir. –

+0

Sorunuz nedir? Kodunuz yanlış mı yoksa ondan eksik bir şey mi? Hangi durumda? –

+3

' * *. btw ayrıca bir dvorak düzeni ile deneyin. –

cevap

3

STL yolu test edebilir nasıl harf için bir dize nasıl test:?

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

Test parametresinin bir parçası olarak yer mi eklemek istedim? nasıl yapardın? – miatech

+0

değiştirmek if if (stringIsCorrect &&! ((Ch <= 'z' && ch> = 'a') || (ch <= 'Z' && ch> = 'A'))) 'ile if (stringIsCorrect && ! ((ch <= 'z' && ch> = 'a') || (ch <= 'Z' && ch> = 'A') || (ch == ''))) ' – GreenScape

+1

Kodlamaya dikkat edin [EBCDIC] olarak (https://en.wikipedia.org/wiki/EBCDIC) "a" ve "z'" arasında karakterler olmayan karakterler vardır. – Jarod42

43

İ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ı!

+0

+1 Bu yaklaşımın, wchars, vb. De ingilizce unicode ile i18n bir ortamda çalışacağından emin değilim, ama büyük tepki. :) –

+1

name.find_first_not_of, return position veya npos (-1) değerini döndürür. Bu sonuç, boole dönüştürüldüğünde her zaman doğru olacaktır. Bunun mantıklı olması için npos'a karşı test etmeniz gerekir. – flumpb

+0

@kisplit: Bunu yakaladığın için teşekkürler. Sadece benim tarafımdaki bir gözetim. –

2

Ben Ctype kütüphane araştıran öneririm: Örneğin http://www.cplusplus.com/reference/std/locale/ctype/

, fonksiyonunu is (ctype.is bakınız) yerel duyarlı bir şekilde harflerin özelliklerini denetlemek için bir yoldur:

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

ile hex sayısının yanlış olduğunu değiştirebilirsiniz. lütfen doğru HEX kodları ile güncelleyin (bkz. asciitable.com). Ayrıca, 'A' - 'Z' için de yapabilirsiniz. – CyprUS

+1

Sihirli numaradan kaçınmak ve '' A'' ve ''Z' 'kullanmaktan kaçının, ancak bu durumun sistem için [EBCDIC] (https://en.wikipedia.org/wiki/EBCDIC) olarak yanlış olduğuna dikkat edin. – Jarod42

5

Boost'u kullanıyorsanız, bu denetimi gerçekleştirmek için boost::algorithm::is_alpha yüklemini kullanabilirsiniz. , Dokümantasyon devletler olarak "Tüm() bir yüklemi tarafından belirtilen bir koşulu yerine bir kabın tüm unsurları kontrol eder":

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

Güncelleme: İşte nasıl kullanılacağını olduğunu. Is_alpha() aslında karakterlerle çalıştığı için, tüm() öğesine çağrı gereklidir.

Umut, yardımcı oldum.

+0

Muhtemelen 'const char * test' – curiousguy

+0

@curiousguy: teşekkürler. hitap etti. – Lev

+1

Tam olarak adlandırdığınız şeyi göstermek isteyebilirsiniz "all" ve "is_alpha", genellikle kullanmanız gereken "use namespace" harfine sahip olmadığınız sürece çalışmayacaktır. Ayrıca, text1 nedir? –