Zh/String: Difference between revisions

From Valve Developer Community
< Zh
Jump to navigation Jump to search
No edit summary
m (Multipage removal)
 
(13 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{otherlang2
{{LanguageBar|title = 字符串}}
|en=String
 
|de=String:de
}}
{{toc-right}}
{{toc-right}}


<code>[[char]]</code>([[W:ASCII|ASCII]])或 <code>[[wchar_t]]</code>([[W:Unicode|Unicode]])的[[W:Array data structure|数组]]被经常用来储存文本。这些缓冲区有特定的术语:''' [[W:String (computer science)|字符串]]''',或有时被称为“C语言式字符串”。它们很重要,但也比较复杂。
[[W:Array data structure|数组]]中的 {{ent|char}}([[W:ASCII|ASCII]])或 {{ent|wchar_t}}([[W:Unicode|Unicode]])常用于存储文本。这些缓冲区有一个特殊的术语:'''[[W:String (computer science)|字符串]]'''。它们很重要,但也很复杂。


== Null 终结符 ==
== C 字符串或[https://en.cppreference.com/w/cpp/string/byte 空终止字节字符串]==


'''字符串总是要比其文本内容多一个字符,这多的一个字符就是 null 终结符(二进制上的 0)。'''字符串需要终结符,是因为字符串经常用[[pointer|指针]]来传递,而指针并不像数组那样自带长度信息。
'''一个字符串总是比它看起来的要大一个字符。额外的项目是空终止符(二进制零,表示为 <code>\0</code>)。''' 这是必需的,因为通常传递的是指向字符串的 {{L|pointer}},而不是数组本身。
{{warning|指针不包含字符串长度的数据。}}


若没有终结符,就无法判断字符串结尾的位置。因此会读取到下一个变量或者是未分配内存的信息,这就造成了[[W:buffer overflow|缓冲区溢出]],大大滴坏!
没有终止符,将无法确定字符串在哪里结束以及下一个变量或未分配的内存从何开始。这就是[[W:buffer overflow|缓冲区溢出]],而这些是坏消息!


{{tip|Null 终结符不需要位于字符串最后,字符串处理函数会忽略掉 Null 终结符后的内容。}}
{{tip|空终止符不需要是数组中的最后一个项目。它后面的字节将被字符串处理函数忽略。}}


== 从字面量创建字符串 ==
== 从字符串文字创建 ==


<source lang=cpp>
<source lang=cpp>
char* MyString = "Hello world"; // 必须赋值给指针!
char* MyString = "Hello world"; // 必须分配给指针!
</source>
</source>


This code creates a string from a [[W:string literal|string literal]]. The double quote marks are special syntax which generate an array of <code>char</code> from their contents. The code above therefore:
这段代码从一个[[W:string literal|字符串字面量]]创建一个字符串。双引号是特殊的语法,它们从其内容生成一个 <code>char</code> 数组。因此,上面的代码:


# Assigns 12 bytes of memory, somewhere arbitrary, to store the string. This is one byte for each character, plus an automatic twelfth for the null terminator.
# 分配了12字节的内存,存储字符串的任意位置。这是每个字符一个字节,加上一个自动的第12个字节用于空终止符。
# Creates a local <code>char</code> [[pointer]] containing the address of the first character (H in this case).
# 创建一个本地的 <code>char</code> {{L|pointer}},其中包含第一个字符的地址(在本例中为 H)。


String literals are often handed with <code>[[W:const|const]]</code> variables. This is because a string literal will stay in memory for the process's whole lifespan.
字符串字面量通常与 <code>[[W:const|const]]</code> 变量一起使用。这是因为字符串字面量将在进程的整个生命周期中保留在内存中。


{{note|If you examine <code>MyString</code> in the Visual Studio debugger, you will see the entire string. This is special behaviour to make examining strings easier; strictly speaking it should just show you the pointee (i.e. the first character, H).}}
{{note|如果你在 Visual Studio 调试器中检查 <code>MyString</code>,你会看到整个字符串。这是为了使检查字符串更容易而采取的特殊行为;严格来说,它应该只显示指针(即第一个字符,H)。}}


== Creating by size ==
== 按大小创建 ==


<source lang=cpp>
<source lang=cpp>
char MyString[12]; // accepts a static size only
char MyString[12]; // 只接受静态大小


int StringLen = 12;
int StringLen = 12;
char* pMyString = new char[StringLen]; // accepts a variable size
char* pMyString = new char[StringLen]; // 接受可变大小


delete[] pMyString; // always delete / delete[] anything created with 'new' after use
delete[] pMyString; // 使用完 'new' 创建的任何东西后始终删除 / delete[]
</source>
</source>


This code both allocates two 12-byte strings, but does not write anything to them (so their contents will be either blank or gibberish). They need to be assigned to, ideally with a string function like <code>strcpy()</code> or <code>sprintf()</code>.
这段代码同时分配了两个12字节的字符串,但并没有向它们写入任何内容(因此它们的内容要么是空白的,要么是无意义的)。它们需要被赋值,最好使用像 <code>strcpy()</code> <code>sprintf()</code> 这样的字符串函数。


The difference between them is that one creates an array in the function's memory space, while the other creates a pointer in the function and uses <code>[[W:new (C++)|new]]</code> to allocate the string itself somewhere else. The advantage of <code>new</code> is that you can allocate an array of a size determined at run-time, but the downside is that if you aren't scrupulous about calling <code>[[W:delete (C++)|delete]]</code> (or <code>delete[]</code> for arrays) you will suffer a [[W:memory leak|memory leak]].
它们之间的区别在于,一个在函数的内存空间中创建一个数组,而另一个在函数中创建一个指针,并使用 <code>[[W:new (C++)|new]]</code> 在其他地方分配字符串本身。使用 <code>new</code> 的优点是可以在运行时确定大小,但缺点是如果不仔细调用 <code>[[W:delete (C++)|delete]]</code>(或对于数组是 <code>delete[]</code>)你将遭受[[W:memory leak|内存泄漏]]


== Unicode strings ==
== Unicode 字符串 ==


{{note|Source is internally ASCII. The only time you will deal with Unicode is if you delve into the inner workings of [[VGUI]].}}
{{note|源代码内部是 ASCII。只有当你深入了解{{L|VGUI}}的内部工作时,你才会处理 Unicode。}}


[[W:Unicode|Unicode]] strings behave similarly to ASCII strings, but are instead arrays of <code>[[wchar_t]]</code>. They are operated on by their own set of string functions, normally with 'wc' or 'wcs' (wide char string) in their name.
[[W:Unicode|Unicode]] 字符串的行为与 ASCII 字符串类似,但是它们是 <code>{{L|wchar_t}}</code> 的数组。它们由自己的一组字符串函数操作,通常名称中包含 'wc' 'wcs'(宽字符字符串)。


<source lang=cpp>
<source lang=cpp>
Line 55: Line 54:
</source>
</source>


The <code>L</code> marks the string literal as being Unicode. You need to do this even if the characters are all ASCII-compatible.
<code>L</code> 标记字符串字面量为 Unicode。即使字符全部兼容 ASCII,你也需要这样做。
 
== String functions ==


There are a multitude of functions which process strings, of which the most common ASCII variants have Source-specific <code>V_*</code> equivalents. See [http://msdn.microsoft.com/en-us/library/f0151s4x.aspx MSDN] for a quite comprehensive list, or search VS' Class View for "V_str".
== 字符串函数 ==


[[category:Variables]]
有许多函数处理字符串,其中最常见的 ASCII 变体具有 Source 特定的 <code>V_*</code> 等效项。请参阅[http://msdn.microsoft.com/en-us/library/f0151s4x.aspx MSDN]获取相当全面的列表,或者在 VS 的类视图中搜索“V_str”。
[[Category:Glossary]]
{{ACategory|C++}}
[[Category:Simplified Chinese]]
{{ACategory|Variables}}

Latest revision as of 11:18, 12 July 2024

English (en)Deutsch (de)Español (es)Русский (ru)中文 (zh)Translate (Translate)

数组中的 charASCII)或 wchar_tUnicode)常用于存储文本。这些缓冲区有一个特殊的术语:字符串。它们很重要,但也很复杂。

C 字符串或空终止字节字符串

一个字符串总是比它看起来的要大一个字符。额外的项目是空终止符(二进制零,表示为 \0)。 这是必需的,因为通常传递的是指向字符串的 pointer(en),而不是数组本身。

Warning.png警告:指针不包含字符串长度的数据。

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

Tip.png提示:空终止符不需要是数组中的最后一个项目。它后面的字节将被字符串处理函数忽略。

从字符串文字创建

char* MyString = "Hello world"; // 必须分配给指针!

这段代码从一个字符串字面量创建一个字符串。双引号是特殊的语法,它们从其内容生成一个 char 数组。因此,上面的代码:

  1. 分配了12字节的内存,存储字符串的任意位置。这是每个字符一个字节,加上一个自动的第12个字节用于空终止符。
  2. 创建一个本地的 char pointer(en),其中包含第一个字符的地址(在本例中为 H)。

字符串字面量通常与 const 变量一起使用。这是因为字符串字面量将在进程的整个生命周期中保留在内存中。

Note.png注意:如果你在 Visual Studio 调试器中检查 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 字符串

Note.png注意:源代码内部是 ASCII。只有当你深入了解VGUI(en)的内部工作时,你才会处理 Unicode。

Unicode 字符串的行为与 ASCII 字符串类似,但是它们是 wchar_t(en) 的数组。它们由自己的一组字符串函数操作,通常名称中包含 'wc' 或 'wcs'(宽字符字符串)。

wchar_t* MyWideString = L"Здравей свят";

L 标记字符串字面量为 Unicode。即使字符全部兼容 ASCII,你也需要这样做。

字符串函数

有许多函数处理字符串,其中最常见的 ASCII 变体具有 Source 特定的 V_* 等效项。请参阅MSDN获取相当全面的列表,或者在 VS 的类视图中搜索“V_str”。