字元串

編程語言中表示文本的數據類型

字元串主要用於編程,概念說明、函數解釋、用法詳述見正文,這裡補充一點:字元串在存儲上類似字元數組,所以它每一位的單個元素都是可以提取的,如s=“abcdefghij”,則s[1]=“a”,s[10]="j",而字元串的零位正是它的長度,如s[0]=10(※上述功能Ansistring沒有。),這可以給我們提供很多方便,如高精度運算時每一位都可以轉化為數字存入數組。

簡介


字元串或串(String)是由數字、字母、下劃線組成的一串字元。一般記為 s=“a1a2···an”(n>=0)。它是編程語言中表示文本的數據類型。在程序設計中,字元串(string)為符號或數值的一個連續序列,如符號串(一串字元)或二進位數字串(一串二進位數字)。
通常以串的整體作為操作對象,如:在串中查找某個子串、求取一個子串、在串的某個位置上插入一個子串以及刪除一個子串等。兩個字元串相等的充要條件是:長度相等,並且各個對應位置上的字元都相等。設p、q是兩個串,求q在p中首次出現的位置的運算叫做模式匹配。串的兩種最基本的存儲方式是順序存儲方式和鏈接存儲方式。

函數應用


1. 連接運算 concat(s1,s2,s3…sn) 相當於s1+s2+s3+…+sn.
例:concat(‘11’,'aa’)='11aa’;
2. 求子串。 Copy(s,I,I) 從字元串s中截取第I個字元開始后的長度為l的子串。
例:copy(‘abdag’,2,3)=’bda’
3. 刪除子串。過程 Delete(s,I,l) 從字元串s中刪除第I個字元開始后的長度為l的子串。
例:s:=’abcde’;delete(s,2,3);結果s:=’ae’
4. 插入子串。過程Insert(s1,s2,I) 把s1插入到s2的第I個位置
例:s:=abc;insert(‘12’,s,2);結果s:=’a12bc’
5. 求字元串長度 length(s) 例:length(‘12abc’)=5
在ASP中 求字元串長度用 len(s)例: len("abc12")=5
6. 搜索子串的位置 pos(s1,s2) 如果s1是s2的子串,則返回s1的第一個字元在s2中的位置,若不是子串,則返回0.
例:pos(‘ab’,’12abcd’)=3
7. 字元的大寫轉換。Upcase(ch) 求字元ch的大寫體。
例:upcase(‘a’)=’A’
8. 數值轉換為數串。過程 Str(x,s) 把數值x化為數串s.
例:str(12345,s); 結果s=’12345’
9. 數串轉換為數值。過程val(s,x,I) 把數串s轉化為數值x,如果成功則I=0,不成功則I為無效字元的序數,第三個參數也可不傳
例:val(‘1234’,x,I);結果 x:=1234

病毒


“字元串(Trojan.String.a)”病毒:警惕程度★★★,木馬病毒,通過網路傳播,依賴系統: WIN9X/NT/2000/XP。
該病毒通過網路傳播,進入用戶電腦後就隱藏在系統目錄和內存中,病毒發作時會給用戶電腦造成以下破壞:屏幕為空、無端打開CD驅動器、進行洪水攻擊、打開黃色網站等,用戶要小心防毒。

形式理論


設 Σ 是叫做字母表的非空有限集合。Σ 的元素叫做“符號”或“字元”。在 Σ 上的字元串(或字)是來自 Σ 的任何有限序列。例如,如果 Σ = {0, 1},則 0101 是在 Σ 之上的字元串。
字元串的長度是在字元串中字元的數目(序列的長度),它可以是任何非負整數。“空串”是在 Σ 上的唯一的長度為 0 的字元串,並被指示為 ε 或 λ。
在 Σ 上的所有長度為 n 的字元串的集合指示為 Σn。例如,如果 Σ = {0, 1} 則 Σ2 = {00, 01, 10, 11}。注意 Σ0 = {ε} 對於任何字母表 Σ。
在 Σ 上的所有任何長度的字元串的集合是 Σ 的Kleene閉包並被指示為 Σ*。依據Σn, 。例如,如果 Σ = {0, 1} 則 Σ* = {ε, 0, 1, 00, 01, 10, 11, 000, 001, 010, 011, …}。儘管 Σ* 自身是可數無限的,Σ* 的所有元素都有有限長度。
在 Σ 上一個字元串的集合(就是 Σ* 的任何子集)被稱為在 Σ 上的形式語言。例如,如果 Σ = {0, 1},則帶有偶數個零的字元串的集合({ε, 1, 00, 11, 001, 010, 100, 111, 0000, 0011, 0101, 0110, 1001, 1010, 1100, 1111, …})是在 Σ 上的形式語言。

串接子串


“串接”是 Σ* 上的重要二元運算。對於 Σ* 中的兩個字元串 s 和 t,它們的串接被定義為在 s 中的字元序列之後跟隨著 t 中的字元序列,並被指示為 st。例如,Σ = {a, b, …, z},並且 s = bear 且 t = hug,則 st = bearhug 而 ts = hugbear。
字元串串接是結合性的,但非交換性運算。空串充當單位;對於任何字元串 s,有 εs = sε = s。所以,集合 Σ* 和串接運算形成了幺半群,就是從 Σ 生成的自由幺半群。此外,長度函數定義從 Σ* 到非負整數的幺半群同態。
字元串 s 被稱為是字元串 t 的“子串”或“因子”,如果存在(可能為空)字元串 u 和 v 使得 t = usv。“是其子串”關係定義了在 Σ* 上的偏序,其最小元是空串。

詞典排序


經常需要定義在字元串集合上的次序。如果字元表 Σ 有一個全序 (cf. 字母序),則可以定義在 Σ* 上的叫做詞典序的全序。注意因為 Σ 是有限的,總是可以定義在 Σ 繼而在 Σ* 上的良好次序。例如,如果 Σ = {0, 1} 並且 0 < 1,則 Σ* 的詞典次序是 ε < 0 < 00 < 000 < … < 011 < 0110 < … < 01111 < … < 1 < 10 < 100 < … < 101 < … < 111 …

運算


在形式理論中經常出現一些在字元串上的額外運算。它們在條目字元串運算中給出。

數據類型


字元串數據類型是建模在形式字元串的想法上的數據類型。字元串是幾乎在所有編程語言中可以實現的非常重要和有用的數據類型。在某些語言中它們可作為基本類型獲得,在另一些語言中做為複合類型獲得。多數高級語言的語法允許通常用某種方式引用起來的字元串來表示字元串數據類型的實例;這種元字元串叫做“文本”或“字元串文本”。

長度


儘管形式字元串可以有任意(但有限)的長度,實際語言的字元串的長度經常被限制到一個人工極大值。一般的說,有兩種類型的字元串數據類型: “定長字元串”,它有固定的極大長度並且不管是否達到了這個極大值都使用同樣數量的內存;和“變長字元串”,它的長度不是專斷固定的並且依賴於實際的大小使用可變數量的內存。在現代編程語言中的多數字元串是變長字元串。儘管叫這個名字,所有變長字元串還是在長度上有個極限,一般的說這個極限只依賴於可獲得的內存的數量。

字元編碼


歷史上,字元串數據類型為每個字元分配一個位元組,儘管精確的字符集隨著區域而改變,字元編碼足夠類似得程序員可以忽略它 — 同一個系統在不同的區域中使用的字符集組要麼讓一個字元在同樣位置,要麼根本就沒有它。這些字符集典型的基於ASCII碼或EBCDIC碼。
意音文本的語言比如漢語、日語和朝鮮語(合稱為CJK)的合理表示需要多於256個字元(每字元一個位元組編碼的極限)。常規的解決涉及保持對ASCII碼的單位元組表示並使用雙位元組來表示CJK字形。現存代碼在用到它們會導致一些字元串匹配和切斷上的問題,嚴重程度依賴於字元編碼是如何設計的。某些編碼比如EUC家族保證在ASCII碼範圍內的位元組值只表示ASCII字元,使得使用這些字元作為欄位分隔符的系統得到編碼安全。其他編碼如ISO-2022和Shift-JIS不做這種擔保,使得基於位元組的代碼做的匹配不安全。另一個問題是如果一個字元串的開頭被刪除了,對解碼器的重要指示或關於在多位元組序列中的位置的信息可能就丟失了。另一個問題是如果字元串被連接到一起(特別是在被不知道這個編碼的代碼截斷了它們的結尾之後),第一個字元串可能不能導致編碼器進入適合處理第二個字元串的狀態中。
Unicode也有些複雜的問題。多數語言有Unicode字元串數據類型(通常是UTF-16,因為它在Unicode補充位面介入之前就被增加了)。在Unicode和本地編碼之間轉換要求理解本地編碼,這對於現存系統要一起傳輸各種編碼的字元串而又沒有實際標記出它們用了什麼編碼就是個問題。

實現


某些語言如 C++ 把字元串實現為可以用於任何基本類型的模版,但這是個例外而不是規則。
如果一個面向對象語言把字元串表示為對象,它們叫做“可變的”(mutable),如果值可以在進行時間變更,叫做“不變的”(immutable),如果這個值在建立后就凍結了。例如,Ruby 有可變字元串,而 Python 的字元串是不可變的。
其他語言,最著名的有 Prolog 和 Erlang,避免實現字元串數據類型,轉而採用把字元串表示為字元代碼的列表的約定。

表示法


一種常用的表示法是使用一個字元代碼的數組,每個字元佔用一個位元組(如在ASCII代碼中)或兩個位元組(如在unicode中)。它的長度可以使用一個結束符(一般是NUL,ASCII代碼是0,在C編程語言中使用這種方法)。或者在前面加入一個整數值來表示它的長度(在Pascal語言中使用這種方法)。
這是一個用NUL結束的字元串的例子,它用10個byte存儲,用ASCII表示法:
F R A N K NUL k e f w
46 52 41 4E 4B 00 6B 66 66 77
上面的字元串的長度為5個字元,但注意它佔用6個位元組。結束符后的字元沒有任何意義。
這是相同的Pascal字元串:
length F R A N K k e f w
05 46 52 41 4E 4B 6B 66 66 77
當然,可能還有其它的表示法。使用樹和列表可以使得一些字元串操作(如插入和刪除)更高效。

實用程序


一些編程語言設計為編寫字元串處理程序更容易編寫。這是一些例子:
awk
Icon
perl
MUMPS
sed
SNOBOL
很多UNIX實用程序進行簡單的字元串處理,並能用於簡單地編寫一些強大的字元串處理演演算法。文件和有限流可以像字元串一樣查看。
一些新的編程語言,包括Perl、Python和Ruby,藉助正則表達式來幫助文本處理。

操作


一個簡單的字元串操作是“連接”:也就是說先寫一個字元串S,隨後在後面再寫一個T得到ST這樣一個過程。其它的常見操作包括在一個長字元串中搜索一個子串,排列一組字元串以及分析一個字元串。因為存在如此多的字元串應用方式,所以相應地有許多權衡了不同應用的相關演演算法。高級的字元串演演算法通常使用包括後向樹和有限狀態機在內的複雜機制和數據結構。

演演算法


這是一些字元串處理演演算法,在字元串上進行不同的處理:
字元串查找演演算法
正則表達式演演算法
模式匹配
字元串的匹配演演算法(kmp)
AC自動機
後綴數組/樹/自動機

PHP中介紹


string是一系列字元。在 php 中,字元和位元組一樣,也就是說,一共有 256 種不同字元的可能性。這也暗示 php 對 Unicode 沒有本地支持。請參閱函數 utf8_encode()和 utf8_decode()以了解有關 Unicode 支持
注:一個字元串變得非常巨大也沒有問題,php 沒有給字元串的大小強加實現範圍,所以完全沒有理由擔心長字元串。
語法
字元串可以用三種字面上的方法定義。
單引號
雙引號
定界符

單引號

指定一個簡單字元串的最簡單的方法是用單引號(字元 ')括起來。
要表示一個單引號,需要用反斜線(/)轉義,和很多其它語言一樣。如果在單引號之前或字元串結尾需要出現一個反斜線,需要用兩個反斜線表示。注意如果試圖轉義任何其它字元,反斜線本身也會被顯示出來!所以通常不需要轉義反斜線本身。
注:在 php 3 中,此情況下將發出一個 E_NOTICE 級的警告。
注:和其他兩種語法不同,單引號字元串中出現的變數和轉義序列 不會被變數的值替代。
foo = 'Foo'; $this->bar = array('Bar1', 'Bar2', 'Bar3'); }}$foo = new foo();$name = 'MyName';echo <<foo.Now, I am printing some {$foo->bar[1]}.This should print a capital 'A': /x41EOT;?> 注:定界符支持是 php 4 中加入的。

變數解析

當用雙引號或者定界符指定字元串時,其中的變數會被解析。
有兩種語法,一種簡單的和一種複雜的。簡單語法最通用和方便,它提供了解析變數,數組值,或者對象屬性的方法。
複雜語法是 php 4 引進的,可以用花括弧括起一個表達式。
簡單語法如果遇到美元符號($),解析器會儘可能多地取得後面的字元以組成一個合法的變數名。如果想明示指定名字的結束,用花括弧把變數名括起來。
同樣也可以解析數組索引或者對象屬性。對於數組索引,右方括弧(])標誌著索引的結束。對象屬性則和簡單變數適用同樣的規則,儘管對於對象屬性沒有像變數那樣的小技巧。
'red', 'banana' => 'yellow');// Works but note that this works differently outside string-quotesecho "A banana is $fruits[banana].";// Worksecho "A banana is {$fruits['banana']}.";// Works but php looks for a constant named banana first// as described below.echo "A banana is {$fruits[banana]}.";// Won't work, use braces. This results in a parse error.echo "A banana is $fruits['banana'].";// Worksecho "A banana is " . $fruits['banana'] . ".";// Worksecho "This square is $square->width meters broad.";// Won't work. For a solution, see the complex syntax.echo "This square is $square->width00 centimeters broad.";?>
對於任何更複雜的情況,應該使用複雜語法。
複雜(花括弧)語法不是因為語法複雜而稱其為複雜,而是因為用此方法可以包含複雜的表達式。
事實上,用此語法可以在字元串中包含任何在名字空間的值。僅僅用和在字元串之外同樣的方法寫一個表達式,然後用 { 和 } 把它包含進來。因為不能轉義“{”,此語法僅在 $ 緊跟在 { 後面時被識別(用“{/$”或者“/{$”來得到一個字面上的“{$”)。用一些例子可以更清晰:
width}00 centimeters broad.";// Worksecho "This works: {$arr[4][3]}";// This is wrong for the same reason as $foo[bar] is wrong// outside a string. In otherwords, it will still work but// because php first looks for a constant named foo, it will// throw an error of level E_NOTICE (undefined constant).echo "This is wrong: {$arr[foo][3]}";// Works. When using multi-dimensional arrays, always use// braces around arrays when inside of stringsecho "This works: {$arr['foo'][3]}";// Works.echo "This works: " . $arr['foo'][3];echo "You can even write {$obj->values[3]->name}";echo "This is the value of the var named $name: {${$name}}";?>
訪問和修改字元串中的字元
字元串中的字元可以通過在字元串之後用花括弧指定所要字元從零開始的偏移量來訪問和修改。
注:為了向下兼容,仍然可以用方括弧。不過此語法自 php 4 起已過時。
例子 11-5. 一些字元串例子

實用函數

字元串可以用“.”(點)運算符連接。注意這裡不能用“+”(加)運算符。更多信息參見字元串運算符。
有很多實用函數來改變字元串。
普通函數見字元串函數一節,高級搜索和替換見正則表達式函數(兩種風格:Perl 和 POSIX 擴展)。
還有 URL 字元串函數,以及加密/解密字元串的函數(mcrypt 和 mhash)。
最後,如果還是找不到想要的函數,參見字元類型函數。

轉換

可以用 (string) 標記或者 strval()函數將一個值轉換為字元串。當某表達式需要字元串時,字元串的轉換會在表達式範圍內自動完成。例如當使用 echo()或者 print()函數時,或者將一個變數值與一個字元串進行比較的時候。閱讀手冊中有關類型和類型戲法中的部分有助於更清楚一些。參見 settype()。
布爾值 TRUE將被轉換為字元串 "1",而值 FALSE將被表示為 ""(即空字元串)。這樣就可以隨意地在布爾值和字元串之間進行比較。
整數或浮點數數值在轉換成字元串時,字元串由表示這些數值的數字字元組成(浮點數還包含有指數部分)。
數組將被轉換成字元串 "Array",因此無法通過 echo()或者 print()函數來輸出數組的內容。請參考下文以獲取更多提示。
對象將被轉換成字元串 "Object"。如果因為調試需要,需要將對象的成員變數列印出來,請閱讀下文。如果希望得到該對象所依附的類的名稱,請使用函數 get_class()。自 php 5 起,如果合適可以用 __toString() 方法。
資源類型總是以 "Resource id #1" 的格式被轉換成字元串,其中 1 是 php 在運行時給資源指定的唯一標識。如果希望獲取資源的類型,請使用函數 get_resource_type()。
NULL將被轉換成空字元串。
正如以上所示,將數組、對象或者資源列印出來,並不能提供任何關於這些值本身的有用的信息。請參閱函數 print_r()和 var_dump(),對於調試來說,這些是更好的列印值的方法。
可以將 php 的值轉換為字元串以永久地儲存它們。這種方法被稱為序列化,可以用函數 serialize()來完成該操作。如果在安裝 php 時建立了 WDDX 支持,還可以將 php 的值序列化為 XML 結構。

轉換數值

當一個字元串被當作數字來求值時,根據以下規則來決定結果的類型和值。
如果包括“.”,“e”或“E”其中任何一個字元的話,字元串被當作 float來求值。否則就被當作整數。
該值由字元串最前面的部分決定。如果字元串以合法的數字數據開始,就用該數字作為其值,否則其值為 0(零)。合法數字數據由可選的正負號開始,後面跟著一個或多個數字(可選地包括十進位分數),後面跟著可選的指數。指數是一個“e”或者“E”後面跟著一個或多個數字。
此轉換的更多信息見 Unix 手冊中關於 strtod(3) 的部分。
如果想測試本節中的任何例子,可以拷貝和粘貼這些例子並且加上下面這一行自己看看會發生什麼:
/n";?>
不要指望在將一個字元轉換成整型時能夠得到該字元的編碼(可能也會在 C 中這麼做)。如果希望在字元編碼和字元之間轉換,請使用 ord()和 chr()函數。