wchar_t获取长度的有关问题
wchar_t获取长度的问题
在vs2010 unicode 模式下 想获取一个wchar_t字符串占用几个字节
比如英文、数字、一些符号如:半角逗号等 占一个 字节。汉字 还有符号像全角逗号占等 2个字节
代码如下
方法一:直接获取长度
方法二:转换char在获取长度
两种方式获取字符串长度都是5,而不是7.请问要怎么获取字节长度呢
------解决思路----------------------
windows下wchar_t是使用UTF-16(UCS2)编码, 占2字节.
一般一个Unicode字符占用两字节(包括英文), 少数(编码大于0xFFFF)占用4字节.
获取字节占用长度 = sizeof(wchar_t) * (wcslen(str) + 1), 加不加1看情况.
"2ss你好"在UTF-16下占用14字节(包括null结尾字符),
"2ss你好"在UTF-8下占用10字节(包括null结尾字符),
"2ss你好"在GBK下占用8字节(包括null结尾字符),
------解决思路----------------------
输出:
------解决思路----------------------
------解决思路----------------------
理解和讨论之前请先学会如何观察!
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……
对学习编程者的忠告:
多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程!
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步Debug版对应汇编一行!
单步Debug版对应汇编千行不如单步Release版对应汇编一行!
VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
仅供参考:
在vs2010 unicode 模式下 想获取一个wchar_t字符串占用几个字节
比如英文、数字、一些符号如:半角逗号等 占一个 字节。汉字 还有符号像全角逗号占等 2个字节
代码如下
方法一:直接获取长度
wchar_t *myChar;
myChar=L"2ss你好";
int lenChar=wcslen(myChar);
方法二:转换char在获取长度
char szEdit[20] = {0};
char *p = NULL;
USES_CONVERSION;
p = W2A(myChar);
strcpy(szEdit,p);
int nLen = strlen(szEdit);
两种方式获取字符串长度都是5,而不是7.请问要怎么获取字节长度呢
------解决思路----------------------
windows下wchar_t是使用UTF-16(UCS2)编码, 占2字节.
一般一个Unicode字符占用两字节(包括英文), 少数(编码大于0xFFFF)占用4字节.
获取字节占用长度 = sizeof(wchar_t) * (wcslen(str) + 1), 加不加1看情况.
"2ss你好"在UTF-16下占用14字节(包括null结尾字符),
"2ss你好"在UTF-8下占用10字节(包括null结尾字符),
"2ss你好"在GBK下占用8字节(包括null结尾字符),
------解决思路----------------------
#include<iostream>
using namespace std;
int main()
{
cout<<"Narrow multibyte string:"<<sizeof "2ss你好"<<endl;
cout<<"Wide string:"<<sizeof L"2ss你好"<<endl;
cout<<"UTF-8 encoded string:"<<sizeof u8"2ss你好"<<endl;
cout<<"UTF-16 encoded string:"<<sizeof u"2ss你好"<<endl;
cout<<"UTF-32 encoded string:"<<sizeof U"2ss你好"<<endl;
return 0;
}
输出:
Narrow multibyte string:8
Wide string:12
UTF-8 encoded string:10
UTF-16 encoded string:12
UTF-32 encoded string:24
------解决思路----------------------
#include <AtlBase.h>
#include <iostream>
int main ()
{
wchar_t *myChar;
myChar=L"2ss你好";
USES_CONVERSION;
std::cout << strlen(W2A(myChar)) << std::endl; //7
}
------解决思路----------------------
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……
对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步Debug版对应汇编一行!
单步Debug版对应汇编千行不如单步Release版对应汇编一行!
VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
仅供参考:
#pragma comment(lib,"user32")
#pragma comment(lib,"gdi32")
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
extern "C" HWND WINAPI GetConsoleWindow();
void HideTheCursor() {
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {
cciCursor.bVisible = FALSE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
void ShowTheCursor() {
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {
cciCursor.bVisible = TRUE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}
int main() {
HWND hwnd;
HDC hdc;
HFONT hfont;
wchar_t wc[2];
system("color F0");
system("cls");
HideTheCursor();
hwnd = GetConsoleWindow();
hdc = GetDC(hwnd);
hfont = CreateFont(48,0,0,0,0,0,0,0,GB2312_CHARSET ,0,0,0,0,"宋体-方正超大字符集");
SelectObject(hdc,hfont);
wc[0]=0xD854u;
wc[1]=0xDC00u;
TextOutW(hdc,10,10,wc,2);
DeleteObject(hfont);
ReleaseDC(hwnd,hdc);
getch();
system("color 07");
system("cls");
ShowTheCursor();
return 0;
}
#if 0
代理项或代理项对是一对共同表示单个字符的 16 位 Unicode 编码值。需要记住的关键一点是:
代理项对实际上是 32 位单个字符,不能再假定一个 16 位 Unicode 编码值正好映射到一个字符。
使用代理项对
代理项对的第一个值是高代理项,包含介于 U+D800 到 U+DBFF 范围内的 16 位代码值。
该对的第二个值是低代理项,包含介于 U+DC00 到 U+DFFF 范围内的值。通过使用代理项对,
16 位 Unicode 编码系统可以对已由 Unicode 标准定义的一百多万个其他字符 (220) 进行寻址。
在传递给 XmlTextWriter 方法的任何字符串中都可以使用代理项字符。不过,代理项字符在编写的
XML 中应该有效。例如,万维网联合会 (W3C) 建议不允许在元素或属性的名称中使用代理项字符。
如果字符串包含无效的代理项对,则引发异常。
另外,可以使用 WriteSurrogateCharEntity 写出与代理项对相对应的字符实体。字符实体以十六
进制格式写出,并用以下公式生成:
(highChar -0xD800) * 0x400 + (lowChar -0xDC00) + 0x10000
如果字符串包含无效的代理项对,则引发异常。下面的示例显示将代理项对作为输入的 WriteSurrogateCharEntity 方法。
C#复制
// The following line writes 𐀀.
WriteSurrogateCharEntity ('\uDC00', '\uD800');
下面的示例生成一个代理项对文件,将其加载到 XmlReader 中,并用新的文件名保存文件。
然后,原始文件和新文件被加载回应用程序的 XML 文档对象模型 (DOM) 结构中以进行比较。
C#复制
char lowChar, highChar;
char [] charArray = new char[10];
FileStream targetFile = new FileStream("SurrogatePair.xml",
FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
lowChar = Convert.ToChar(0xDC00);
highChar = Convert.ToChar(0xD800);
XmlTextWriter tw = new XmlTextWriter(targetFile, null);
tw.Formatting = Formatting.Indented;
tw.WriteStartElement("root");
tw.WriteStartAttribute("test", null);
tw.WriteSurrogateCharEntity(lowChar, highChar);
lowChar = Convert.ToChar(0xDC01);
highChar = Convert.ToChar(0xD801);
tw.WriteSurrogateCharEntity(lowChar, highChar);
lowChar = Convert.ToChar(0xDFFF);
highChar = Convert.ToChar(0xDBFF);
tw.WriteSurrogateCharEntity(lowChar, highChar);
// Add 10 random surrogate pairs.
// As Unicode, the high bytes are in lower
// memory; for example, word 6A21 as 21 6A.
// The high or low is in the logical sense.
Random random = new Random();
for (int i = 0; i < 10; ++i) {
lowChar = Convert.ToChar(random.Next(0xDC00, 0xE000));
highChar = Convert.ToChar(random.Next(0xD800, 0xDC00));
charArray[i] = highChar;
charArray[++i] = lowChar;
}
tw.WriteChars(charArray, 0, charArray.Length);
for (int i = 0; i < 10; ++i) {
lowChar = Convert.ToChar(random.Next(0xDC00, 0xE000));
highChar = Convert.ToChar(random.Next(0xD800, 0xDC00));
tw.WriteSurrogateCharEntity(lowChar, highChar);
}
tw.WriteEndAttribute();
tw.WriteEndElement();
tw.Flush();
tw.Close();
XmlTextReader r = new XmlTextReader("SurrogatePair.xml");
r.Read();
r.MoveToFirstAttribute();
targetFile = new FileStream("SurrogatePairFromReader.xml",
FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
tw = new XmlTextWriter(targetFile, null);
tw.Formatting = Formatting.Indented;
tw.WriteStartElement("root");
tw.WriteStartAttribute("test", null);
tw.WriteString(r.Value);
tw.WriteEndAttribute();
tw.WriteEndElement();
tw.Flush();
tw.Close();
// Load both result files into the DOM and compare.
XmlDocument doc1 = new XmlDocument();
XmlDocument doc2 = new XmlDocument();
doc1.Load("SurrogatePair.xml");
doc2.Load("SurrogatePairFromReader.xml");
if (doc1.InnerXml != doc2.InnerXml) {
Console.WriteLine("Surrogate Pair test case failed");
}
在使用 WriteChars 方法(一次写出一个缓冲区的数据)写出时,输入中的代理项对可能
会在一个缓冲区内被意外拆分。由于代理项值是定义完善的,如果 WriteChars 遇到来自
较低范围或者较高范围的 Unicode 值,它将该值标识为代理项对的一半。当遇到
WriteChars 将导致从拆分代理项对的缓冲区写入的情况时,将引发异常。使用
IsHighSurrogate 方法检查缓冲区是否以高代理项字符结束。如果缓冲区中的最后一个
字符不是高代理项,可以将该缓冲区传递给 WriteChars 方法。
请参见
概念
使用 XmlTextWriter 创建格式正确的 XML
XmlTextWriter 的 XML 输出格式设置
XmlTextWriter 的命名空间功能
#endif