2011-09-30 9 views
14

cómo podría probar una cadena contra únicos caracteres válidos como letras az ...cómo probar una cadena de letras solamente

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

Si esto es tarea ... debe marcarse como tal. –

+0

¿Cuál es tu pregunta? ¿Su código está equivocado o le falta algo? En ese caso, ¿qué? –

+3

'* it'. Por cierto, inténtelo con un diseño dvorak. –

Respuesta

3

STL manera:?

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

¿Qué tal si quisiera incluir un espacio como parte del parámetro de prueba? ¿como lo harias? – miatech

+0

reemplaza 'if (stringIsCorrect &&! ((Ch <= 'z' && ch> = 'a') || (ch <= 'Z' && ch> = 'A')))' con 'if (stringIsCorrect && ! ((ch <= 'z' && ch> = 'a') || (ch <= 'Z' && ch> = 'A') || (ch == ''))) ' – GreenScape

+1

Tenga en cuenta que la codificación como [EBCDIC] (https://en.wikipedia.org/wiki/EBCDIC) tiene caracteres entre '' a'' y ''z'' que no son letras. – Jarod42

43

En primer lugar, el uso de std::cin >> name se fallar si el usuario ingresa John Smith porque >> divide la entrada en caracteres de espacios en blanco. Debe utilizar std::getline() para obtener el nombre:

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

Aquí vamos ...

Hay un número de maneras de comprobar que una cadena contiene sólo caracteres alfabéticos. La más sencilla es probablemente s.find_first_not_of(t), que devuelve el índice del primer carácter en s que no está en t:

bool contains_non_alpha 
    = name.find_first_not_of("abcdefghijklmnopqrstuvwxyz") != std::string::npos; 

que rápidamente se vuelve muy complicada, sin embargo. Para que coincida con los caracteres alfabéticos en mayúsculas, debe agregar 26 caracteres más a esa cadena. En su lugar, es posible que desee utilizar una combinación de find_if de la cabecera <algorithm> y std::isalpha de <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 búsquedas al alcance de un valor que coincide con un predicado, en este caso un funtor non_alpha que devuelve si su argumento es un personaje no alfabético Si find_if(name.begin(), name.end(), ...) devuelve name.end(), no se encontró ninguna coincidencia.

¡Pero aún hay más!

Para hacer esto como una sola línea, puede utilizar los adaptadores del <functional> cabecera:

#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(); 

El std::not1 produce un objeto de función que devuelve la inversa lógica de su entrada; suministrando un puntero a una función con std::ptr_fun(...), podemos decir std::not1 para producir la inversa lógica de std::isalpha. El molde (int(*)(int)) está allí para seleccionar la sobrecarga de std::isalpha que toma un int (tratado como un carácter) y devuelve un int (tratado como un booleano).

O, si se puede utilizar un compilador de C++ 11, utilizando una lambda limpia esto mucho:

#include <cctype> 

bool contains_non_alpha 
    = std::find_if(name.begin(), name.end(), 
        [](char c) { return !std::isalpha(c); }) != name.end(); 

[](char c) -> bool { ... } denota una función que acepta un carácter y devuelve un bool. En nuestro caso, podemos omitir el tipo de devolución -> bool porque el cuerpo de la función consiste solamente en una declaración return. Esto funciona igual que en los ejemplos anteriores, excepto que el objeto de función se puede especificar mucho más sucintamente.

y (casi) por último ...

En C++ 11 también se puede usar una expresión regular para llevar a cabo el partido:

#include <regex> 

bool contains_non_alpha 
    = !std::regex_match(name, std::regex("^[A-Za-z]+$")); 

Pero, por supuesto ...

Ninguna de estas soluciones ¡aborda el problema de la codificación de locale o de caracteres! Para una versión independiente de la Localidad de isalpha(), que había necesidad de utilizar el encabezado de 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); 
} 

Lo ideal sería utilizar char32_t, pero ctype no parece ser capaz de clasificar, por lo que estamos atascado con char. Por suerte para nosotros podemos bailar completamente sobre el tema de la configuración regional, porque probablemente solo le interesen las letras en inglés. Hay una útil biblioteca de solo encabezado llamada UTF8-CPP que nos permitirá hacer lo que necesitamos hacer de una forma más segura para la codificación. Primero definimos nuestra versión de isalpha() que utiliza UTF-32 puntos de código:

bool isalpha(uint32_t c) { 
    return (c >= 0x0041 && c <= 0x005A) 
     || (c >= 0x0061 && c <= 0x007A); 
} 

entonces podemos utilizar el adaptador utf8::iterator para adaptar el basic_string::iterator de octetos en UTF-32 puntos de código:

#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(); 

Para un mejor rendimiento a costa de la seguridad, se puede utilizar 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(); 

Esto se producirá un error en alguna inpu no válido t.

El uso de UTF8-CPP de esta manera asume que la codificación del host es UTF-8, o una codificación compatible como ASCII. En teoría, esta sigue siendo una solución imperfecta, pero en la práctica funcionará en la gran mayoría de las plataformas.

¡Espero que esta respuesta finalmente se haya completado!

+0

+1 No estoy seguro de si este enfoque funcionaría en un entorno i18n con unicode no inglés en wchars, etc., pero una gran respuesta. :) –

+1

name.find_first_not_of returns position o npos (-1). Esto significa que el resultado, cuando se lanza a bool, siempre será cierto. Debes probar contra npos para que tenga sentido. – flumpb

+0

@kisplit: Gracias por atrapar eso. Solo un descuido de mi parte. –

2

que sugeriría la investigación de la biblioteca ctype: http://www.cplusplus.com/reference/std/locale/ctype/

Por ejemplo, la función is (ver ctype.is) es una manera de comprobar las propiedades de las cartas en cuenta la sensibilidad local:

#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

el recuento hexadecimal es incorrecto. por favor, actualice con los códigos HEX correctos (consulte asciitable.com). Además, también puedes usar 'A' - 'Z'. – CyprUS

+1

Evite el número mágico y use ''A'' y'' Z'', pero tenga en cuenta que esta condición es falsa para el sistema como [EBCDIC] (https://en.wikipedia.org/wiki/EBCDIC). – Jarod42

5

Si usa Boost, puede usar el predicado boost::algorithm::is_alpha para realizar esta comprobación. Aquí es cómo usarlo:

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

actualización: Como los estados de documentación, "todos() comprueba todos los elementos de un contenedor para satisfacer una condición especificada por un predicado". La llamada a all() es necesaria aquí, ya que is_alpha() en realidad opera en caracteres.

Espero, ayudé.

+0

Probablemente quiso decir 'const char * test' – curiousguy

+0

@curiousguy: gracias. dirigido. – Lev

+1

Es posible que desee mostrar lo que llama completamente calificado 'all' y' is_alpha' por sí solos no funcionará a menos que tenga el 'uso adecuado espacio de nombres 'que generalmente no se recomienda. Además, ¿qué es 'text1'? –

Cuestiones relacionadas