CSDN-CSDN社区-C/C++-C++ 语言

收藏 标准C++中,如何获取std::wstring定义的字符串的字节数[问题点数:80]

  • htty326
  • 等 级:
  • 结帖率:
楼主发表于:2009-07-02 16:07:11
请问在标准C++中,如何获取std::wstring定义的字符串的字节数?该字符串类中的length()函数只能获取字符串中所包含的字符数,比如:
        std::wstring wstrData =  L"";

wstrData = L"6564我们的国家";
std::wcout < < wstrData.length() < <std::endl;

程序的输出结果为:9,而将该字符串写入到文件中,该字符串其实有20个字节。

请问VS2008中的宽字节字符集所使用的是哪个版本的Unicode标准呀?是UTF-8嘛?
请大家不吝赐教,非常感谢!
回复次数:72
  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#1楼 得分:0回复于:2009-07-02 16:08:24
VS2008使用的是UTF-16
  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#2楼 得分:0回复于:2009-07-02 16:09:23
wstrData = L"6564我们的国家";
6565共4字节
每个汉字两个字节,所以14字节
#3楼 得分:0回复于:2009-07-02 16:20:44
引用楼主 htty326 的帖子:
请问在标准C++中,如何获取std::wstring定义的字符串的字节数?该字符串类中的length()函数只能获取字符串中所包含的字符数,比如:
        std::wstring wstrData =  L"";

wstrData = L"6564我们的国家";
std::wcout < < wstrData.length() < <std::endl;

程序的输出结果为:9,而将该字符串写入到文件中,该字符串其实有14个字节。

请问VS2008中的宽字节字符集所使用的是哪个版本的Unicode标准呀?是UTF-8嘛?…


wstrData.length()这里返回的是宽字符的个数。一个数字或者汉字都认为是一个宽字符。
而你说的14字节是ANSCII之类的变长码。数字占一字节,汉字2字节。


http://blog.csdn.net/hairetz/archive/2009/05/18/4198191.aspx

#4楼 得分:0回复于:2009-07-02 17:01:38
C/C++ code
wstrData = L"6564我们的国家"; setlocale(LC_ALL, "Chinese-simplified"); int requiredSize = wcstombs( NULL, wstrData.c_str(), 0); std::wcout << requiredSize <<std::endl;
#5楼 得分:0回复于:2009-07-02 17:26:49
引用 3 楼 hairetz 的回复:

wstrData.length()这里返回的是宽字符的个数。一个数字或者汉字都认为是一个宽字符。
而你说的14字节是ANSCII之类的变长码。数字占一字节,汉字2字节。


嗯,学习了。。。。。
#6楼 得分:0回复于:2009-07-02 18:40:20
引用 3 楼 hairetz 的回复:
引用楼主 htty326 的帖子:
请问在标准C++中,如何获取std::wstring定义的字符串的字节数?该字符串类中的length()函数只能获取字符串中所包含的字符数,比如:
std::wstring wstrData =  L"";

wstrData = L"6564我们的国家";
std::wcout  <  < wstrData.length()  <  <std::endl;

程序的输出结果为:9,而将该字符串写入到文件中,该字符串其实有14个字节。

请问VS2008中的宽字节字符集所使用的是哪个版本的Unicode标…


其实UNICODE与UTF-16应该是等价的.
#7楼 得分:0回复于:2009-07-02 18:45:53
引用 3 楼 hairetz 的回复:
引用楼主 htty326 的帖子:
请问在标准C++中,如何获取std::wstring定义的字符串的字节数?该字符串类中的length()函数只能获取字符串中所包含的字符数,比如:
        std::wstring wstrData =  L"";

wstrData = L"6564我们的国家";
std::wcout < < wstrData.length() < <std::endl;

程序的输出结果为:9,而将该字符串写入到文件中,该字符串其实有14个字节。

请问VS2008中的宽字节字符集所使用的是哪个版本的…


支持!!看一下占字节数,定义一数组长度,
#8楼 得分:0回复于:2009-07-02 19:20:51
引用 2 楼 Loaden 的回复:
wstrData = L"6564我们的国家";
6565共4字节
每个汉字两个字节,所以14字节

用ANSCII之类的变长码来人为的考虑,这个宽字符串的长度是不对的,因为宽字符串的每个字符都是宽字符,占2个字节,而且还要包括结尾符'\0',所以这个字符串应该占20个字节.
C/C++ code
#include <iostream> #include <string.h> using namespace std; int main() { cout<<sizeof L"6564我们的国家"; return 0; }

程序运行结果:
20
Process returned 0 (0x0)  execution time : 0.031 s
Press any key to continue.
  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#9楼 得分:0回复于:2009-07-03 08:20:11
引用 8 楼 Walf_ghoul 的回复:
引用 2 楼 Loaden 的回复:
wstrData = L"6564我们的国家"; 
6565共4字节 
每个汉字两个字节,所以14字节
 
用ANSCII之类的变长码来人为的考虑,这个宽字符串的长度是不对的,因为宽字符串的每个字符都是宽字符,占2个字节,而且还要包括结尾符'\0',所以这个字符串应该占20个字节.
C/C++ code
#include <iostream>
#include <string.h>
using namespace std;

int main()
{
    cout < <sizeof L"6564我们的国家"…


哦,忘了,不管是英文字母,还是汉字,都占两个字节。
但:奇怪的输出结果,谁能解释一下呢?
C/C++ code
#include <iostream> #include <string> using namespace std; int main() { wstring s1(L"6564我们的国家"); cout << sizeof(L"6564我们的国家") << endl; cout << sizeof(s1) << endl; s1.reserve(28); cout << sizeof(L"6564我们的国家") << endl; s1.reserve(10); cout << sizeof(L"6564我们的国家") << endl; return 0; }

输出结果:
20
28
20
20

Process returned 0 (0x0)  execution time : 0.031 s
Press any key to continue.

第一次输出20很正常,第二次为什么输出28?而第三次却又输出20?即使改成s1.reserve(10);,仍然输出20??
#10楼 得分:0回复于:2009-07-03 08:39:58
关注
#11楼 得分:0回复于:2009-07-03 08:43:28
hao
  • taodm用户头像
  • taodm
  • (taodm(不能处理站内信))
  • 等 级:
  • 5

    3

#12楼 得分:0回复于:2009-07-03 08:51:14
老邓还没睡醒吧?
  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#13楼 得分:0回复于:2009-07-03 08:52:57
引用 12 楼 taodm 的回复:
老邓还没睡醒吧?

解释一下9楼,想不通。
#14楼 得分:0回复于:2009-07-03 08:55:50
需要设置下平台,才可以显示出来,以前做过忘记具体怎么设定了
  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#18楼 得分:0回复于:2009-07-03 08:59:29
引用 13 楼 Loaden 的回复:
引用 12 楼 taodm 的回复:
老邓还没睡醒吧?
 
解释一下9楼,想不通。

晕了,代码写错了。
不过,写成这样,也解释不了运行结果:
C/C++ code
#include <iostream> #include <string> #include <locale> using namespace std; int main() { setlocale(LC_ALL, ""); wstring s1(L"6564我们的国家"); cout << sizeof(L"6564我们的国家") << endl; wcout << s1 << " : " << sizeof(s1) << endl; s1.reserve(28); wcout << s1 << " : " << sizeof(s1) << endl; s1.resize(1); wcout << s1 << " : " << sizeof(s1) << endl; return 0; }

运行结果:
20
6564我们的国家 : 28
6564我们的国家 : 28
6 : 28
#22楼 得分:0回复于:2009-07-03 09:03:12
唉,第一次,第三次,第四次都是 sizeof(L"6564我们的国家") ,当然都是 20
第二次是 sizeof(s1), s1 却是个 std::wstring , 这是与内部实现相关的,不管是多少都是合理的。
  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#23楼 得分:0回复于:2009-07-03 09:07:08
引用 22 楼 Vegertar 的回复:
唉,第一次,第三次,第四次都是 sizeof(L"6564我们的国家") ,当然都是 20
第二次是 sizeof(s1), s1 却是个 std::wstring , 这是与内部实现相关的,不管是多少都是合理的。

哦,改在18楼了,看来只能这样得大小了:
C/C++ code
wcout << s1 << " : " << s1.length() * sizeof(wchar_t) << endl;

想起来了。
#24楼 得分:0回复于:2009-07-03 09:12:09
看看,我也正需要呢,
#25楼 得分:0回复于:2009-07-03 09:12:32
reserve() 操作是非强制性的,为了获得最佳性能,容器可以增加容量,却可以永不缩减!
只有响应 reserve() 调用,容量才会减少。
看看标准:
After reserve(), capacity() is greater or equal to the argument of reserve. [Note: Calling
reserve() with a res_arg argument less than capacity() is in effect a non-binding shrink
request. A call with res_arg <= size() is in effect a non-binding shrink-to-fit request.
—end note]
#26楼 得分:0回复于:2009-07-03 09:15:01
关注中.....
#28楼 得分:0回复于:2009-07-03 09:19:23
  一个字符集都有这么多学问啊~~
  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#29楼 得分:0回复于:2009-07-03 09:21:55
resize可以强制改变:
C/C++ code
#include <iostream> #include <string> #include <locale> using namespace std; int main() { setlocale(LC_ALL, ""); wstring s1(L"6564我们的国家"); wcout << s1 << " : " << s1.length() * sizeof(wchar_t) << endl; s1.resize(5); wcout << s1 << " : " << s1.length() * sizeof(wchar_t) << endl; return 0; }

输出:
6564我们的国家 : 18
6564我 : 10

有没有办法获得std::string对象实际占用的内存。
通过swap方法,可以将内存降至最少,但如何得到当前实例所占的内存呢?

#30楼 得分:0回复于:2009-07-03 09:24:19
unicode下都是用两个字节来表示的,而wstrData.length() 取到的也是unicode编码的长度:汉字五个,数字四个,一共是9个

但是你写入磁盘的时候也要注意编码,14个字节说明写进去不是unicode或者你写入的长度处理错误
你可以强行写入形如((char*)wstrData.c_str(),wstrData.size()*sizeof(wchar_t));
#31楼 得分:0回复于:2009-07-03 09:26:48
mark~
#32楼 得分:0回复于:2009-07-03 10:02:06
std::string之类的容器,它的内存开辟的长度和它的实际长度并不相等。一般来说它会开一个比较大的空间,以避免每增加一个字符就动态申请一次空间。
#33楼 得分:0回复于:2009-07-03 10:19:26
程序1:
std::wofstream OFile;
std::locale loc("chs");
        std::wstring wstrData =  L"";

wstrData = L"6564我们的国家";

        OFile.open(L"D:\\Unicode.txt",std::ios::out | std::ios::binary);
OFile.imbue(loc);
OFile.write(reinterpret_cast <const wchar_t*>(wstrData.c_str()),wstrData.length());
std::cout < <"The total written bytes is:" < < wstrData.length() < <std::endl;
OFile.close();

运行结果:The total written bytes is:9。打开文件后,文件内容为:"6564我们的国家"
查看了文件大小为:14字节。


程序2:
        std::wofstream OFile;
std::locale loc("chs");
        std::wstring wstrData =  L"";

wstrData = L"6564我们的国家";

        OFile.open(L"D:\\Unicode.txt",std::ios::out | std::ios::binary);
OFile.imbue(loc);
OFile.write(reinterpret_cast <const wchar_t*>(wstrData.c_str()),wstrData.length());
std::cout < <"The total written bytes is:" < < wstrData.length() < <std::endl;
OFile.close();
运行结果:The total written bytes is:9。打开文件后,文件内容为:"6564我们的国家 "
查看了文件大小为:15字节。用UltraEdit查看,程序2生成的文件比程序1生成文件多了一个字节:"00";
查看了wstrData在内存中的内容为:
36 00 35 00 36 00 34 00 11 62 ec 4e 84 76 fd 56 b6 5b 00 00
由此看来,该类写入文件内容用的还是多字节字符集,而并不是使用Unicode字符集,请问如何使用wofstream来写入Unicode字符串呢?
#34楼 得分:0回复于:2009-07-03 10:21:15
更正:程序2中的OFile.write(reinterpret_cast <const wchar_t*>(wstrData.c_str()),wstrData.length());
应为:OFile.write(reinterpret_cast <const wchar_t*>(wstrData.c_str()),wstrData.length()*2);
不好意思!
  • taodm用户头像
  • taodm
  • (taodm(不能处理站内信))
  • 等 级:
  • 5

    3

#35楼 得分:0回复于:2009-07-03 10:27:43
自己google “如何升级基于STL的应用来支持Unicode”会找到答案。

  • r_swordsman用户头像
  • r_swordsman
  • (取什么样的昵称才有个性又能显示)
  • 等 级:
#36楼 得分:0回复于:2009-07-03 10:36:38
引用 9 楼 Loaden 的回复:
引用 8 楼 Walf_ghoul 的回复:
引用 2 楼 Loaden 的回复:
wstrData = L"6564我们的国家"; 
6565共4字节 
每个汉字两个字节,所以14字节
 
用ANSCII之类的变长码来人为的考虑,这个宽字符串的长度是不对的,因为宽字符串的每个字符都是宽字符,占2个字节,而且还要包括结尾符'\0',所以这个字符串应该占20个字节.
C/C++ code
#include <iostream>
#include <string.h>
using namespace std;

int main()
{…



第一次输出20很正常,第二次为什么输出28?而第三次却又输出20?即使改成s1.reserve(10);,仍然输出20??
----------------------
你基础很不扎实啊

根据 wstring s1, 得出 wstring 是一个类,而 s1 是该类的实例
所以得出 sizeof(wstring) 等于 sizeof(s1) 恒等于 28(此值根据编译时类库版本而定)





  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#37楼 得分:0回复于:2009-07-03 10:39:06
引用 36 楼 r_swordsman 的回复:
引用 9 楼 Loaden 的回复:
引用 8 楼 Walf_ghoul 的回复:
引用 2 楼 Loaden 的回复: 
wstrData = L"6564我们的国家";  
6565共4字节  
每个汉字两个字节,所以14字节 
  
用ANSCII之类的变长码来人为的考虑,这个宽字符串的长度是不对的,因为宽字符串的每个字符都是宽字符,占2个字节,而且还要包括结尾符'\0',所以这个字符串应该占20个字节. 
C/C++ code 
#include  <iostream> 
#include  <string.h> 


面壁思过!一定要把C++ Primer看完!!
#38楼 得分:0回复于:2009-07-03 11:39:16
kankan
#39楼 得分:0回复于:2009-07-03 14:03:13
学习中
#40楼 得分:0回复于:2009-07-03 14:32:51
看看这个吧
#include <iostream>
#include <string.h>
using namespace std;

int main()
{
    cout < <sizeof L"6564我们的国家";
    return 0;
}


程序运行结果:
20
Process returned 0 (0x0)  execution time : 0.031 s
Press any key to continue.
#41楼 得分:0回复于:2009-07-03 15:38:55
学习了
#42楼 得分:0回复于:2009-07-03 15:41:42
输出字节啊
#43楼 得分:0回复于:2009-07-03 15:46:50
来学习一下
#44楼 得分:0回复于:2009-07-03 16:17:11
领悟中
#45楼 得分:0回复于:2009-07-03 16:31:07
哎,进来面壁了。
#46楼 得分:0回复于:2009-07-03 16:57:49
lz 错了, 应该是18个有效字节, 另外两个字节是0, 因为是按宽字节存的
所以, 要获取该字符串实际占用内存字节数很简单, length()乘以2就可以了
#47楼 得分:0回复于:2009-07-03 20:20:52
看看,学习学习。
#48楼 得分:0回复于:2009-07-03 20:50:02
#include <iostream>
#include <string.h>
using namespace std;

int main()
{
    cout < <sizeof L"6564我们的国家";
    return 0;
}


程序运行结果:
20
Process returned 0 (0x0)  execution time : 0.031 s
Press any key to continue.
就是 这样
#49楼 得分:0回复于:2009-07-03 21:07:59
来顶一下
#50楼 得分:0回复于:2009-07-03 21:16:06
学习
  • clever101用户头像
  • clever101
  • (好好学习,天天向上)
  • 等 级:
#51楼 得分:0回复于:2009-07-03 21:18:07
引用 18 楼 Loaden 的回复:
引用 13 楼 Loaden 的回复:
引用 12 楼 taodm 的回复:
老邓还没睡醒吧?
 
解释一下9楼,想不通。


晕了,代码写错了。
不过,写成这样,也解释不了运行结果:

C/C++ code#include <iostream>
#include <string>
#include <locale>

using namespace std;

int main()
{
    setlocale(LC_ALL, "");
   
    wstring s1(L"6564我们的国家");
   
    cout < < sizeof(L"6564我们的国家") < < endl…


    很奇怪啊,我运行上面的代码输出结果居然是下图:



    我的编译环境是
Win XP sp3, VS C++ 2005 + sp1
  • fldx用户头像
  • fldx
  • (迎接胜利)
  • 等 级:
#52楼 得分:0回复于:2009-07-03 21:50:00
回帖是一种美德!每天回帖即可获得 10 分可用分!
#53楼 得分:0回复于:2009-07-03 21:58:22
asdfdasdfsdfasdf
#54楼 得分:0回复于:2009-07-03 21:59:43
123123
#55楼 得分:0回复于:2009-07-03 22:20:06
支持一下!!
  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#56楼 得分:0回复于:2009-07-03 22:26:29
难道GCC的string效率低?
C/C++ code
#include <iostream> #include <string> using namespace std; class StringBase { protected: size_t _len; }; class WString : public StringBase { public: wchar_t* _p; size_t _size; }; int main(int argc, char **argv) { string s1; wstring s2; WString s3; cout << sizeof(s1) << endl; cout << sizeof(s2) << endl; cout << sizeof(s3) << endl; return 0; }

如代码所示,输出:
4
4
12

那不就说明,其实GCC的string和wstring实现,其数据成员都只有一个指针?或char*或wchar_t*,那用户在获取长度时怎么办?
总不能重新计算一下吧。
  • QQ_456用户头像
  • QQ_456
  • (QQ_456)
  • 等 级:
#57楼 得分:0回复于:2009-07-03 23:09:24
up
#58楼 得分:0回复于:2009-07-03 23:33:27
UP
#59楼 得分:0回复于:2009-07-03 23:44:54
看看。。。
  • djog用户头像
  • djog
  • (djog)
  • 等 级:
#60楼 得分:0回复于:2009-07-04 00:21:20
引用 23 楼 Loaden 的回复:
引用 22 楼 Vegertar 的回复:
唉,第一次,第三次,第四次都是 sizeof(L"6564我们的国家") ,当然都是 20
第二次是 sizeof(s1), s1 却是个 std::wstring , 这是与内部实现相关的,不管是多少都是合理的。


哦,改在18楼了,看来只能这样得大小了:

C/C++ codewcout < < s1 < < " : " < < s1.length() * sizeof(wchar_t) < < endl;


想起来了。



支持这方法
#61楼 得分:0回复于:2009-07-04 01:56:43
好呀,哈哈
#62楼 得分:0回复于:2009-07-04 07:52:41
学习
#63楼 得分:0回复于:2009-07-04 09:09:19
wstring获取字符数的标准方法是length或者size成员。
获取字节数个人感觉其实没有非常实用的意义,因为本身wstring就是一种抽象,让用户略存储细节,下面的程序
演示在64位linux下运行的结果。

C/C++ code
#include<iostream> #include<string> using namespace std; int main() { wstring ws; while(true) { getline(wcin, ws); if (!wcin || wcin.fail()) break; wcout<<ws<<L" has "<<ws.size()<<L" char(s) and need " <<ws.size() * sizeof(wstring::value_type) << L"bytes memory at least.\n"; } return 0; }


输出是:
XML code
one one has 3 char(s) and need 12bytes memory at least. two two has 3 char(s) and need 12bytes memory at least. three three has 5 char(s) and need 20bytes memory at least. four four has 4 char(s) and need 16bytes memory at least. ten ten has 3 char(s) and need 12bytes memory at least. hundred hundred has 7 char(s) and need 28bytes memory at least. thousand thousand has 8 char(s) and need 32bytes memory at least.

  • ytfsse用户头像
  • ytfsse
  • (无声的落幕)
  • 等 级:
#64楼 得分:0回复于:2009-07-04 10:18:54
不错,学习一下
#65楼 得分:0回复于:2009-07-04 10:38:19
支持一下
  • hiboys用户头像
  • hiboys
  • (上网拷代码为生计)
  • 等 级:
#66楼 得分:0回复于:2009-07-04 11:24:26
1. unicode编码是2字节,即使是英文字母和数字。
2. sizeof找\0来确定串的长度(没翻书,自己瞎想啊)
#67楼 得分:0回复于:2009-07-04 21:18:59
想知道一个wstring对象存储的内容的字节数很简单,
大体上字符数量乘以2就行了,想更保险的话,这样:

C/C++ code
wstring strTest(L"hello你好"); size_t szBytes = strTest.size() * sizeof(std::wstring::value_type) ;


但是我不清楚LZ这样做的目的是什么,说说你的目的,
或许能得到更多帮助。

另外,你了解VS2008的具体实现细节做什么呢?
依赖这些细节的话,虽然可能写出来令人惊异的东西,
但应该是及其不可移植的。
#68楼 得分:0回复于:2009-07-04 21:38:37
引用 23 楼 Loaden 的回复:
引用 22 楼 Vegertar 的回复:
唉,第一次,第三次,第四次都是 sizeof(L"6564我们的国家") ,当然都是 20
第二次是 sizeof(s1), s1 却是个 std::wstring , 这是与内部实现相关的,不管是多少都是合理的。


哦,改在18楼了,看来只能这样得大小了:

C/C++ codewcout < < s1 < < " : " < < s1.length() * sizeof(wchar_t) < < endl;


想起来了。


支持
#69楼 得分:0回复于:2009-07-04 21:44:57
vs2008可以设置所选用的字符集吧。
  • Loaden用户头像
  • Loaden
  • (老邓+宠辱不惊)
  • 等 级:
  • 2

#70楼 得分:0回复于:2009-07-04 22:17:19
引用 56 楼 Loaden 的回复:
难道GCC的string效率低?

谁能帮忙解决一下56楼?
#71楼 得分:0回复于:2009-07-04 23:16:50
本来挺清楚的,越看越晕~
  • clever101用户头像
  • clever101
  • (好好学习,天天向上)
  • 等 级:
#72楼 得分:0回复于:2009-07-05 10:03:33
引用 56 楼 Loaden 的回复:
难道GCC的string效率低?

C/C++ code#include <iostream>
#include <string>

using namespace std;

class StringBase
{
protected:
    size_t _len;
};

class WString : public StringBase
{
public:
    wchar_t* _p;
    size_t _size;
};

int main(int argc, char **argv)
{
    string s1;
    wstring s2;
    WString s3;

    cout < < sizeof(s1) < < endl;
    cout < < sizeof(s2) < < …


      上面代码的在VS C++ 2005 + sp1,unicode字符集编译的运行结果是: