在C ++中将字符串复制到TCHAR中

时间:2015-09-20 19:10:33

标签: c++

我正在尝试用C ++将字符串复制到TCHAR中,但是我遇到了以下错误:

  

错误C4996'std :: _ Copy_impl':带有可能不安全的参数的函数调用 - 此调用依赖于调用者来检查传递的值是否正确。要禁用此警告,请使用-D_SCL_SECURE_NO_WARNINGS。

这就是我想要做的。我只是将一个字符串复制到TCHAR中,然后尝试将其打印出来以确认它是正确的。

  root 'index#home'

  scope '/:user' do
    get '/change_avatar' => 'avatars#edit', as: :change_avatar
    post '/change_avatar' => 'avatars#update', as: :update_avatar
    get '/edit' => 'users#edit', as: :edit_user
    delete '/' => 'users#destroy', as: :destroy_user
    post '/playlists' => 'playlists#create', as: :playlists
  end

  scope '/:user/:playlist' do
    get '/' => 'playlists#show', as: :show_playlist
    get '/edit' => 'playlists#edit', as: :edit_playlist
    patch '/' => 'playlists#update', as: :update_playlist
    delete '/' => 'playlists#destroy', as: :destroy_playlist
    post '/tracks' => 'tracks#create', as: :tracks
  end

  scope '/:user/:playlist/:track' do
    get '/' => 'tracks#show', as: :show_track
    get '/edit' => 'tracks#edit', as: :edit_track
    patch '/' => 'tracks#update', as: :update_track
    delete '/' => 'tracks#destroy', as: :destroy_track
    delete '/photos/:id' => 'photos#destroy', as: :destroy_photo
  end

EDIT 如何“使用-D_SCL_SECURE_NO_WARNINGS”作为消息状态?

3 个答案:

答案 0 :(得分:4)

编译器警告说。您可以在#define _SCL_SECURE_NO_WARNINGS语句之前添加#include,或将-D_SCL_SECURE_NO_WARNINGS标志添加到项目的编译器输入标记中。

但是,这不是一个合适的解决方案。当std::copy()映射到char而不是TCHAR时,TCHAR不足以将基于wchar_t的字符串转换为基于char的字符串。复制字符1对1仅适用于ASCII字符(您的示例正在使用),但在使用非ASCII字符时失败,因为生成的TCHAR[]数组可能需要比TCHAR更多的元素{ {1}}报告。在这种情况下,您确实需要使用str.size()MultiByteToWideChar之类的数据转换。

试试这个:

std::wstring_convert

或更简单(如@MicroVirus建议):

#include "stdafx.h"
#include <string>

using namespace std;

typedef basic_string<TCHAR> TCHARstring;

TCHARstring string2TCHAR(const string &s)
{
    #ifdef UNICODE
    TCHARstring tstr;
    int size = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), NULL, 0);
    if (size > 0)
    {
        tstr.resize(size);
        MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), &tstr[0], size);
    }
    return tstr;
    #else
    return s;
    #endif
}

int main()
{
    string str = "C:\\windows\\system32\\calc.exe";
    TCHARstring tstr = string2TCHAR(str);
    _tprintf(_T("%s"), tstr.c_str());
    /*
    or:
    #ifdef UNICODE
    wcout << tstr;
    #else
    cout << tstr;
    #endif
    */
    return 0;
}

但你真的应该停止使用#include "stdafx.h" #include <string> using namespace std; typedef basic_string<TCHAR> TCHARstring; int main() { TCHARstring str = TEXT("C:\\windows\\system32\\calc.exe"); _tprintf(_T("%s"), tstr.c_str()); /* or: #ifdef UNICODE wcout << tstr; #else cout << tstr; #endif */ return 0; } 。其主要目的是通过允许开发人员为两个平台使用单个代码库来帮助将传统的Win9x / ME ANSI代码迁移到NT4 + Unicode。但是,没有人为Win9x / ME开发,所以你应该坚持使用Unicode:

TCHAR

或者至少继续按原样使用int main() { wstring str = L"C:\\windows\\system32\\calc.exe"; wprintf(L"%s", str.c_str()); // or: wcout << str; return 0; } 并让操作系统在API层处理ANSI-&gt; Unicode转换(不推荐,但仍然支持):

string

否则,如果要在Unicode API中使用ANSI int main() { string str = "C:\\windows\\system32\\calc.exe"; printf("%s", str.c_str()); // or: cout << str; return 0; } 值,则必须进行手动转换:

string

答案 1 :(得分:2)

A&#39;技巧&#39;在Windows中使用TCHAR以及我更喜欢使用的STL字符串是定义我自己的tstring类型:

typedef std::basic_string<TCHAR> tstring;

然后,我到处都使用tstring而不是std::string。这样,如果使用&#34;多字节字符集编译&#34;对于字符集,它等于std::string,并且在使用&#34; Unicode字符集&#34;进行编译时它等于std::wstring

最棒的是,这可以避免将其复制到TCHAR数组,并且可以直接将c_str()属性与_tprintf以及 TCHAR.h 标题。它也摆脱了警告,这指出了一个潜在的问题。

答案 2 :(得分:1)

现代编译器强制实施安全编码,以提高代码质量。

早期C设计了一个像$gameid = 5; $game{$gameid} = active; 这样的函数,它将新行读入缓冲区。

这导致程序崩溃(缓冲区溢出),然后有些人发现他们可以“接管”程序,并允许远程攻击者接管计算机。

现代gets( buffer );设计尝试提供相同类型的功能,而没有固定大小缓冲区的风险。

投诉是,在复制到szAppName时,C++无法检查std::copy是否足够大,如果不是,那么您的程序就容易受到攻击。

在您的情况下,您已创建了正确大小的缓冲区,并且警告没有帮助。

szAppName中存在不同类型的漏洞。这是为了获取带有格式说明符的字符串并打印出参数。

考虑_tprintf

_tprintf( "%s", szAppName ); // avoid _tprintf exploit.

因为这会避免警告。