Zh/String: Difference between revisions
HouJunhao33 (talk | contribs) No edit summary |
m (Multipage removal) |
||
(13 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
{{ | {{LanguageBar|title = 字符串}} | ||
| | |||
}} | |||
{{toc-right}} | {{toc-right}} | ||
[[W:Array data structure|数组]]中的 {{ent|char}}([[W:ASCII|ASCII]])或 {{ent|wchar_t}}([[W:Unicode|Unicode]])常用于存储文本。这些缓冲区有一个特殊的术语:'''[[W:String (computer science)|字符串]]'''。它们很重要,但也很复杂。 | |||
== | == C 字符串或[https://en.cppreference.com/w/cpp/string/byte 空终止字节字符串]== | ||
''' | '''一个字符串总是比它看起来的要大一个字符。额外的项目是空终止符(二进制零,表示为 <code>\0</code>)。''' 这是必需的,因为通常传递的是指向字符串的 {{L|pointer}},而不是数组本身。 | ||
{{warning|指针不包含字符串长度的数据。}} | |||
没有终止符,将无法确定字符串在哪里结束以及下一个变量或未分配的内存从何开始。这就是[[W:buffer overflow|缓冲区溢出]],而这些是坏消息! | |||
{{tip| | {{tip|空终止符不需要是数组中的最后一个项目。它后面的字节将被字符串处理函数忽略。}} | ||
== | == 从字符串文字创建 == | ||
<source lang=cpp> | <source lang=cpp> | ||
char* MyString = "Hello world"; // | char* MyString = "Hello world"; // 必须分配给指针! | ||
</source> | </source> | ||
这段代码从一个[[W:string literal|字符串字面量]]创建一个字符串。双引号是特殊的语法,它们从其内容生成一个 <code>char</code> 数组。因此,上面的代码: | |||
# | # 分配了12字节的内存,存储字符串的任意位置。这是每个字符一个字节,加上一个自动的第12个字节用于空终止符。 | ||
# | # 创建一个本地的 <code>char</code> {{L|pointer}},其中包含第一个字符的地址(在本例中为 H)。 | ||
字符串字面量通常与 <code>[[W:const|const]]</code> 变量一起使用。这是因为字符串字面量将在进程的整个生命周期中保留在内存中。 | |||
{{note| | {{note|如果你在 Visual Studio 调试器中检查 <code>MyString</code>,你会看到整个字符串。这是为了使检查字符串更容易而采取的特殊行为;严格来说,它应该只显示指针(即第一个字符,H)。}} | ||
== | == 按大小创建 == | ||
<source lang=cpp> | <source lang=cpp> | ||
char MyString[12]; // | char MyString[12]; // 只接受静态大小 | ||
int StringLen = 12; | int StringLen = 12; | ||
char* pMyString = new char[StringLen]; // | char* pMyString = new char[StringLen]; // 接受可变大小 | ||
delete[] pMyString; // | delete[] pMyString; // 使用完 'new' 创建的任何东西后始终删除 / delete[] | ||
</source> | </source> | ||
这段代码同时分配了两个12字节的字符串,但并没有向它们写入任何内容(因此它们的内容要么是空白的,要么是无意义的)。它们需要被赋值,最好使用像 <code>strcpy()</code> 或 <code>sprintf()</code> 这样的字符串函数。 | |||
它们之间的区别在于,一个在函数的内存空间中创建一个数组,而另一个在函数中创建一个指针,并使用 <code>[[W:new (C++)|new]]</code> 在其他地方分配字符串本身。使用 <code>new</code> 的优点是可以在运行时确定大小,但缺点是如果不仔细调用 <code>[[W:delete (C++)|delete]]</code>(或对于数组是 <code>delete[]</code>)你将遭受[[W:memory leak|内存泄漏]]。 | |||
== Unicode | == Unicode 字符串 == | ||
{{note| | {{note|源代码内部是 ASCII。只有当你深入了解{{L|VGUI}}的内部工作时,你才会处理 Unicode。}} | ||
[[W:Unicode|Unicode]] | [[W:Unicode|Unicode]] 字符串的行为与 ASCII 字符串类似,但是它们是 <code>{{L|wchar_t}}</code> 的数组。它们由自己的一组字符串函数操作,通常名称中包含 'wc' 或 'wcs'(宽字符字符串)。 | ||
<source lang=cpp> | <source lang=cpp> | ||
Line 55: | Line 54: | ||
</source> | </source> | ||
<code>L</code> 标记字符串字面量为 Unicode。即使字符全部兼容 ASCII,你也需要这样做。 | |||
== 字符串函数 == | |||
[ | 有许多函数处理字符串,其中最常见的 ASCII 变体具有 Source 特定的 <code>V_*</code> 等效项。请参阅[http://msdn.microsoft.com/en-us/library/f0151s4x.aspx MSDN]获取相当全面的列表,或者在 VS 的类视图中搜索“V_str”。 | ||
{{ACategory|C++}} | |||
{{ACategory|Variables}} |
Latest revision as of 11:18, 12 July 2024
数组中的 char(ASCII)或 wchar_t(Unicode)常用于存储文本。这些缓冲区有一个特殊的术语:字符串。它们很重要,但也很复杂。
C 字符串或空终止字节字符串
一个字符串总是比它看起来的要大一个字符。额外的项目是空终止符(二进制零,表示为 \0
)。 这是必需的,因为通常传递的是指向字符串的 pointer ,而不是数组本身。

没有终止符,将无法确定字符串在哪里结束以及下一个变量或未分配的内存从何开始。这就是缓冲区溢出,而这些是坏消息!

从字符串文字创建
char* MyString = "Hello world"; // 必须分配给指针!
这段代码从一个字符串字面量创建一个字符串。双引号是特殊的语法,它们从其内容生成一个 char
数组。因此,上面的代码:
- 分配了12字节的内存,存储字符串的任意位置。这是每个字符一个字节,加上一个自动的第12个字节用于空终止符。
- 创建一个本地的
char
pointer ,其中包含第一个字符的地址(在本例中为 H)。
字符串字面量通常与 const
变量一起使用。这是因为字符串字面量将在进程的整个生命周期中保留在内存中。

MyString
,你会看到整个字符串。这是为了使检查字符串更容易而采取的特殊行为;严格来说,它应该只显示指针(即第一个字符,H)。按大小创建
char MyString[12]; // 只接受静态大小
int StringLen = 12;
char* pMyString = new char[StringLen]; // 接受可变大小
delete[] pMyString; // 使用完 'new' 创建的任何东西后始终删除 / delete[]
这段代码同时分配了两个12字节的字符串,但并没有向它们写入任何内容(因此它们的内容要么是空白的,要么是无意义的)。它们需要被赋值,最好使用像 strcpy()
或 sprintf()
这样的字符串函数。
它们之间的区别在于,一个在函数的内存空间中创建一个数组,而另一个在函数中创建一个指针,并使用 new
在其他地方分配字符串本身。使用 new
的优点是可以在运行时确定大小,但缺点是如果不仔细调用 delete
(或对于数组是 delete[]
)你将遭受内存泄漏。
Unicode 字符串

Unicode 字符串的行为与 ASCII 字符串类似,但是它们是 wchar_t
的数组。它们由自己的一组字符串函数操作,通常名称中包含 'wc' 或 'wcs'(宽字符字符串)。
wchar_t* MyWideString = L"Здравей свят";
L
标记字符串字面量为 Unicode。即使字符全部兼容 ASCII,你也需要这样做。
字符串函数
有许多函数处理字符串,其中最常见的 ASCII 变体具有 Source 特定的 V_*
等效项。请参阅MSDN获取相当全面的列表,或者在 VS 的类视图中搜索“V_str”。