【问题标题】:Converting _TCHAR* to char*将 TCHAR* 转换为 char*
【发布时间】:2013-10-18 13:17:32
【问题描述】:

我正在尝试让a simple OpenCV sample 在 Windows 上使用 C++ 工作,但我的 C++ 已经生锈了。

The sample 相当简单:

#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 Studio 2012 中创建一个新的简单 C++ 控制台应用程序(使用 ATL)时,我得到了 main 的不同模板:

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

所以在我将文件名发送到 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。)

【问题讨论】:

  • 您的项目模板正在尝试创建一个 C++ 项目以支持 unicode。我不记得具体的项目/编译器选项,但应该有一些东西可以指定是否使用 unicode。
  • 你需要一个USES_CONVERSION;使用转换宏的每个函数顶部的语句?

标签: c++ string visual-c++ atl tchar


【解决方案1】:

_TCHAR,即TCHAR 是一种取决于项目设置的类型。它可以是wchar_t(使用Unicode 时)或char(使用多字节时)。你会在Project Properties - General中找到这个,有一个设置Character Set

您可以做的最简单的事情可能就是使用多字节选项并将_TCHAR* 类型视为简单的char* 并使用它尽快构造std::string 对象:

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

但是,如果您要使用很多特殊字符,那么我发现尽可能使用 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;
}

【讨论】:

  • "我推荐你使用 Unicode" 当然使用 Unicode 并不排除使用char*。通常我将 Unicode 数据编码为 UTF-8 并坚持使用char*
  • @bames53:取决于程序的上下文以及他将要使用的 API,但我承认在这里多字节似乎是更好的选择。
  • @bames53:是的,但不幸的是,在 windows 上,unicode 或多或少暗示了 utf-16 和 wchar_t,因为这就是 win32 api 使用的。
  • 感谢@LihO,但我很确定我明白这一点。然后我会将什么传递给imread 作为它的第一个参数?
  • @dumbledad:你确定你使用的是多字节字符集吗?
【解决方案2】:

最快的解决方案是将签名更改为标准签名。替换:

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

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

这确实意味着在 Windows 上命令行参数被转换为系统的区域设置编码,并且由于 Windows 不支持 UTF-8,因此并非所有内容都能正确转换。但是,除非您确实需要国际化,否则可能不值得您花时间做更多的事情。

【讨论】:

  • 我试过了 - 我会编辑问题来解释(我认为)出了什么问题
  • @dumbledad 好的。编辑问题后在此处发表评论,以便我收到通知。
  • @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 这是字符c 后跟\0 加上更多字节,即字符串“c”!将 _tmain 交换为 main 会有所不同,谢谢。
【解决方案3】:

除了阅读没有太大变化的 26,000 页 cpp 2003 VS 手册之外...... std::string test(print); 测试 = "";

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

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

除非您使用某些安全功能,否则工作方式相同....并且在字符集属性中不能是 unicode ...如果您要在文件管理功能中使用 CreateFile 功能,除非您以某种方式对其进行多线程处理

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-05
    • 2011-11-02
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    相关资源
    最近更新 更多