论坛首页· 友情链接申请·申请版主· 广告投放· 道具中心· 设为首页· 收藏本站
 19 12
发新话题
打印

LPTSTR类型转换为char*

LPTSTR类型转换为char*

换了vs2008,最近编程总是这个问题,比较烦。在vc++6.0中,可以直接用char*赋给LPSTR,现在VS中不行了,开始我通过CString实现,但又遇到一个麻烦,CString没有提供转换到c-style字符串的函数,我去查了些资料,贴进来,希望能对大家有些帮助。
因为梦想而努力,因为有你而精彩!
mail: qianzongming@gmail.com

TOP

CString   转化成   char*   之一:强制类型转换为   LPCTSTR;   
   
    这是一种略微硬性的转换,有关"正确"的做法,人们在认识上还存在许多混乱,正确的使用方法有很多,但错误的使用方法可能与正确的使用方法一样多。   
    我们首先要了解   CString   是一种很特殊的   C++   对象,它里面包含了三个值:一个指向某个数据缓冲区的指针、一个是该缓冲中有效的字符记数以及一个缓冲区长度。   有效字符数的大小可以是从0到该缓冲最大长度值减1之间的任何数(因为字符串结尾有一个NULL字符)。字符记数和缓冲区长度被巧妙隐藏。   
    除非你做一些特殊的操作,否则你不可能知道给CString对象分配的缓冲区的长度。这样,即使你获得了该0缓冲的地址,你也无法更改其中的内容,不能截短字符串,也   绝对没有办法加长它的内容,否则第一时间就会看到溢出。   
    LPCTSTR   操作符(或者更明确地说就是   TCHAR   *   操作符)在   CString   类中被重载了,该操作符的定义是返回缓冲区的地址,因此,如果你需要一个指向   CString   的   字符串指针的话,可以这样做:   
   
   
  CString   s("GrayCat");   
  LPCTSTR   p   =   s;   
    它可以正确地运行。这是由C语言的强制类型转化规则实现的。当需要强制类型转化时,C++规测容许这种选择。比如,你可以将(浮点数)定义为将某个复数   (有一对浮点数)进行强制类型转换后只返回该复数的第一个浮点数(也就是其实部)。可以象下面这样:   
   
  Complex   c(1.2f,   4.8f);   
  float   realpart   =   c;   
  如果(float)操作符定义正确的话,那么实部的的值应该是1.2。   
    这种强制转化适合所有这种情况,例如,任何带有   LPCTSTR   类型参数的函数都会强制执行这种转换。   于是,你可能有这样一个函数(也许在某个你买来的DLL中):   
   
  BOOL   DoSomethingCool(LPCTSTR   s);   
  你象下面这样调用它:   
   
  CString   file("c:\\myfiles\\coolstuff")   
  BOOL   result   =   DoSomethingCool(file);   
    它能正确运行。因为   DoSomethingCool   函数已经说明了需要一个   LPCTSTR   类型的参数,因此   LPCTSTR   被应用于该参数,在   MFC   中就是返回的串地址。   
   
  如果你要格式化字符串怎么办呢?   
   
  CString   graycat("GrayCat");   
  CString   s;   
  s.Format("Mew!   I   love   %s",   graycat);   
    注意由于在可变参数列表中的值(在函数说明中是以"..."表示的)并没有隐含一个强制类型转换操作符。你会得到什么结果呢?   
    一个令人惊讶的结果,我们得到的实际结果串是:   
   
  "Mew!   I   love   GrayCat"。   
    因为   MFC   的设计者们在设计   CString   数据类型时非常小心,   CString   类型表达式求值后指向了字符串,所以这里看不到任何象   Format   或   sprintf   中的强制类型转换,你仍然可以得到正确的行为。描述   CString   的附加数据实际上在   CString   名义地址之后。   
    有一件事情你是不能做的,那就是修改字符串。比如,你可能会尝试用","代替"."(不要做这样的,如果你在乎国际化问题,你应该使用十进制转换的   National   Language   Support   特性,),下面是个简单的例子:   
   
  CString   v("1.00");   //   货币金额,两位小数   
  LPCTSTR   p   =   v;   
  p[lstrlen(p)   -   3]   =   ,;   
    这时编译器会报错,因为你赋值了一个常量串。如果你做如下尝试,编译器也会错:   
   
  strcat(p,   "each");   
    因为   strcat   的第一个参数应该是   LPTSTR   类型的数据,而你却给了一个   LPCTSTR。   
   
    不要试图钻这个错误消息的牛角尖,这只会使你自己陷入麻烦!   
   
    原因是缓冲有一个计数,它是不可存取的(它位于   CString   地址之下的一个隐藏区域),如果你改变这个串,缓冲中的字符计数不会反映所做的修改。此外,如果字符串长度恰好是该字符串物理限制的长度(梢后还会讲到这个问题),那么扩展该字符串将改写缓冲以外的任何数据,那是你无权进行写操作的内存(不对吗?),你会毁换坏不属于你的内存。这是应用程序真正的死亡处方。   
   
  CString转化成char*   之二:使用   CString   对象的   GetBuffer   方法;   
   
    如果你需要修改   CString   中的内容,它有一个特殊的方法可以使用,那就是   GetBuffer,它的作用是返回一个可写的缓冲指针。   如果你只是打算修改字符或者截短字符串,你完全可以这样做:   
   
  CString   s(_T("File.ext"));   
  LPTSTR   p   =   s.GetBuffer();   
  LPTSTR   dot   =   strchr(p,   .);   //   OK,   should   have   used   s.Find...   
  if(p   !=   NULL)   
  *p   =   _T(\0);   
  s.ReleaseBuffer();   
    这是   GetBuffer   的第一种用法,也是最简单的一种,不用给它传递参数,它使用默认值   0,意思是:"给我这个字符串的指针,我保证不加长它"。当你调用   ReleaseBuffer   时,字符串的实际长度会被重新计算,然后存入   CString   对象中。   
    必须强调一点,在   GetBuffer   和   ReleaseBuffer   之间这个范围,一定不能使用你要操作的这个缓冲的   CString   对象的任何方法。因为   ReleaseBuffer   被调用之前,该   CString   对象的完整性得不到保障。研究以下代码:   
   
  CString   s(...);   
   
  LPTSTR   p   =   s.GetBuffer();   
   
  //...   这个指针   p   发生了很多事情   
   
  int   n   =   s.GetLength();   //   很糟D!!!!!   有可能给出错误的答案!!!   
   
  s.TrimRight();   //   很糟!!!!!   不能保证能正常工作!!!!   
   
  s.ReleaseBuffer();   //   现在应该   OK   
   
  int   m   =   s.GetLength();   //   这个结果可以保证是正确的。   
   
  s.TrimRight();   //   将正常工作。   
    假设你想增加字符串的长度,你首先要知道这个字符串可能会有多长,好比是声明字符串数组的时候用:   
   
  char   buffer[1024];   
  表示   1024   个字符空间足以让你做任何想做得事情。在   CString   中与之意义相等的表示法:   
   
  LPTSTR   p   =   s.GetBuffer(1024);   
    调用这个函数后,你不仅获得了字符串缓冲区的指针,而且同时还获得了长度至少为   1024   个字符的空间(注意,我说的是"字符",而不是"字节",因为   CString   是以隐含方式感知   Unicode   的)。   
    同时,还应该注意的是,如果你有一个常量串指针,这个串本身的值被存储在只读内存中,如果试图存储它,即使你已经调用了   GetBuffer   ,并获得一个只读内存的指针,存入操作会失败,并报告存取错误。我没有在   CString   上证明这一点,但我看到过大把的   C   程序员经常犯这个错误。   
    C   程序员有一个通病是分配一个固定长度的缓冲,对它进行   sprintf   操作,然后将它赋值给一个   CString:   
   
  char   buffer[256];   
  sprintf(buffer,   "%......",   args,   ...);   //   ...   部分省略许多细节   
  CString   s   =   buffer;   
  虽然更好的形式可以这么做:   
   
  CString   s;   
  s.Format(_T("%...."),   args,   ...);   
  如果你的字符串长度万一超过   256   个字符的时候,不会破坏堆栈。   
   
    另外一个常见的错误是:既然固定大小的内存不工作,那么就采用动态分配字节,这种做法弊端更大:   
   
  int   len   =   lstrlen(parm1)   +   13   lstrlen(parm2)   +   10   +   100;   
   
  char   *   buffer   =   new   char[len];   
   
  sprintf(buffer,   "%s   is   equal   to   %s,   valid   data",   parm1,   parm2);   
   
  CString   s   =   buffer;   
   
  ......   
   
  delete   []   buffer;   
  它可以能被简单地写成:   
   
  CString   s;   
   
  s.Format(_T("%s   is   equal   to   %s,   valid   data"),   parm1,   parm2);   
    需要注意   sprintf   例子都不是   Unicode   就绪的,尽管你可以使用   tsprintf   以及用   _T()   来包围格式化字符串,但是基本   思路仍然是在走弯路,这这样很容易出错。
因为梦想而努力,因为有你而精彩!
mail: qianzongming@gmail.com

TOP

LPTSTR     是   wchar_t   类型的指针~~~   
  而   LPSTR   是   char   类型的指针~~~   
  不一样哦~~~~   
   
  而   wchar_t   通常定义为   unsigned   short   
   
  所以   char   为一个字节   ~~~   wchar_t   为两个字节~~   
   
  当   wchar_t   的低八位为   0   是~~   你就接受到   第一个   char   了~~
因为梦想而努力,因为有你而精彩!
mail: qianzongming@gmail.com

TOP

How to convert from LPTSTR into CHAR[] in VC6++
Asked by iphone in C++ Programming Language
Tags: convert, lptstr, char
Hi,
Im using VC6++ and need to convert from LPTSTR into CHAR[]
I tried this but doesnt work:

LPTSTR target;
char cTarget[50];
strcpy(cTarget, target);

it say this error:
error C2664: 'strcpy' : cannot convert parameter 2 from 'unsigned short *' to 'const char *'
因为梦想而努力,因为有你而精彩!
mail: qianzongming@gmail.com

TOP

回复 4# 的帖子

First thing LPTSTR target; is a pointer. So it has to point something.
Second LPTSTR points to 16bit array (unsigned short) on the contrary char * points to 8bit array

Why are you going to use LPTSTR?
因为梦想而努力,因为有你而精彩!
mail: qianzongming@gmail.com

TOP

回复 4# 的帖子

The following link can help you to understand:

http://msdn2.microsoft.com/en-us/library/ms776419.aspx
因为梦想而努力,因为有你而精彩!
mail: qianzongming@gmail.com

TOP

Depending how you compile your program, LPTSTR can either be Unicode or ANSI string. (wchar_t* or char*).
I recommend making an overloaded wrapper function.
Example:
#include <string.h>
#include <string>
#include <locale>
#include <algorithm>
#include <functional>
#include <vector>
#include <sstream>

      template<class T>
            std::string ToStr(const T &Data)
      {
            std::ostringstream ss;
            ss << Data;
            return ss.str();
      }

      inline std::string ToStr(wchar_t *Data)
      {
            const size_t SizeDest = wcslen(Data);
            std::vector<char>AnsiStr(SizeDest+1);
            wcstombs(&AnsiStr[0], Data, SizeDest);
            AnsiStr[SizeDest] = 0;
            return ToStr(&AnsiStr[0]);
      }

      inline char*  StrCpyT(char*  lpString1,const char*  lpString2){
            return strcpy(lpString1, lpString2);
      }

      inline char*  StrCpyT(char*  lpString1,const wchar_t*  lpString2){
            return strcpy(lpString1, ToStr(lpString2).c_str());
      }

You can then use the following in your code, which will work in both UNICODE and ANSI build programs:
LPTSTR target = _T("Hello World");
char cTarget[50];
StrCpyT(cTarget, target);
因为梦想而努力,因为有你而精彩!
mail: qianzongming@gmail.com

TOP

to take care of either UNICODE or ansi, this would be much easier.

inline void copy_to_cstr( const wchar_t* lptstr, char* dest, size_t N )
{ wcstombs( dest, lpstr, N ) ; }
inline void copy_to_cstr( const char* lptstr, char* dest, size_t N )
{ strcpy( dest, lpstr ) ; }

LPTSTR target = _T("Hello World");
char cTarget[50];
copy_to_cstr( target, cTarget, sizeof(cTarget) );
因为梦想而努力,因为有你而精彩!
mail: qianzongming@gmail.com

TOP

>>to take care of either UNICODE or ansi, this would be much easier.

That's true.

The code I posted, was copied and pasted from a set of existing library functions, that had more complicated functionalities.
The ToStr function already existed, so it was easier to reuse it.
因为梦想而努力,因为有你而精彩!
mail: qianzongming@gmail.com

TOP

LPTSTR是一个宏,定义UNICODE宏时就是LPWSTR,没有定义UNICODE宏时就是LPSTR,LPSTR就是char*,LPWSTR可以通过WideCharToMultiByte转换成char*
建议不要混用C++类型和Windows类型,虽然本质上Windows类型都是一些宏,但是混合使用容易出错

TOP

 19 12
发新话题