2009-10-07 257 views
5

我想比较两种格式,我预计会有点兼容,因为它们通常都是字符串。我试图用一个字符串和std :: wstring来执行strcmp,而且我确信C++的专家知道,这将不会编译。可以比较这两种类型吗?这里有一个简单的转换吗?字符串比较。你怎么能比较字符串与std :: wstring? WRT strcmp

+0

我很困惑。你想比较两个宽字符串还是你想比较宽字符串与普通字符串? – jmucchiello

+0

我有一个char [256]来自另一个程序编组的文件流。然后我必须将它(它代表一个文件名)与作为参数传递给该函数的std :: wstring文件名进行比较。然而,我不能在逻辑上比较这些 – Mark

+0

你对这些字符的编码有任何保证吗?它是系统区域设置编码吗?一些特定的已知编码? –

回答

9

您需要将char*字符串转换 - 在ISO C说法 “多字节” - 一个wchar_t*字符串 - “宽字符” 在ISO C说法。这的确是标准的函数被调用mbstowcs(“多字节字符串为宽字符字符串”)

注意:如史蒂夫在评论中指出,这是C99的功能,因而不是ISO C++符合的,但可能被C++实现作为扩展支持。 MSVC和g ++都支持它。

因此使用:

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]); 

一旦你有两个wstring S,只是比较像往常一样。请注意,这将使用当前系统区域设置进行转换(即,在Windows上,这将是当前的“ANSI”代码页) - 通常这只是您想要的,但偶尔您需要处理特定的编码,在这种情况下上述不会,你需要使用像iconv这样的东西。

编辑

所有其他的答案似乎去直接码点转换(即在串中的每char c中的(wchar_t)c当量)。这可能不适用于所有语言环境,但它可以工作,例如,您的char都是ASCII或Latin-1,而您的wchar_t是Unicode。如果你确定这就是你真正想要的,最快的方法其实是为了避免转换完全,并使用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; 

如果你特别需要测试平等,使用std::equal有长度检查:

#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

这是C++吗?它似乎是C99,我不确定什么版本的C库被合并到C++标准中。反正无论如何 - 都应该在实践中以任何方式工作。 – Steve314

+0

是的,'mbstowcs'是C99,虽然在实践中我熟悉的C++实现(MSVC和g ++)都支持这个功能。 –

+0

似乎100%可移植的ISO C++方法是使用'std :: codecvt 'facet及其in()'方法,但它太杂乱而冗长... http://msdn.microsoft.com/en-us/library/xse90h58。aspx - 为了防止任何人想写出详细的答案。 –

2

将您的wstring转换为字符串。

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

现在您可以使用b.c_str()或任何您喜欢的方式将它与任何char *进行比较。

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

对不起以前的答案,我改变了它。 – Jacob

+1

由于丢失数据的可能性较小,所以最好采用其他方式(即'char *' - >'wstring') - 您可以将原始指针作为字符串用作迭代器。但其他方法是一样的,使用构造函数比使用'copy'的其他答案要好。注意事项是相同的:这可能无法正确运行所有语言环境。 –

2

首先你要问自己,为什么要使用std :: wstring的是使用char *(CString的)一个Unicode格式为ANSI。使用unicode是最好的做法,因为它允许您的应用程序国际化,但在大多数情况下使用混合并没有多大意义。如果你想让你的cstrings unicode使用wchar_t。如果你想让你的STL字符串被ansi使用std :: string。

现在回到你的问题。

您想要做的第一件事是将其中的一个转换为匹配其他数据类型。

std::stringstd::wstringc_str功能

这里的函数定义

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

我不记得了手如何转换的char *至* wchar_t的,反之亦然,但你以后你可以使用strcmp。如果你谷歌,你会找到一种方法。

你可以使用下面的功能转换的std :: wstring的到的std :: string然后c_str会给你char *之,你可以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

这只有在给定语言环境的多字节和宽度编码是“兼容”的情况下才会起作用 - 例如,如果多字节实际上只是ASCII或Latin-1,并且widechar是Unicode。如果多字节是例如,这将不起作用。 CP1251。 –

+0

这就是为什么我喜欢stackoverflow。如果你去一些随机的谷歌结果,你可能会得到错误的答案。 – Ryu

2

的快速和肮脏的方法是

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

我说脏,因为它会创建一个临时字符串并将your_char复制到它。然而,只要你不在紧密的环路中,它就可以正常工作。

请注意,wstring使用16位字符(即unicode - 65536个可能的字符),而char *往往是8位字符(仅限Ascii,拉丁文英文)。它们不一样,所以wstring - > char *可能会失去准确性。

-Tom

+0

这看起来比我的想法更好 - 出于某种原因,我认为std :: wstring没有正确的转换。我的方法创建了两个额外的对象 - 一个命名(可能比一个简单的wstring更重),另一个是临时的wstring实例。 – Steve314

+3

'std :: wstring'没有'const char *'中的任何构造函数。 –

+0

你可以从char *构建一个wstring,其底层类型是不同的。 wstring使用wchar_t(可能是32个字节,而不是某些系统上的16个字节)。 –