web-dev-qa-db-ja.com

_TCHAR *をchar *に変換する

私は取得しようとしています 単純なOpenCVサンプル Windows上のC++で動作し、私のC++はさびた以上のものです。

サンプル はかなり単純です:

#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;
}

Visual Studio2012で新しい単純なC++コンソールアプリケーション(ATLを使用)を作成すると、mainの別のテンプレートが表示されます。

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

したがって、ファイル名をOpenCVのimread関数に送信する前に、_TCHAR*arg[1]char*に変換する必要があります。メモリウィンドウのメモリから単純なファイル名 'opencv-logo.jpg'を使用すると、_TCHARがそれぞれ2バイトを使用していることがわかります。

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

別の回答 の変換の推奨事項に従って ATL 7.0文字列変換クラスとマクロ を使用しようとしています。次のコードを挿入します。

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

しかし、結果として得られるメモリは混乱しており、ASCII文字列としての「opencv-logo.jpg」ではありません。

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

どの変換手法、関数、またはマクロを使用する必要がありますか?

(注 これ 関連する質問かもしれませんが、適用方法がわかりません 答え ここにあります。)

5
dumbledad

最も簡単な解決策は、署名を標準の署名に変更することです。交換:

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

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

これは、Windowsでは、コマンドライン引数がシステムのロケールエンコーディングに変換されることを意味します。WindowsはUTF-8をサポートしていないため、すべてが正しく変換されるわけではありません。ただし、実際に国際化が必要な場合を除いて、これ以上何もする価値はないかもしれません。

19
bames53

_TCHAR、つまりTCHARは、プロジェクトの設定に依存するタイプです。 wchar_t(Unicodeを使用する場合)またはchar(マルチバイトを使用する場合)のいずれかになります。これはプロジェクトプロパティ --General、設定があります文字セット

おそらく、あなたができる最も簡単なことは、マルチバイトオプションを使用し、_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;
}
7
LihO