2009-10-07 63 views
5

Tôi đang cố gắng so sánh hai định dạng mà tôi mong đợi sẽ có phần tương thích, vì cả hai đều là chuỗi chung. Tôi đã cố gắng để thực hiện strcmp với một chuỗi và std :: wstring, và như tôi chắc chắn C++ rất kinh nghiệm biết, điều này sẽ chỉ đơn giản là không biên dịch. Có thể so sánh hai loại này không? Ở đây có chuyển đổi dễ dàng không?So sánh chuỗi. Làm thế nào bạn có thể so sánh chuỗi với std :: wstring? WRT strcmp

+0

Tôi đang bối rối. Bạn đang cố gắng để so sánh hai chuỗi rộng hoặc bạn đang cố gắng để so sánh một chuỗi rộng đến một chuỗi bình thường? – jmucchiello

+0

Tôi có một char [256] đến từ một bộ phim được sắp xếp từ một chương trình khác. sau đó tôi phải so sánh điều đó (nó đại diện cho một tên tệp) với một tên tệp std :: wstring được chuyển thành tham số cho hàm. tuy nhiên, tôi không thể so sánh một cách hợp lý những số này – Mark

+0

Bạn có bất kỳ sự bảo đảm nào về việc mã hóa các ký tự đó không? Có mã hóa ngôn ngữ hệ thống không? Một số mã hóa đã biết cụ thể? –

Trả lời

9

Bạn cần phải chuyển đổi char* chuỗi của bạn - "multibyte" trong ISO C cách nói - một chuỗi wchar_t* - "nhân vật rộng" trong ISO C cách nói. Các chức năng tiêu chuẩn nào đó được gọi là mbstowcs ("Multi-Byte Chuỗi Để Wide Character String")

LƯU Ý: như Steve đã chỉ ra trong các ý kiến, đây là một chức năng C99 và do đó không phải là tiêu chuẩn ISO C++ tuân thủ QTI, nhưng có thể được hỗ trợ bởi triển khai C++ dưới dạng phần mở rộng. MSVC và g ++ đều hỗ trợ nó.

Nó được sử dụng như sau:

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

Khi bạn có hai wstring s, chỉ cần so sánh như bình thường. Lưu ý rằng điều này sẽ sử dụng ngôn ngữ hệ thống hiện tại để chuyển đổi (tức là trên Windows, đây sẽ là mã "ANSI" hiện tại) - thông thường đây chỉ là những gì bạn muốn, nhưng đôi khi bạn sẽ cần phải xử lý một mã hóa cụ thể. ở trên sẽ không làm, và bạn sẽ cần phải sử dụng một cái gì đó như iconv.

EDIT

Tất cả các câu trả lời khác dường như đi cho dịch điểm mã trực tiếp (ví dụ: tương đương với (wchar_t)c cho mỗi char c trong chuỗi). Điều này có thể không hoạt động đối với tất cả các ngôn ngữ, nhưng nó sẽ hoạt động nếu ví dụ: char của bạn là tất cả ASCII hoặc Latin-1 và wchar_t là Unicode. Nếu bạn chắc chắn đó là những gì bạn thực sự muốn, cách nhanh nhất là thực sự để tránh chuyển đổi hoàn toàn, và sử dụng 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; 

Nếu bạn đặc biệt cần phải kiểm tra bình đẳng, sử dụng std::equal với một tấm séc dài:

#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

Đây có phải là C++ không? Nó có vẻ là C99, và tôi không chắc chắn những phiên bản của thư viện C đã được sáp nhập vào tiêu chuẩn C++. Upvoted anyway - nên làm việc trong thực tế một trong hai cách. – Steve314

+0

Vâng, 'mbstowcs' là C99, mặc dù trong thực tế cả hai C++ triển khai tôi quen thuộc với - MSVC và g + + - hỗ trợ chức năng này. –

+0

Dường như cách tiếp cận ISO C++ di động 100% sẽ sử dụng phương thức 'std :: codecvt ' và phương thức 'in()' của nó, nhưng nó quá lộn xộn và dài dòng ... http://msdn.microsoft.com/en-us/library/xse90h58.aspx - tài liệu cho nó trong trường hợp bất cứ ai muốn cố gắng để viết lên một câu trả lời chi tiết cho điều đó. –

2

Chuyển đổi chuỗi ký tự thành chuỗi.

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

Bây giờ bạn có thể so sánh nó với bất kỳ char * nào bằng b.c_str() hoặc bất kỳ thứ gì bạn thích.

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

Xin lỗi về câu trả lời trước, tôi đã thay đổi nó. – Jacob

+1

Có thể tốt hơn để đi theo cách khác (nghĩa là 'char *' -> 'wstring'), vì có ít cơ hội bị mất dữ liệu hơn - bạn có thể sử dụng con trỏ thô thành chuỗi làm trình lặp. Nhưng nếu không phương thức là như nhau, và sử dụng các hàm tạo là tốt hơn câu trả lời khác sử dụng 'copy'. Caveat là như nhau: điều này có thể không hoạt động chính xác cho tất cả các ngôn ngữ. –

2

Trước hết bạn phải tự hỏi mình tại sao bạn đang sử dụng std :: wstring mà là một định dạng unicode với char * (cstring) là ansi. Cách tốt nhất là sử dụng unicode vì nó cho phép ứng dụng của bạn được quốc tế hóa, nhưng việc sử dụng kết hợp không có ý nghĩa gì trong hầu hết các trường hợp. Nếu bạn muốn cstrings của bạn được unicode sử dụng wchar_t. Nếu bạn muốn chuỗi STL của bạn được ansi sử dụng std :: string.

Bây giờ, hãy quay lại câu hỏi của bạn.

Điều đầu tiên bạn muốn làm là chuyển đổi một trong số chúng để khớp với kiểu dữ liệu khác.

std::string một std::wstringc_str chức năng

đây là những chức năng các định nghĩa

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

Tôi không nhớ ra tay như thế nào để chuyển đổi char * để wchar_t * và ngược lại, nhưng sau khi bạn làm bạn có thể sử dụng strcmp. Nếu bạn google, bạn sẽ tìm thấy một cách.

Bạn có thể sử dụng các chức năng dưới đây để chuyển đổi std :: wstring để std :: string sau đó c_str sẽ cung cấp cho bạn char * mà bạn có thể 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

Điều này sẽ chỉ hoạt động nếu mã hóa nhiều byte và widechar cho một ngôn ngữ cụ thể là "tương thích" - ví dụ: nếu multibyte thực sự chỉ là ASCII hoặc Latin-1, và widechar là Unicode. Điều này sẽ không hoạt động nếu có nhiều byte. CP1251. –

+0

Đây là lý do tại sao tôi thích stackoverflow. Nếu bạn đi đến một số kết quả google ngẫu nhiên, bạn có thể nhận được câu trả lời sai. – Ryu

2

Cách nhanh chóng và dơ bẩn là

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

Tôi nói bẩn vì nó sẽ tạo ra một chuỗi tạm thời và sao chép your_char vào nó. Tuy nhiên, nó sẽ làm việc tốt miễn là bạn không ở trong một vòng lặp chặt chẽ.

Lưu ý rằng wstring sử dụng ký tự 16 bit (tức là unicode - 65536 ký tự có thể) trong khi char * có xu hướng là 8 ký tự bit (Ascii, chỉ tiếng Anh Latinh). Chúng không giống nhau, vì vậy wstring -> char * có thể mất độ chính xác.

-Tom

+0

Điều này có vẻ tốt hơn so với ý tưởng của tôi - vì lý do nào đó, tôi nghĩ std :: wstring sẽ không có chuyển đổi đúng. Cách tiếp cận của tôi tạo ra hai đối tượng phụ - một đối tượng có tên (và có lẽ nặng hơn một chuỗi đơn giản), một đối tượng khác là một cá thể wstring tạm thời. – Steve314

+3

'std :: wstring' không có bất kỳ hàm tạo nào từ' const char * '. –

+0

Bạn có thể xây dựng một chuỗi từ char * các kiểu cơ bản khác nhau. wstring sử dụng wchar_t (có thể là 32 byte không chỉ 16 trên một số hệ thống). –

Các vấn đề liên quan