2009-10-07 90 views
5

私はどちらも一般的な文字列であるので、私は幾分互換性があると思われる2つのフォーマットを比較しようとしています。私は文字列とstd :: wstringを使ってstrcmpを実行しようとしましたが、C++達が知っていると確信しているので、これは単にコンパイルされません。これらの2つのタイプを比較することは可能ですか?ここに簡単な変換はありますか?文字列の比較。どのようにstd :: wstringと文字列を比較できますか? WRT strcmp

+0

私は混乱しています。 2つのワイド文字列を比較しようとしていますか、ワイド文字列を通常の文字列と比較しようとしていますか? – jmucchiello

+0

私は別のプログラムからマーシャリングされたファイルストリームからchar [256]が入ってきました。私はそれから、関数にパラメータとして渡されるstd :: wstringのファイル名と比較する必要があります(ファイル名を表します)。しかし、私は論理的にこれらを比較することはできません – Mark

+0

これらの文字のエンコーディングに関する保証はありますか?システムロケールエンコーディングですか?いくつかの特定の既知のエンコーディング? –

答えて

9

あなたのchar*文字列に変換する必要があります - ISO Cの用語では "ワイド文字" - wchar_t*文字列に - ISO Cの用語では "マルチバイトを"。それは、(「ワイド文字列にマルチバイト文字列」)mbstowcsと呼ばれているん標準機能

:スティーブはコメントで指摘したように、これはC99の機能であるため、ISO C++準拠ではありませんが、拡張としてC++の実装によってサポートされるかもしれません。 MSVCとg ++の両方でサポートされています。

したがって、使用されている:あなたは2 wstring秒を持っていたら、ちょうどいつものように比較

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

。これは変換のために現在のシステムロケールを使用することに注意してください(Windowsの場合、これは現在の "ANSI"コードページになります)。通常これはあなたの望むものですが、特定のエンコーディングを扱う必要があることもあります。上記は行いません。iconvのようなものを使用する必要があります。

EDITは

他のすべての答えは、直接コードポイント変換(文字列内のすべてのchar cため(wchar_t)cのすなわち同等)のために行くように見えます。これはすべてのロケールでは機能しない可能性がありますが、たとえばcharはすべてASCIIまたはLatin-1で、wchar_tはUnicodeです。

#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を使用します:

あなたはそれはあなたが本当に欲しいものだと確信している場合は、最速の方法は、完全な変換を避けるために、そして std::lexicographical_compareを使用することが実際にあります
#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++標準にマージされたのかよくわかりません。とにかくupvoted - 実際にいずれかの方法で動作する必要があります。 – Steve314

+0

ええ、 'mbstowcs'はC99ですが、実際には私がよく知っているC++の実装 - MSVCとg ++ - がこの機能をサポートしています。 –

+0

100%移植性のあるISO C++のアプローチは、 'std :: codecvt 'ファセットと '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

。まずあなたがANSIでのchar *(のCString)とUnicode形式でのstd :: wstringのを使用しているなぜあなたは自問する必要があり、すべての。ユニコードは、アプリケーションの国際化を可能にするため、使用することをお勧めしますが、ほとんどの場合、ミックスを使用することはあまり意味がありません。あなたのcstringをユニコードにするには、wchar_tを使用してください。あなたのSTL文字列がANSIであるようにするにはstd :: stringを使用します。

今質問に戻ってください。

最初に行うことは、そのうちの1つを他のデータ型と一致させることです。

std::stringstd::wstringがここ

機能は、私がどのようにwchar_tに、char *を変換する*およびその逆の手をオフに覚えていないが、あなたが行った後

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

を定義ですc_str機能を持っていますあなたはstrcmpを使うことができます。あなたがGoogleの場合は、方法を見つけるでしょう。

あなたははstdするのstd :: wstringのを変換するには、以下の機能を使用することができます::文字列は、その後c_strはあなたがchar型与える*あなたが迅速かつ汚い方法は

#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が好きな理由です。あなたが何かランダムなGoogleの結果に行く場合は、間違った答えを得るかもしれません。 – Ryu

2

あるのstrcmpできる

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

一時的な文字列を作成してyour_charをその中にコピーするので、ダーティと言います。しかし、タイトなループではない限り、正常に動作します。 wstringの16ビット文字(すなわちユニコード - 65536可能な文字)を使用すること

注チャー一方は* 8ビット文字(ASCII、ラテンのみ英語)になる傾向があります。それらは同じではないので、wstring - > char *は精度を失う可能性があります。

-Tom

+0

これは私の考えよりよく見えます。何らかの理由でstd :: wstringに正しい変換がないと思いました。私のアプローチでは、2つの余分なオブジェクトが作成されます。名前のついたオブジェクト(単純なwstringよりも重いもの)と、一時的なwstringインスタンスです。 – Steve314

+3

'std :: wstring'には' const char * 'のコンストラクタはありません。 –

+0

charからwstringを構築できます*基になる型は異なります。 wstringはwchar_tを使用します(いくつかのシステムでは16バイトだけでなく32バイトかもしれません)。 –