汉字繁简体互换

1、chs2cht.h

#pragma once
char* UnicodeToBIG5(const wchar_t* szUnicodeString);
char* UnicodeToGB2312(const wchar_t* szUnicodeString);
wchar_t* GB2312ToUnicode(const char* szGBString);
char* GB2312ToBIG5(const char* szGBString);

2、chs2cht.cpp

#include "chs2cht.h"
#include <atlstr.h>
//GB2312 转 Unicode:
wchar_t* GB2312ToUnicode(const char* szGBString)  
{  
	UINT nCodePage = 936; //GB2312  
	int nLength=MultiByteToWideChar(nCodePage,0,szGBString,-1,NULL,0);  
	wchar_t* pBuffer = new wchar_t[nLength+1];  
	MultiByteToWideChar(nCodePage,0,szGBString,-1,pBuffer,nLength);  
	pBuffer[nLength]=0;  
	return pBuffer;  
}

//BIG5 转 Unicode:  
wchar_t* BIG5ToUnicode(const char* szBIG5String)  
{  
	UINT nCodePage = 950; //BIG5  
	int nLength=MultiByteToWideChar(nCodePage,0,szBIG5String,-1,NULL,0);  
	wchar_t* pBuffer = new wchar_t[nLength+1];  
	MultiByteToWideChar(nCodePage,0,szBIG5String,-1,pBuffer,nLength);  
	pBuffer[nLength]=0;  
	return pBuffer;  
}

//Unicode 转 GB2312:  
char* UnicodeToGB2312(const wchar_t* szUnicodeString)  
{  
	UINT nCodePage = 936; //GB2312  
	int nLength=WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,NULL,0,NULL,NULL);  
	char* pBuffer=new char[nLength+1];  
	WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);  
	pBuffer[nLength]=0;  
	return pBuffer;  
}

//Unicode 转 BIG5:  
char* UnicodeToBIG5(const wchar_t* szUnicodeString)  
{  
	UINT nCodePage = 950; //BIG5  
	int nLength=WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,NULL,0,NULL,NULL);  
	char* pBuffer=new char[nLength+1];  
	WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);  
	pBuffer[nLength]=0;  
	return pBuffer;  
}

//繁体中文BIG5 转 简体中文GB2312  
char* BIG5ToGB2312(const char* szBIG5String)  
{  
	LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);  
	wchar_t* szUnicodeBuff = BIG5ToUnicode(szBIG5String);  
	char* szGB2312Buff = UnicodeToGB2312(szUnicodeBuff);  
	int nLength = LCMapStringA(lcid,LCMAP_SIMPLIFIED_CHINESE, (LPCSTR)szGB2312Buff,-1,NULL,0);  
	char* pBuffer = new char[nLength + 1];  
	LCMapStringA(0x0804,LCMAP_SIMPLIFIED_CHINESE,(LPCSTR)szGB2312Buff,-1,pBuffer,nLength);  
	pBuffer[nLength] = 0;  

	delete[] szUnicodeBuff;  
	delete[] szGB2312Buff;  
	return pBuffer;  
}

//简体中文GB2312 转 繁体中文BIG5  
char* GB2312ToBIG5(const char* szGBString)  
{  
	LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);  
	int nLength = LCMapStringA(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,NULL,0);  
	char* pBuffer=new char[nLength+1];  
	LCMapStringA(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,pBuffer,nLength);  
	pBuffer[nLength]=0;  
	wchar_t* pUnicodeBuff = GB2312ToUnicode(pBuffer);  
	char* pBIG5Buff = UnicodeToBIG5(pUnicodeBuff);  
	delete[] pBuffer;  
	delete[] pUnicodeBuff;  
	return pBIG5Buff;  
}

3、test.cpp

#include "chs2cht.h"
#include <iostream> 
#include <locale.h>
#include <atlstr.h>  

using namespace std;

int main(int argc, char** argv)
{
    //“区域设置”为简体中文 
    locale loc( "chs" ); 
    char str[100];  
    cin>>str;  
    
    char * rlt=GB2312ToBIG5(str);  
    CString cStr1;   
    cStr1.Format( TEXT("%s"),rlt); 

    //“区域设置”为繁体中文 
    setlocale(LC_ALL, ".950");  
    cout<<rlt<<endl; 

    return 0;
}

VC fix .pch file missing

表现:

Error   1   fatal error C1083: Cannot open precompiled header file: 'Debug\????.pch': No such file or directory

解决方法:
1、保证stdafx.h及stdafx.cpp在项目的最顶层,stdafx.h用于保存需要的头文件,stdafx.cpp中只有对stdafx.h的引用;
2、在VS中,右击需要修改的工程,选择”Properties”;
3、在左上角,选择“ All Configurations”;
4、在左边,找到“C/C++”,并定位到“Precompiled Headers”;
5、将选项Precompiled Header修改为: “Use (/Yu)”;
6、将选项“Precompiled Header File”修改为:“stdafx.h”;
7、保存设置;
8、保证#include “stdafx.h”为所有需要预编译的cpp文件的第一行;
9、VS中,右击stdafx.cpp,选择”Properties”;
10、在左上角,选择“ All Configurations”;
11、将选项Precompiled Header修改为: “Create (/Yc).”;
12、保存设置,重新编译。

VC的链接顺序

CRT库在链接new, delete, DllMain这些符号的时候,使用的是弱外链接
MFC库同样也包含了new, delete, DllMain这几个符号,而MFC库必须在CRT库之前被链接才会成功。

如果link时出现了符号冲突,做下面的设置即可
project>properties>configuration properties>linker>input
在”Additional dependency”中依次增加 Nafxcwd.lib Libcmtd.lib
在add to “ignore specific library”中依次增加Nafxcwd.lib;Libcmtd.lib

VC服务程序调用远程资源

当VC服务程序调用远程资源时,经常返回路径不存在等问题
这是因为Windows中,服务程序以System用户登录,而不是桌面用户登录
这样就导致,虽然桌面程序已经映射网络资源,但System用户仍无法访问的问题
为了可以访问远程资源,可以调用API:WNetAddConnection2

BOOL AcessNetworkDrtive(CString szDevice,CString szDeviceName,CString szUsername,CString szPassword)
{
	DWORD dwRetVal;
	NETRESOURCE nr;

	memset(&nr, 0, sizeof (NETRESOURCE));
	nr.dwType = RESOURCETYPE_ANY;
	nr.lpLocalName = strDevice.GetBuffer(szDevice.GetLength());
	nr.lpRemoteName = szDeviceName.GetBuffer(szDeviceName.GetLength());
	nr.lpProvider = NULL;

	dwRetVal = WNetAddConnection2(&nr, szUsername, szUsername, CONNECT_UPDATE_PROFILE);

	if (dwRetVal != NO_ERROR)
	{
		CString cError;
		cError.Format(TEXT("[ERROR]WNetAddConnection2 Failed: %u\n"), dwRetVal);
		LogEvent(cError,TEXT("With remote name "),nr.lpRemoteName);
		return dwRetVal;
	}

	return 	dwRetVal;
}

创建进程API

Winexec
UINT WinExec(
LPCSTR lpCmdLine, 
UINT uCmdShow ); 

ShellExecute
HINSTANCE ShellExecute(
HWND hwnd, 
LPCTSTR lpOperation, 
LPCTSTR lpFile,
LPCTSTR lpParameters, 
LPCTSTR lpDirectory,
INT nShowCmd ); 

CreateProcess
BOOL CreateProcess(LPCTSTR lpApplicationName, 
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo, 
LPPROCESS_INFORMATION lpProcessInformation
); 

CPP类型转换

1、static_cast

这是应该首先选用的转换方式,一般用于在相关类型间进行转换或在继承链中进行转换。
其运作方式类似于隐式转换 (比如int转为float,或指针转换为 void*), 而且它可以调用显示转换(当然包括隐式转换)。

在很多情况下, 显示声明static_cast是不必要的,
但有一点需要指出的是应当尽量避免type(XXX) 与(type)XXX 语法(详情见下文)。
然而type(XXX,YYY) 是安全的,而且一定会去调用构造函数。

static_cast也可以在父类及子类之间进行。 当子类向父类转换时是可以顺利进行的。但父类向子类转换时,只要子类没有继承virtual父类,就可以一直进行。但是它从父类转为子类时,不会做任何检查,即使类型不完全匹配。

2、const_cast

用来向一个变量增加或删除const属性。 其他任何C++ casts都无法完成此任务。
需要指出的是,当变量为const,该操作符是未定义的。

用它来声明一个非const类型的const引用是安全的。
当重载const类型的类成员变量时,该转换十分有用。
它也可以用来把一个对象增加const属性,比如调用重载的方法。

const_cast也适用于volatile,但很少见。

3、dynamic_cast

一般用来解决多态问题。你可以把指针或参考转换为任何继承链上的类型。
(一个多态类型至少用一个虚函数,无论是声明还是继承的)。
当从子类转换为父类时,dynamic_cast一定会成功。但从父类转换为子类,dynamic_cast会确保对象为子类的一个完全实现。

dynamic_cast将返回其是否可能。如果无法转换,他将返回NULL(对指针),或抛出std::bad_cast异常(对参考)。

dynamic_cast有一些限制:
如果在继承链中,同一类型有多个对象(dreaded diamond)同时你没有使用虚接口,转换不会进行。
他也只能应用于public继承,当protect或private继承时,会失败。

注意:
dynamic_cast需要编译器支持RTTI(运行时类型识别)。

4、reinterpret_cast

这是最危险的转换方式,慎用。 它直接把一种类型转换为另一种
(比如把值从一种指针转换为另一种指针,或把指针储存在int中, 或其他让人讨厌的事情)

使用reinterpret_cast,唯一能保证的是,当你从结构转回为原类型时,你能得到相同的结果。
当然,reinterpret_cast也有一些转换无法进行。

他通常用于比较奇怪的转换,或bit操作,比图把raw数据流转换为实际数据,或把数据储存在对齐指针的低字节。
当其他转换无法使用时,可以尝试reinterpret_cast

5、C-style cast
C-style cast 是使用(type)object 或 type(object)的转换方式。
C-style cast 被定义为下列转换中第一个成功返回的:
const_cast
static_cast
static_cast, then const_cast
reinterpret_cast
reinterpret_cast, then const_cast

在一些时候,他可以被用来替代其他casts,但用于他最后可能会调用reinterpret_cast(应显示调用),因此C-style cast是十分危险的。
除非你能保证,不会调用reinterpret_cast,或者reinterpret_cast一定会失败,否则不要轻易使用。即使如此,也应该考虑显示调用上面的转换。

当使用static_cast时,C-style casts 也可以忽略权限控制,这意味着他可以进行其他cast无法进行的操作。
这是避免C-style casts的一个不错的理由。

(翻译自Stack Overflow的一个帖子,水平有限,哈哈)

参考资料:
http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-and-reinterpret-cast-be-used
http://www.cplusplus.com/doc/tutorial/typecasting/
http://en.wikibooks.org/wiki/C%2B%2B_Programming/Programming_Languages/C%2B%2B/Code/Statements/Variables/Type_Casting

VC计算CString摘要

1、VC计算字符串MD5摘要

//输入:要计算摘要的字符串
//输出:128位MD5摘要
#include <wincrypt.h>
CString szResult;

CString CDigestDlg::CalcMD5(CString strContent)
{
  DWORD dwLength=0;
  BYTE* pbContent=NULL;

  dwLength = (DWORD)strContent.GetLength();
  pbContent = new BYTE[dwLength];
  memcpy(pbContent,strContent.GetBuffer(dwLength),dwLength);

  //计算MD5编码
  HCRYPTPROV hCryptProv; 
  HCRYPTHASH hHash; 
  BYTE byteMD5[16]; 
  DWORD dwHashLen=16;
  CString szResult;

  if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) 
  {
    if(CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) 
    {
      if(CryptHashData(hHash, pbContent, dwLength, 0))
      {

        if(CryptGetHashParam(hHash, HP_HASHVAL, byteMD5, &dwHashLen, 0)) 
        {
          szResult.Format(TEXT("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"),
            byteMD5[0],byteMD5[1],byteMD5[2],byteMD5[3],byteMD5[4],byteMD5[5],byteMD5[6],byteMD5[7]
            ,byteMD5[8],byteMD5[9],byteMD5[10],byteMD5[11],byteMD5[12],byteMD5[13],byteMD5[14],byteMD5[15]);
        }
        else
        {
          szResult=TEXT("Error getting hash param");
        }

      }
      else
      {
        szResult=TEXT("Error hashing data");
      }
    }
    else
    {
      szResult=TEXT("Error creating hash");
    }
  }
  else
  {
    szResult=TEXT("Error acquiring context");
  }

  CryptDestroyHash(hHash); 
  CryptReleaseContext(hCryptProv, 0); 
  delete[] pbContent;
  pbContent=NULL;

  return szResult;
}

2、VC计算字符串SHA1摘要

//输入:要计算摘要的字符串
//输出:160位SHA1摘要
#include <wincrypt.h>
CString szResult;

CString CDigestDlg::CalcSHA1(CString strContent)
{
  DWORD dwLength=0;
  BYTE* pbContent=NULL;

  dwLength = (DWORD)strContent.GetLength();
  pbContent = new BYTE[dwLength];
  memcpy(pbContent,strContent.GetBuffer(dwLength),dwLength);

  //计算MD5编码
  HCRYPTPROV hCryptProv; 
  HCRYPTHASH hHash; 
  BYTE byteSHA1[20]; 
  DWORD dwHashLen=20;
  CString szResult;

  if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) 
  {
    if(CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash)) 
    {
      if(CryptHashData(hHash, pbContent, dwLength, 0))
      {

        if(CryptGetHashParam(hHash, HP_HASHVAL, byteSHA1, &dwHashLen, 0)) 
        {
          szResult.Format(TEXT("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"),
            byteSHA1[0],byteSHA1[1],byteSHA1[2],byteSHA1[3],byteSHA1[4],byteSHA1[5],byteSHA1[6],byteSHA1[7],
            byteSHA1[8],byteSHA1[9],byteSHA1[10],byteSHA1[11],byteSHA1[12],byteSHA1[13],byteSHA1[14],byteSHA1[15],
            byteSHA1[16],byteSHA1[17],byteSHA1[18],byteSHA1[19]);
        }
        else
        {
          szResult=TEXT("Error getting hash param");
        }

      }
      else
      {
        szResult=TEXT("Error hashing data");
      }
    }
    else
    {
      szResult=TEXT("Error creating hash");
    }
  }
  else
  {
    szResult=TEXT("Error acquiring context");
  }

  CryptDestroyHash(hHash); 
  CryptReleaseContext(hCryptProv, 0); 
  delete[] pbContent;
  pbContent=NULL;

  return szResult;
}

VC计算文件摘要

1、VC计算文件MD5摘要

//输入:文件路径
//输出:128位MD5摘要
#include <wincrypt.h>
CString szResult;

CString CMD5AndSHA1Dlg::CalcMD5(CString strFilePath)
{
  //读取文件
  CFile inFile;
  CFileException ex;
  DWORD dwLength=0;
  BYTE* pbContent=NULL;
  BOOL bRet;

  bRet=inFile.Open(strFilePath,CFile::modeRead | CFile::typeBinary | CFile::shareDenyWrite,&ex);
  if(bRet==FALSE)
  {
    return TEXT("Error opening file");;
  }

  dwLength = (DWORD)inFile.GetLength();
  pbContent = new BYTE[dwLength];
  if(pbContent==NULL)
  {
    return TEXT("Error not enough memory");;
  }
  inFile.Read(pbContent,dwLength);
  inFile.Close();

  //计算MD5编码
  HCRYPTPROV hCryptProv; 
  HCRYPTHASH hHash; 
  BYTE byteMD5[16]; 
  DWORD dwHashLen=16;
  CString szResult;

  if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) 
  {
    if(CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) 
    {
      if(CryptHashData(hHash, pbContent, dwLength, 0))
      {

        if(CryptGetHashParam(hHash, HP_HASHVAL, byteMD5, &dwHashLen, 0)) 
        {
          szResult.Format(TEXT("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"),
            byteMD5[0],byteMD5[1],byteMD5[2],byteMD5[3],byteMD5[4],byteMD5[5],byteMD5[6],byteMD5[7]
            ,byteMD5[8],byteMD5[9],byteMD5[10],byteMD5[11],byteMD5[12],byteMD5[13],byteMD5[14],byteMD5[15]);
        }
        else
        {
          szResult=TEXT("Error getting hash param");
        }

      }
      else
      {
        szResult=TEXT("Error hashing data");
      }
    }
    else
    {
      szResult=TEXT("Error creating hash");
    }
  }
  else
  {
    szResult=TEXT("Error acquiring context");
  }

  CryptDestroyHash(hHash); 
  CryptReleaseContext(hCryptProv, 0); 
  delete[] pbContent;
  pbContent=NULL;

  return szResult;
}

2、VC计算文件SHA1摘要

//输入:文件路径(文件必须小于2^64bit)
//输出:160位SHA1摘要
#include <wincrypt.h>
CString szResult;

CString CMD5AndSHA1Dlg::CalcSHA1(CString strFilePath)
{
  //读取文件
  CFile inFile;
  CFileException ex;
  DWORD dwLength=0;
  BYTE* pbContent=NULL;
  BOOL bRet;

  bRet=inFile.Open(strFilePath,CFile::modeRead | CFile::typeBinary | CFile::shareDenyWrite,&ex);
  if(bRet==FALSE)
  {
    return TEXT("Error opening file");;
  }

  dwLength = (DWORD)inFile.GetLength();
  pbContent = new BYTE[dwLength];
  if(pbContent==NULL)
  {
    return TEXT("Error not enough memory");;
  }
  inFile.Read(pbContent,dwLength);
  inFile.Close();

  //计算MD5编码
  HCRYPTPROV hCryptProv; 
  HCRYPTHASH hHash; 
  BYTE byteSHA1[20]; 
  DWORD dwHashLen=20;
  CString szResult;

  if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) 
  {
    if(CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash)) 
    {
      if(CryptHashData(hHash, pbContent, dwLength, 0))
      {

        if(CryptGetHashParam(hHash, HP_HASHVAL, byteSHA1, &dwHashLen, 0)) 
        {
          szResult.Format(TEXT("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"),
            byteSHA1[0],byteSHA1[1],byteSHA1[2],byteSHA1[3],byteSHA1[4],byteSHA1[5],byteSHA1[6],byteSHA1[7],
            byteSHA1[8],byteSHA1[9],byteSHA1[10],byteSHA1[11],byteSHA1[12],byteSHA1[13],byteSHA1[14],byteSHA1[15],
            byteSHA1[16],byteSHA1[17],byteSHA1[18],byteSHA1[19]);
        }
        else
        {
          szResult=TEXT("Error getting hash param");
        }

      }
      else
      {
        szResult=TEXT("Error hashing data");
      }
    }
    else
    {
      szResult=TEXT("Error creating hash");
    }
  }
  else
  {
    szResult=TEXT("Error acquiring context");
  }

  CryptDestroyHash(hHash); 
  CryptReleaseContext(hCryptProv, 0); 
  delete[] pbContent;
  pbContent=NULL;

  return szResult;
}

函数调用约定

1.STDCALL
微软制定的c语言调用约定,也就是传说中的WINAPI
参数从右向左进行压栈(微软官方文档说从左向右压栈),返回值存在eax中,
被调用函数清理栈,不允许变长参数列表
函数名前增加_,函数名后增加@和参数个数(32位机器上一定被4整除)
ret指令中,有可选参数指定有多少字节需要弹栈

2.CDECL
c语言的默认调用约定
参数从右向左进行压栈,返回值存在eax中,
调用函数清理栈,可用变长参数列表
函数名前会增加_

3.FASTCALL
非跨编译器的c语言调用约定,
前2-3个4字节内的参数被存放到寄存器(edx,eax,ecx)中,其他参数,或大于4字节的参数,按从右到左的顺序被存放在栈中
多数情况下,调用函数负责清理栈
仅适用于参数少,而且实时性要求很高的情况下
函数名前增加@,函数名后增加@和参数个数

4.THISCALL
cpp的调用约定
参数从右向左进行压栈,返回值存在eax中,this指针存在ecx中
每种编译器对函数名称有不同的修饰方法,但基于重载的需要,一般都会增加参数类型和类名
当使用extern “C”的时候,cpp编译器会使用c语言的修饰方法来修饰函数名,这样就可以方便的供别人调用了。

c与cpp输出16进制,8进制及ASCII

1.c

#include <stdio.h>
int main(int argc,char **argv)
{
	for(int i=0;i<=127;i++)
	{
		printf("%X-%03o-%c\n",i,i,i);
	}
	return 0;
}

2.cpp

#include <iostream>
#include <iomanip>

using namespace std;

int main(int argc,char **argv)
{
	for(int i=0;i<=127;i++)
	{
		cout<<setw(2)<<setfill('0')<<hex<<i<<"-"<<setw(3)<<setfill('0')<<oct<<i<<"-"<<dec<<(char)i<<endl;
	}

	return 0;
}