簡介
字符串或串(String)是由數字、字母、下劃線組成的一串字符。一般記為 s=“a1a2···an”(n>=0)。它是編程語言中表示文本的數據類型。在程序設計中,字符串(string)為符号或數值的一個連續序列,如符号串(一串字符)或二進制數字串(一串二進制數字)。
補充:字符串在存儲上類似字符數組,它每一位單個元素都是能提取的,字符串的零位是它的長度,如s[0]=10,這提供給我們很多方便,例如高精度運算時每一位都能轉化為數字存入數組。
通常以串的整體作為操作對象,如:在串中查找某個子串、求取一個子串、在串的某個位置上插入一個子串以及删除一個子串等。兩個字符串相等的充要條件是:長度相等,并且各個對應位置上的字符都相等。設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 級的警告。
注:和其他兩種語法不同,單引号字符串中出現的變量和轉義序列不會被變量的值替代。
此外,如果試圖轉義任何其它字符,反斜線本身也會被顯示出來。
雙引号字符串最重要的一點是其中的變量名會被變量值替代。細節參見字符串解析。
定界符
另一種給字符串定界的方法使用定界符語法(“<<<”)。應該在 <<< 之後提供一個标識符,然後是字符串,然後是同樣的标識符結束字符串。
結束标識符必須從行的第一列開始。同樣,标識符也必須遵循 php 中其它任何标簽的命名規則:隻能包含字母數字下劃線,而且必須以下劃線或非數字字符開始。
例子 11-3. 非法的例子
定界符文本表現的就和雙引号字符串一樣,隻是沒有雙引号。這意味着在定界符文本中不需要轉義引号,不過仍然可以用以上列出來的轉義代碼。變量會被展開,但當在定界符文本中表達複雜變量時和字符串一樣同樣也要注意。
例子 11-4. 定界符字符串例子
foo = 'Foo'; $this->bar = array('Bar1', 'Bar2', 'Bar3'); }}$foo = new foo();$name = 'MyName';echo <
變量解析
當用雙引号或者定界符指定字符串時,其中的變量會被解析。
有兩種語法,一種簡單的和一種複雜的。簡單語法最通用和方便,它提供了解析變量,數組值,或者對象屬性的方法。
複雜語法是 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()函數。