关于字符串的相互转化问题(全)

 《第一部分》

CString ,BSTR ,LPCTSTR之间关系和区别

CString是一个动态TCHAR数组,BSTR是一种专有格式的字符串(需要用系统提供的函数来操纵,LPCTSTR只是一个常量的TCHAR指针。

CString 是一个完全独立的类,动态的TCHAR数组,封装了 + 等操作符和字符串操作方法。
typedef OLECHAR FAR* BSTR;
typedef const char * LPCTSTR;

vc++中各种字符串的表示法

首先char* 是指向ANSI字符数组的指针,其中每个字符占据8位(有效数据是除掉最高位的其他7位),这里保持了与传统的C,C++的兼容。

LP的含义是长指针(long pointer)。LPSTR是一个指向以‘\0’结尾的ANSI字符数组的指针,与char*可以互换使用,在win32中较多地使用LPSTR。
而LPCSTR中增加的‘C’的含义是“CONSTANT”(常量),表明这种数据类型的实例不能被使用它的API函数改变,除此之外,它与LPSTR是等同的。
1.LP表示长指针,在win16下有长指针(LP)和短指针(P)的区别,而在win32下是没有区别的,都是32位.所以这里的LP和P是等价的.
2.C表示const
3.T是什么东西呢,我们知道TCHAR在采用Unicode方式编译时是wchar_t,在普通时编译成char.

为了满足程序代码国际化的需要,业界推出了Unicode标准,它提供了一种简单和一致的表达字符串的方法,所有字符中的字节都是16位的值,其数量也可以满足差不多世界上所有书面语言字符的编码需求,开发程序时使用Unicode(类型为wchar_t)是一种被鼓励的做法。

LPWSTR与LPCWSTR由此产生,它们的含义类似于LPSTR与LPCSTR,只是字符数据是16位的wchar_t而不是char。

然后为了实现两种编码的通用,提出了TCHAR的定义:
如果定义_UNICODE,声明如下:
typedef wchar_t TCHAR;
如果没有定义_UNICODE,则声明如下:
typedef char TCHAR;

LPTSTR和LPCTSTR中的含义就是每个字符是这样的TCHAR。

CString类中的字符就是被声明为TCHAR类型的,它提供了一个封装好的类供用户方便地使用。

LPCTSTR:
#ifdef _UNICODE
typedef const wchar_t * LPCTSTR;
#else
typedef const char * LPCTSTR;
#endif

VC常用数据类型使用转换详解

先定义一些常见类型变量借以说明
int i = 100;
long l = 2001;
float f=300.2;
double d=12345.119;
char username[]="女侠程佩君";
char temp[200];
char *buf;
CString str;
_variant_t v1;
_bstr_t v2;

一、其它数据类型转换为字符串

短整型(int)
itoa(i,temp,10); //将i转换为字符串放入temp中,最后一个数字表示十进制
itoa(i,temp,2); //按二进制方式转换
长整型(long)
ltoa(l,temp,10);


二、从其它包含字符串的变量中获取指向该字符串的指针

CString变量
str = "2008北京奥运";
buf = (LPSTR)(LPCTSTR)str;
BSTR类型的_variant_t变量
v1 = (_bstr_t)"程序员";
buf = _com_util::ConvertBSTRToString((_bstr_t)v1);

三、字符串转换为其它数据类型
strcpy(temp,"123");

短整型(int)
i = atoi(temp);
长整型(long)
l = atol(temp);
浮点(double)
d = atof(temp);

四、其它数据类型转换到CString

使用CString的成员函数Format来转换,例如:

整数(int)
str.Format("%d",i);
浮点数(float)
str.Format("%f",i);
字符串指针(char *)等已经被CString构造函数支持的数据类型可以直接赋值
str = username;

五、BSTR、_bstr_t与CComBSTR

CComBSTR、_bstr_t是对BSTR的封装,BSTR是指向字符串的32位指针。
char *转换到BSTR可以这样: BSTR b=_com_util::ConvertStringToBSTR("数据"); //使用前需要加上头文件comutil.h
反之可以使用char *p=_com_util::ConvertBSTRToString(b);


六、VARIANT 、_variant_t 与 COleVariant

VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。
对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相同数据类型的变量赋值,举个例子:
VARIANT va;
int a=2001;
va.vt=VT_I4; //指明整型数据
va.lVal=a; //赋值

对于不马上赋值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系:

unsigned char bVal; VT_UI1
short iVal; VT_I2
long lVal; VT_I4
float fltVal; VT_R4
double dblVal; VT_R8
VARIANT_BOOL boolVal; VT_BOOL
SCODE scode; VT_ERROR
CY cyVal; VT_CY
DATE date; VT_DATE
BSTR bstrVal; VT_BSTR
IUnknown FAR* punkVal; VT_UNKNOWN
IDispatch FAR* pdispVal; VT_DISPATCH
SAFEARRAY FAR* parray; VT_ARRAY|*
unsigned char FAR* pbVal; VT_BYREF|VT_UI1
short FAR* piVal; VT_BYREF|VT_I2
long FAR* plVal; VT_BYREF|VT_I4
float FAR* pfltVal; VT_BYREF|VT_R4
double FAR* pdblVal; VT_BYREF|VT_R8
VARIANT_BOOL FAR* pboolVal; VT_BYREF|VT_BOOL
SCODE FAR* pscode; VT_BYREF|VT_ERROR
CY FAR* pcyVal; VT_BYREF|VT_CY
DATE FAR* pdate; VT_BYREF|VT_DATE
BSTR FAR* pbstrVal; VT_BYREF|VT_BSTR
IUnknown FAR* FAR* ppunkVal; VT_BYREF|VT_UNKNOWN
IDispatch FAR* FAR* ppdispVal; VT_BYREF|VT_DISPATCH
SAFEARRAY FAR* FAR* pparray; VT_ARRAY|*
VARIANT FAR* pvarVal; VT_BYREF|VT_VARIANT
void FAR* byref; VT_BYREF

_variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。
例如:
long l=222;
ing i=100;
_variant_t lVal(l);
lVal = (long)i;

COleVariant的使用与_variant_t的方法基本一样,请参考如下例子:
COleVariant v3 = "字符串", v4 = (long)1999;
CString str =(BSTR)v3.pbstrVal;
long i = v4.lVal;

七、其它

对消息的处理中我们经常需要将WPARAM或LPARAM等32位数据(DWORD)分解成两个16位数据(WORD),例如:
LPARAM lParam;
WORD loValue = LOWORD(lParam); //取低16位
WORD hiValue = HIWORD(lParam); //取高16位
对于16位的数据(WORD)我们可以用同样的方法分解成高低两个8位数据(BYTE),例如:
WORD wValue;
BYTE loValue = LOBYTE(wValue); //取低8位
BYTE hiValue = HIBYTE(wValue); //取高8位

如何将CString类型的变量赋给char*类型的变量
1、GetBuffer函数:
使用CString::GetBuffer函数。
char *p;
CString str="hello";
p=str.GetBuffer(str.GetLength());
str.ReleaseBuffer();

将CString转换成char * 时
CString str("aaaaaaa");
strcpy(str.GetBuffer(10),"aa");
str.ReleaseBuffer();
当我们需要字符数组时调用GetBuffer(int n),其中n为我们需要的字符数组的长度.使用完成后一定要马上调用ReleaseBuffer();
还有很重要的一点就是,在能使用const char *的地方,就不要使用char *

2、memcpy:
CString mCS=_T("cxl");
char mch[20];
memcpy(mch,mCS,20);

3、用LPCTSTR强制转换: 尽量不使用
char *ch;
CString str;
ch=(LPSTR)(LPCTSTR)str;

CString str = "good";
char *tmp;
sprintf(tmp,"%s",(LPTSTR)(LPCTSTR)str);

4、
CString Msg;
Msg=Msg+"abc";
LPTSTR lpsz;
lpsz = new TCHAR[Msg.GetLength()+1];
_tcscpy(lpsz, Msg);
char * psz;
strcpy(psz,lpsz);


CString类向const char *转换
char a[100];
CString str("aaaaaa");
strncpy(a,(LPCTSTR)str,sizeof(a));
或者如下:
strncpy(a,str,sizeof(a));
以上两种用法都是正确地. 因为strncpy的第二个参数类型为const char *.所以编译器会自动将CString类转换成const char *.

CString转LPCTSTR (const char *)
CString cStr;
const char *lpctStr=(LPCTSTR)cStr;

LPCTSTR转CString
LPCTSTR lpctStr;
CString cStr=lpctStr;

将char*类型的变量赋给CString型的变量
可以直接赋值,如:
CString myString = "This is a test";
也可以利用构造函数,如:
CString s1("Tom");

将CString类型的变量赋给char []类型(字符串)的变量
1、sprintf()函数
CString str = "good";
char tmp[200] ;
sprintf(tmp, "%s",(LPCSTR)str);
(LPCSTR)str这种强制转换相当于(LPTSTR)(LPCTSTR)str
CString类的变量需要转换为(char*)的时,使用(LPTSTR)(LPCTSTR)str

然而,LPCTSTR是const char *,也就是说,得到的字符串是不可写的!将其强制转换成LPTSTR去掉const,是极为危险的!
一不留神就会完蛋!要得到char *,应该用GetBuffer()或GetBufferSetLength(),用完后再调用ReleaseBuffer()。

2、strcpy()函数
CString str;
char c[256];
strcpy(c, str);

char mychar[1024];
CString source="Hello";
strcpy((char*)&mychar,(LPCTSTR)source);


关于CString的使用
1、指定 CString 形参
对于大多数需要字符串参数的函数,最好将函数原型中的形参指定为一个指向字符 (LPCTSTR) 而非 CString 的 const 指针。
当将形参指定为指向字符的 const 指针时,可将指针传递到 TCHAR 数组(如字符串 ["hi there"])或传递到 CString 对象。
CString 对象将自动转换成 LPCTSTR。任何能够使用 LPCTSTR 的地方也能够使用 CString 对象。

2、如果某个形参将不会被修改,则也将该参数指定为常数字符串引用(即 const CString&)。如果函数要修改该字符串,
则删除 const 修饰符。如果需要默认为空值,则将其初始化为空字符串 [""],如下所示:
void AddCustomer( const CString& name, const CString& address, const CString& comment = "" );

3、对于大多数函数结果,按值返回 CString 对象即可。


串的基本运算
对于串的基本运算,很多高级语言均提供了相应的运算符或标准的库函数来实现。
为叙述方便,先定义几个相关的变量:
char s1[20]="dir/bin/appl",s2[20]="file.asm",s3[30],*p;
int result;
下面以C语言中串运算介绍串的基本运算
1、求串长
int strlen(char *s); //求串s的长度
【例】printf("%d",strlen(s1)); //输出s1的串长12

2、串复制
char *strcpy(char *to,*from);//将from串复制到to串中,并返回to开始处指针
【例】strcpy(s3,s1); //s3="dir/bin/appl",s1串不变


3、联接
char *strcat(char *to,char *from);//将from串复制到to串的末尾,
//并返回to串开始处的指针
【例】strcat(s3,"/"); //s3="dir/bin/appl/"
strcat(s3,s2); //s3="dir/bin/appl/file.asm"

4、串比较
int strcmp(char *s1,char *s2);//比较s1和s2的大小,
//当s1<s2、s1>s2和s1=s2时,分别返回小于0、大于0和等于0的值
【例】result=strcmp("baker","Baker"); //result>0
result=strcmp("12","12"); //result=0
result=strcmp("Joe","joseph") //result<0

5、字符定位
char *strchr(char *s,char c);//找c在字符串s中第一次出现的位置,
//若找到,则返回该位置,否则返回NULL
【例】p=strchr(s2,'.'); //p指向"file"之后的位置
     if(p) strcpy(p,".cpp"); //s2="file.cpp"

注意:
 ①上述操作是最基本的,其中后 4个操作还有变种形式:strncpy,strncath和strnchr。
 ②其它的串操作见C的<string.h>。在不同的高级语言中,对串运算的种类及符号都不尽相同
 ③其余的串操作一般可由这些基本操作组合而成

【例】求子串的操作可如下实现:
void substr(char *sub,char *s,int pos,int len){
//s和sub是字符数组,用sub返回串s的第pos个字符起长度为len的子串
//其中0<=pos<=strlen(s)-1,且数组sub至少可容纳len+1个字符。
if (pos<0||pos>strlen(s)-1||len<0)
Error("parameter error!");
strncpy(sub,&s[pos],len); //从s[pos]起复制至多len个字符到sub

-------------------------------------------------------------------------------------------------------

《第二部分》

 wchar_t和wstring类型输出问题


请问怎么才能输出wchar_t和wstring类型的字符串,用cout输出不了,用wcout编译提示没这个东西.

DEV-C++环境.
#include<iostream>
#include<conio.h>
#include<string>

using namespace std;

int main()
{
  char s1[]="char";
  wchar_t s2[]=L"wchar_t"; 
//wstring ws=L"wstring";

  cout<<"s1="<<s1<<endl;
  cout<<"s2="<<s2<<endl;//输出的是个地址
//cout<<ws<<endl;      //编译提示错误
  
    
    getch();
    return 0;
}
 回复内容

【WinWing】:
wcout不是每个平台都支持的-_-

【jixingzhong】:
wcout  在 VC 环境下使用

【jixingzhong】:
wchar_t 使用对应的宽字符版本操作函数即可

【引用
比如求宽字符串长度的函数是
size_t __cdel wchlen(const wchar_t*);
  为什么要专门定义这些函数呢?最根本的原因是,ANSI下的字符串都是以’\0’来标识字符串尾的(Unicode字符串以“\0\0”结束),许多字符串函数的正确操作均是以此为基础进行。而我们知道,在宽字符的情况下,一个字符在内存中要占据一个字的空间,这就会使操作ANSI字符的字符串函数无法正确操作。以”Hello”字符串为例,在宽字符下,它的五个字符是:
0x0048 0x0065 0x006c 0x006c 0x006f
在内存中,实际的排列是:

48 00 65 00 6c 00 6c 00 6f 00
  于是,ANSI字符串函数,如strlen,在碰到第一个48后的00时,就会认为字符串到尾了,用strlen对宽字符串求长度的结果就永远会是1!


【jixingzhong】:
宽字符处理函数函数与普通函数对照表 
  
 

字符分类: 宽字符函数普通C函数描述 
iswalnum() isalnum() 测试字符是否为数字或字母 
iswalpha() isalpha() 测试字符是否是字母 
iswcntrl() iscntrl() 测试字符是否是控制符 
iswdigit() isdigit() 测试字符是否为数字 
iswgraph() isgraph() 测试字符是否是可见字符 
iswlower() islower() 测试字符是否是小写字符 
iswprint() isprint() 测试字符是否是可打印字符 
iswpunct() ispunct() 测试字符是否是标点符号 
iswspace() isspace() 测试字符是否是空白符号 
iswupper() isupper() 测试字符是否是大写字符 
iswxdigit() isxdigit()测试字符是否是十六进制的数字 


大小写转换: 
宽字符函数普通C函数描述 
towlower() tolower() 把字符转换为小写 
towupper() toupper() 把字符转换为大写 


字符比较: 宽字符函数普通C函数描述 
wcscoll() strcoll() 比较字符串 


日期和时间转换: 
宽字符函数描述 
strftime() 根据指定的字符串格式和locale设置格式化日期和时间 
wcsftime() 根据指定的字符串格式和locale设置格式化日期和时间, 并返回宽字符串 
strptime() 根据指定格式把字符串转换为时间值, 是strftime的反过程 


打印和扫描字符串: 
宽字符函数描述 
fprintf()/fwprintf() 使用vararg参量的格式化输出 
fscanf()/fwscanf() 格式化读入 
printf() 使用vararg参量的格式化输出到标准输出 
scanf() 从标准输入的格式化读入 
sprintf()/swprintf() 根据vararg参量表格式化成字符串 
sscanf() 以字符串作格式化读入 
vfprintf()/vfwprintf() 使用stdarg参量表格式化输出到文件 
vprintf() 使用stdarg参量表格式化输出到标准输出 
vsprintf()/vswprintf() 格式化stdarg参量表并写到字符串 


数字转换: 
宽字符函数普通C函数描述 
wcstod() strtod()  把宽字符的初始部分转换为双精度浮点数 
wcstol() strtol()  把宽字符的初始部分转换为长整数 
wcstoul() strtoul() 把宽字符的初始部分转换为无符号长整数 


多字节字符和宽字符转换及操作: 
宽字符函数描述 
mblen() 根据locale的设置确定字符的字节数 
mbstowcs() 把多字节字符串转换为宽字符串 
mbtowc()/btowc()把多字节字符转换为宽字符 
wcstombs() 把宽字符串转换为多字节字符串 
wctomb()/wctob() 把宽字符转换为多字节字符 


输入和输出: 
宽字符函数普通C函数描述 
fgetwc() fgetc() 从流中读入一个字符并转换为宽字符 
fgetws() fgets() 从流中读入一个字符串并转换为宽字符串 
fputwc() fputc() 把宽字符转换为多字节字符并且输出到标准输出 
fputws() fputs() 把宽字符串转换为多字节字符并且输出到标准输出串 
getwc() getc() 从标准输入中读取字符, 并且转换为宽字符 
getwchar() getchar() 从标准输入中读取字符, 并且转换为宽字符 
None gets() 使用fgetws() 
putwc() putc() 把宽字符转换成多字节字符并且写到标准输出 
putwchar() putchar() 把宽字符转换成多字节字符并且写到标准输出 
None puts() 使用fputws() 
ungetwc() ungetc() 把一个宽字符放回到输入流中 


字符串操作: 
宽字符函数普通C函数描述 
wcscat() strcat() 把一个字符串接到另一个字符串的尾部 
wcsncat() strncat() 类似于wcscat(), 而且指定粘接字符串的粘接长度. 
wcschr() strchr() 查找子字符串的第一个位置 
wcsrchr() strrchr() 从尾部开始查找子字符串出现的第一个位置 
wcspbrk() strpbrk() 从一字符字符串中查找另一字符串中任何一个字符第一次出现的位置 
wcswcs()/wcsstr() strchr() 在一字符串中查找另一字符串第一次出现的位置 
wcscspn() strcspn() 返回不包含第二个字符串的的初始数目 
wcsspn() strspn() 返回包含第二个字符串的初始数目 
wcscpy() strcpy() 拷贝字符串 
wcsncpy() strncpy() 类似于wcscpy(), 同时指定拷贝的数目 
wcscmp() strcmp() 比较两个宽字符串 
wcsncmp() strncmp() 类似于wcscmp(), 还要指定比较字符字符串的数目 
wcslen() strlen() 获得宽字符串的数目 
wcstok() strtok() 根据标示符把宽字符串分解成一系列字符串 
wcswidth() None 获得宽字符串的宽度 
wcwidth() None 获得宽字符的宽度 


另外还有对应于memory操作的 wmemcpy(), wmemchr(), wmemcmp(), wmemmove(), wmemset().

【todototry】:
mark

【zlbruce】:
from: http://blog.vckbase.com/bruceteen/archive/2005/11/15/14924.aspx
补充:在mingw32中使用wcout和wstring需要加一些宏,比如
#define _GLIBCXX_USE_WCHAR_T 1
#include <iostream>
int main( void )
{
    std::wcout << 1 << std::endl;
}
可以编译通过,但无法Link通过,在网上google了一下,stlport说mingw32有问题,mingw32说是M$的c runtime有问题。

 

string 转 CString
CString.format(”%s”, string.c_str());

 

char 转 CString
CString.format(”%s”, char*);

 

char 转 string
string s(char *);

 

string 转 char *
char *p = string.c_str();

 

CString 转 string
string s(CString. GetBuffer_r());
GetBuffer_r()后一定要ReleaseBuffer(),否则就没有释放缓冲区所占的空间.


CString/string互转int ,float

将字符转换为整数,可以使用atoi、_atoi64或atol。

而将数字转换为string变量,可以用itoa函数。

将数字转换为CString变量,可以使用CString的Format函数如:
CString s;
int i = 64;
s.Format(”%d”, i);

 

char*转换为CString类型

将char*转换成CString,可以直接赋值如:
CString strtest;
char * charpoint;
charpoint=”give string a value”;
strtest=charpoint;

 

还可使用CString::Format进行如:

 char chArray[] = "Char  test";
 TCHAR * p = _T("Char  test");( 或LPTSTR p = _T("Char  test");)
 CString theString = chArray;
 theString.Format(_T("%s"), chArray);
 theString = p;

 

CString转换成char*(LPSTR)类型,常常使用下列三种方法:

方法一,使用强制转换。例如:
 CString theString( (_T("Char test "));
 LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;

方法二,使用strcpy。例如:
 CString theString( (_T("Char test "));
LPTSTR lpsz = new TCHAR[theString. GetLength_r()+1];
strcpy(lpsz, theString);

另外:
CString 转换为char[]
CString转换 char[100]
char a[100];
CString str(”aaaaaa”);
strncpy(a,(LPCTSTR)str,sizeof(a));

需要说明的是,strcpy(或可移值的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。

方法三,使用CString::GetBuffer。
如果你需要修改 CString 中的内容,它有一个特殊的方法可以使用,那就是 GetBuffer,它的作用是返回一个可写的缓冲指针。如果你只是打算修改字符或者截短字符串,例如:
CString s(_T("Char test "));
 LPTSTR p = s. GetBuffer_r();
 LPTSTR dot = strchr(p, ''.'');
if(p != NULL)
 *p = _T('');
 s.ReleaseBuffer(); // 使用完后及时释放,以便能使用其它的CString成员函数
在 GetBuffer 和 ReleaseBuffer 之间这个范围,一定不能使用你要操作的这个缓冲的 CString 对象的任何方法。因为 ReleaseBuffer 被调用之前,该 CString 对象的完整性得不到保障

 

最后就是使用两个api函数 就那个MtoW()和WtoM()

一般情况下,字符串的转换问题就可以解决

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值