与所有接受字符串参数的Windows API函数一样,CopyFile函数实际上有两个变体:

> CopyFileA是ANSI版本,它在系统的默认字符集中采用窄(非Unicode)字符串.基本上,它接受const char *类型的参数,但是Windows标头为此使用typedef LPCSTR.

> CopyFileW是宽版本,它采用Unicode字符串.为此,它接受w_char *类型的参数,但是Windows标头为此使用typedef LPCWSTR(请注意typedef中的附加W).

然后,根据是否为项目定义了UNICODE预处理程序宏(在包含Windows头之前的代码中或在Visual Studio中项目的属性中),Windows头将未经修饰的CopyFile定义为CopyFileA或CopyFileW.自然,如果定义了UNICODE,则将CopyFile定义为Unicode版本的CopyFileW.否则,它将定义为CopyFileA.这个想法是在编译时自动将对常规CopyFile函数的调用解析为正确的变体.

当然,既然您已经了解了所有这些内容,那么您基本上可以将其遗忘.在现代Windows编程中,绝对没有理由调用旧的ANSI版本的函数或处理狭窄的字符串.忘记了char *甚至可以用作字符串类型-这些字符串对您来说是固定的.从现在开始,您将要使用的唯一字符串是由wchar_t字符组成的Unicode字符串.因此,应始终为您的代码定义UNICODE符号,并且只能使用Windows API函数的W版本.

再次查看CopyFileW函数的原型(调用定义了UNICODE的CopyFile时得到的原型),我们看到:

BOOL WINAPI CopyFile(LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
BOOL bFailIfExists);

回想一下,您已经了解到LPCWSTR只是const wchar_t *的typedef同义词,const wchar_t *是由宽字符组成的C样式字符串.您已经知道为什么将参数标记为const :,因为该函数不会修改这些值.

并且由于您还从上面了解到,这些是您仅应再使用的唯一类型的字符串,因此下一步是修改FileTrans函数以接受宽字符串(如果不打算对其进行修改,则使其变为const):

int _stdcall FileTrans(const wchar_t* InFile, const wchar_t* OutFile);

现在,从FileTrans内部,您可以调用CopyFile而不会出现任何问题,因为您具有正确的字符串类型.

但是有一点免费的额外建议:切勿在C中使用原始的C样式字符串.始终使用由< string>在std名称空间中定义的C字符串类.头.

该类有两种常见的变体,std :: string和std :: wstring.和以前一样,w表示宽字符串,这是您要在Windows中使用的唯一类型.因此,在整个代码库中,std :: wstring是CHAR *的新替代品.

更改FileTrans函数的声明,如下所示:

#include 
// ...some other stuff...
int __stdcall FileTrans(const std::wstring& InFile, const std::wstring& OutFile);

请注意,我已经将您原来的CHAR *参数更改为对std :: wstring对象的常量引用.常量引用在这里可以很好地工作,因为您不会在函数内部更改这些值中的任何一个.

如果您不清楚常量的含义,如何使用引用或类类型通常在C中的工作方式,请咨询您的favorite C++ book)-这是所有C程序员必需的知识.请记住,C与C是不同的语言,因此不适用相同的习惯用法.在许多情况下,有一种更好的处理方法,这肯定是这种情况的一个示例.