2009-10-07 14 views
5

Estoy tratando de comparar dos formatos que esperaba que fueran algo compatibles, ya que generalmente son cadenas. He intentado ejecutar strcmp con una cadena y std :: wstring, y como estoy seguro de que los gurús de C++ saben, esto simplemente no se compilará. ¿Es posible comparar estos dos tipos? ¿Hay una conversión fácil aquí?Comparaciones de cadenas. ¿Cómo se puede comparar la cadena con std :: wstring? WRT strcmp

+0

Estoy confundido. ¿Estás tratando de comparar dos cuerdas anchas o estás tratando de comparar una cuerda ancha con una cuerda normal? – jmucchiello

+0

tengo un char [256] procedente de una cadena de archivos distribuida desde otro programa. entonces tengo que comparar eso (representa un nombre de archivo) con un nombre de archivo std :: wstring que se pasa como un parámetro a la función. sin embargo, no puedo comparar lógicamente estos – Mark

+0

¿Tiene alguna garantía con respecto a la codificación de esos caracteres? ¿Es la codificación del sistema local? ¿Alguna codificación específica conocida? –

Respuesta

9

Es necesario para convertir su cadena de char* - "multibyte" en la jerga de la ISO C - a una cadena wchar_t* - "caracteres anchos" en el lenguaje C ISO. La función estándar que hace que se llama mbstowcs ("multi-byte cadena Para cadena de caracteres anchos")

NOTA: como Steve señaló en los comentarios, esto es una función C99 y por lo tanto no es ISO C++ conformes, pero puede ser soportado por implementaciones de C++ como una extensión. MSVC y g ++ lo admiten.

Se utiliza así:

const char* input = ...; 

std::size_t output_size = std::mbstowcs(NULL, input, 0); // get length 
std::vector<wchar_t> output_buffer(output_size); 

// output_size is guaranteed to be >0 because of \0 at end 
std::mbstowcs(&output_buffer[0], input, output_size); 

std::wstring output(&output_buffer[0]); 

Una vez que tenga dos wstring s, compara como de costumbre. Tenga en cuenta que esto utilizará la configuración regional actual del sistema para la conversión (es decir, en Windows esta será la página de códigos "ANSI" actual); normalmente esto es justo lo que quiere, pero ocasionalmente tendrá que tratar con una codificación específica, en cuyo caso lo anterior no funcionará, y deberá usar algo como iconv.

EDITAR

Todas las otras respuestas parecen ir de punto de código para la traducción directa (es decir, el equivalente de (wchar_t)c para cada char c en la cadena). Es posible que esto no funcione para todas las configuraciones regionales, pero funcionará si, por ejemplo, su char son todos ASCII o Latin-1, y su wchar_t son Unicode. Si está seguro de que es lo que realmente quiere, la forma más rápida es en realidad para evitar la conversión por completo, y utilizar std::lexicographical_compare:

#include <algorithm> 

const char* s = ...; 
std::wstring ws = ...; 

const char* s_end = s + strlen(s); 

bool is_ws_less_than_s = std::lexicographical_compare(ws.begin, ws.end(), 
                 s, s_end()); 
bool is_s_less_than_ws = std::lexicographical_compare(s, s_end(), 
                 ws.begin(), ws.end()); 
bool is_s_equal_to_ws = !is_ws_less_than_s && !is_s_less_than_ws; 

Si necesita específicamente para comprobar la igualdad, utilice std::equal con un cheque longitud:

#include <algorithm> 

const char* s = ...; 
std::wstring ws = ...; 

std::size_t s_len = strlen(s); 
bool are_equal = 
    ws.length() == s_len && 
    std::equal(ws.begin(), ws.end(), s); 
+0

¿Es esto C++? Parece ser C99, y no estoy seguro de qué versiones de la biblioteca C se fusionaron en el estándar C++. Upvoted de todos modos, debería funcionar en la práctica de cualquier manera. – Steve314

+0

Sí, 'mbstowcs' es C99, aunque en la práctica las dos implementaciones de C++ con las que estoy familiarizado, MSVC y g ++, admiten esta función. –

+0

Parece que el enfoque 100% portable de ISO C++ sería usar la faceta 'std :: codecvt ' y su método 'in()', pero es tan complicado y detallado ... http://msdn.microsoft.com/en-us/library/xse90h58.aspx: documentación en caso de que alguien quiera intentar escribir una respuesta detallada para eso. –

2

Convierta su wstring en una cadena.

wstring a = L"foobar"; 
string b(a.begin(),a.end()); 

Ahora puedes compararlo con cualquier char * usando b.c_str() o lo que quieras.

char c[] = "foobar"; 
cout<<strcmp(b.c_str(),c)<<endl; 
+0

Disculpa por la respuesta anterior, la cambié. – Jacob

+1

Es probable que sea mejor hacerlo de otra manera (es decir, 'char *' -> 'wstring'), ya que hay menos posibilidades de perder datos; puede usar punteros sin procesar en una cadena como iteradores. Pero, de lo contrario, el método es el mismo, y usar constructores es mejor que otra respuesta que use 'copy'. La advertencia es la misma: es posible que esto no funcione correctamente para todas las configuraciones regionales. –

2

En primer lugar usted tiene que preguntarse por qué está utilizando std :: wstring que es un formato Unicode con char * (cstring) que es ANSI. Es una buena práctica usar Unicode porque permite que su aplicación se internacionalice, pero usar una mezcla no tiene mucho sentido en la mayoría de los casos. Si desea que sus cadenas de caracteres sean unicode, use wchar_t. Si desea que sus cadenas STL sean ansi use std :: string.

Ahora volvamos a su pregunta.

Lo primero que debe hacer es convertir uno de ellos para que coincida con el otro tipo de datos.

std::string un std::wstring tienen la función c_str

aquí la función de definiciones

const char* std::string::c_str() const 
const wchar_t* std::wstring::c_str() const 

No recuerdo fuera de la mano cómo convertir char * a * wchar_t y viceversa, pero después de hacer que puedes usar strcmp. Si buscas en Google encontrarás la manera.

Usted podría utilizar las funciones de abajo para convertir std :: wstring a std :: string entonces c_str le dará char * que se puede STRCMP

#include <string> 
#include <algorithm> 

// Prototype for conversion functions 
std::wstring StringToWString(const std::string& s); 
std::string WStringToString(const std::wstring& s); 

std::wstring StringToWString(const std::string& s) 
{ 
std::wstring temp(s.length(),L' '); 
std::copy(s.begin(), s.end(), temp.begin()); 
return temp; 
} 


std::string WStringToString(const std::wstring& s) 
{ 
std::string temp(s.length(), ' '); 
std::copy(s.begin(), s.end(), temp.begin()); 
return temp; 
} 
+0

Esto solo funcionará si las codificaciones multibyte y widechar para una configuración regional determinada son "compatibles", p. si multibyte es realmente solo ASCII o Latin-1, y widechar es Unicode. Esto no funcionará si multibyte es, por ej. CP1251. –

+0

Es por eso que me gusta stackoverflow. Si vas a un resultado aleatorio de google, es posible que obtengas una respuesta incorrecta. – Ryu

2

La forma más rápida y sucia es

if(std::wstring(your_char_ptr_string) == your_wstring) 

Digo sucio porque creará una cadena temporal y copiará tu_char en ella. Sin embargo, funcionará bien siempre y cuando no estés en un circuito cerrado.

Tenga en cuenta que wstring usa caracteres de 16 bits (es decir, unicode - 65536 caracteres posibles) mientras que char * tiende a ser de 8 caracteres (Ascii, solo inglés latino). No son lo mismo, por lo que wstring -> char * puede perder precisión.

-Tom

+0

Esto se ve mejor que mi idea, por alguna razón, pensé que std :: wstring no tendría las conversiones correctas. Mi enfoque crea dos objetos adicionales, uno llamado (y probablemente más pesado que un wstring simple), el otro una instancia temporal de wstring. – Steve314

+3

'std :: wstring' no tiene ningún constructor de' const char * '. –

+0

Puede construir un wstring a partir de char * los tipos subyacentes son diferentes. wstring usa wchar_t (que puede tener 32 bytes y no solo 16 en algunos sistemas). –

Cuestiones relacionadas