2013-10-10 66 views
3

我試圖讓a simple OpenCV sample在Windows上使用C++,而我的C++不僅僅是生鏽。將_TCHAR *轉換爲char *

The sample是相當簡單:所以之前

int _tmain(int argc, _TCHAR* argv[]) 

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <iostream> 

using namespace cv; 
using namespace std; 

int main(int argc, char** argv) 
{ 
    if(argc != 2) 
    { 
     cout <<" Usage: display_image ImageToLoadAndDisplay" << endl; 
     return -1; 
    } 
    Mat image; 
    image = imread(argv[1], IMREAD_COLOR); // Read the file 
    if(! image.data)      // Check for invalid input 
    { 
     cout << "Could not open or find the image" << std::endl ; 
     return -1; 
    } 
    namedWindow("Display window", WINDOW_AUTOSIZE); // Create a window for display. 
    imshow("Display window", image);    // Show our image inside it. 
    waitKey(0); // Wait for a keystroke in the window 
    return 0; 
} 

當我提出一個新的簡單的C++控制檯在Visual Studio應用程序(使用ATL)2012我得到main不同的模板我發送文件名到OpenCV的imread函數,我需要將_TCHAR*arg[1]轉換爲char*。使用一個簡單的文件名,「OpenCV的-logo.jpg」,從內存窗口中的內存,我可以看到_TCHAR正在採取兩個字節每個

o.p.e.n.c.v.-.l.o.g.o...j.p.g... 
6f 00 70 00 65 00 6e 00 63 00 76 00 2d 00 6c 00 6f 00 67 00 6f 00 2e 00 6a 00 70 00 67 00 00 00 

繼轉換建議在another answer我試圖使用ATL 7.0 String Conversion Classes and Macros通過將以下代碼:

char* filename = CT2A(argv[1]); 

但所得到的存儲器是亂的,肯定不是 '的OpenCV-logo.jpg' 爲ASCII字符串:

fe fe fe fe fe fe fe fe fe fe ... 
þþþþþþþþþþ ... 

我應該使用哪種轉換技術,函數或宏?

(注:This可能是一個相關的問題,但我看不出如何適用於此the answer。)

+0

您的項目模板正試圖爲unicode支持創建一個C++項目。我不記得具體的項目/編譯器選項,但應該有一些指定是否使用unicode。 – OldProgrammer

+0

它在[通用項目屬性頁面](http://msdn.microsoft.com/en-us/library/vstudio/8x480de8.aspx) – user786653

+0

您需要USES_CONVERSION;語句在使用轉換宏的每個函數的頂部? –

回答

16

最快的解決方案是將簽名更改爲標準簽名。替換:

int _tmain(int argc, _TCHAR* argv[]) 

隨着

int main(int argc, char *argv[]) 

這並不在Windows上表示命令行參數被轉換到系統的區域設置編碼和因爲Windows不支持UTF-8在這裏並非一切正常轉換。然而除非你真的需要國際化,否則你可能不值得花更多的時間去做更多的事情。

+0

我試過 - 我會編輯這個問題來解釋我認爲出了什麼問題 – dumbledad

+0

@dumbledad好的。當你編輯你的問題時在這裏評論,所以我收到通知。 – bames53

+2

@bames這是行不通的。最後一次我使用了'int _tmain(int argc,char ** argv)'和'char *''結尾爲'6f 00 70 00 65 00 6e 00 63 00 76 00 2d 00 6c 00 6f 00 67 00 6f 00 2e 00 6a 00 70 00 67 00 00 00'這是char'c'後面跟着'\ 0'加上更多字節,即字符串「c」!將'_tmain'交換爲'main'會產生很大的不同,謝謝。 – dumbledad

7

_TCHAR,即TCHAR是依賴於項目的設置類型。它可以是wchar_t(當您使用Unicode時)或char(當您使用多字節時)。您將在項目屬性發現這一點 - 一般,有一個設置字符集

可能是你可以做最簡單的事情就是使用多字節的選項和治療_TCHAR*類型作爲簡單char*,並用它來構建儘快std::string對象:

std::string filename(argv[1]); 

但萬一您將使用特殊字符A LOT,然後我發現使用Unicode更合理,並在任何可能的地方以std::wstring對象的形式保存字符串。如果是這樣的話,那麼就使用std::wstring的構造來代替:

std::wstring filename(argv[1]); 

而如果你會擁有寬字符串的工作,有時候你需要寬字符串和多字節字符串之間的轉換這些幫助者可能會幫助您:

// multi byte to wide char: 
std::wstring s2ws(const std::string& str) 
{ 
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0); 
    std::wstring wstrTo(size_needed, 0); 
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed); 
    return wstrTo; 
} 

// wide char to multi byte: 
std::string ws2s(const std::wstring& wstr) 
{ 
    int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), 0, 0, 0, 0); 
    std::string strTo(size_needed, 0); 
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), &strTo[0], size_needed, 0, 0); 
    return strTo; 
} 
+0

「我推薦你使用Unicode」當然使用Unicode並不排除使用'char *'。通常,我將Unicode數據編碼爲UTF-8並堅持使用'char *'。 – bames53

+0

@ bames53:取決於程序的上下文以及他將要使用的API,但我承認多字節似乎是一個更好的選擇。 – LihO

+1

@ bames53:是的,但不幸的是,在windows unicode中,或多或少意味着utf-16和'wchar_t',因爲這就是win32 API所使用的。 – user786653

-1

除了讀26,000頁的cpp 2003 VS手冊,其中沒有太多變化.... std :: string test(print); test =「」;

int _tmain(int argc, _TCHAR* argv[]) 

int main(int argc, char *argv[]) 

工作一樣,除非你使用一些securitys功能....並不能在字符集屬性unicode的...如果你使用CreateFile函數中的文件管理功能,除非你多 - 它以某種方式運行它