最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

第 17 講:指針和字符

2021-09-19 21:35 作者:SunnieShine  | 我要投稿

前文我們提到了近乎所有的指針的用法,不過指針和數(shù)組用起來確實(shí)挺難的,今天要說到的知識(shí)點(diǎn)是字符串、字符數(shù)組和指針三者的關(guān)系。


什么是字符?

在之前,我們對字符提到的內(nèi)容很少,所以我們這里統(tǒng)一為大家介紹它們。

字符是以一個(gè)單引號(hào)包含起來,以區(qū)分?jǐn)?shù)值字面量的存在。比如下面的這個(gè)寫法:

這樣就表示 c 變量是一個(gè)字符類型的變量,存儲(chǔ)的元素是一個(gè)字符 1。這個(gè)字符 1 和普通的 1 不同,字符 1 一般用于輸出才用到,而數(shù)字 1 則可以操作和計(jì)算。

在 C 語言里,用單引號(hào)把這些符號(hào)引起來可以和數(shù)字作出區(qū)分。但為了靈活使用,字符有時(shí)候也可以和數(shù)字進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換關(guān)系是通過一個(gè)叫做 ASCII 碼表來搞定的。比如,在這個(gè)表里規(guī)定字符 A 的對應(yīng)整數(shù)是 65,a 是 97,而字符 1 對應(yīng)數(shù)值則是 49。

這樣定義,來區(qū)分字符是有意義的。在計(jì)算機(jī)處理這些字符的時(shí)候,為了可以明確表達(dá)數(shù)字的行為是計(jì)算,而字符的行為是輸出,所以 C 語言發(fā)明了類型這個(gè)體系,來區(qū)分字符和整數(shù),所以字符 1 和數(shù)字 1 具有截然不同的用法,所以寫法和聲明(定義)語句上的賦值也是有不同的地方的。

如果你書寫的方式是這樣:

這樣只能表達(dá) i 變量的數(shù)值是 49,反之,如果你書寫成

這樣只能表達(dá) c 變量表示的字符是 ASCII 碼表里編號(hào)為 1 的那個(gè)字符。


使用字符和數(shù)字進(jìn)行輸出

在前文里,我們提到過數(shù)字的輸出模式。如果是整數(shù),輸出則使用 %d 的格式化字符串,它會(huì)自動(dòng)幫我們改為字符串的形式書寫出來:

比如上面的這個(gè)寫法,顯然第一個(gè) 0 是沒有意義的,但用整數(shù)輸出的時(shí)候,你也就看不到這個(gè) 0 了,而只有 12 這個(gè)字符串。這就是數(shù)字的輸出模式。

字符的輸出使用的是 %c 這個(gè)格式化字符串。

這樣你就可以在輸出里得到一個(gè) 1。不過,如果你把這個(gè)單引號(hào)去掉了:

它就好比是

所以,輸出的內(nèi)容其實(shí)是 ASCII 碼表里編號(hào)為 1 的那個(gè)字符,而并不是 1,因?yàn)?1 在編號(hào)第 49 號(hào)的地方,所以如果想輸出 49,你還必須得寫成

這樣才可以得到一個(gè)字符 1。


字符串

字符串(也經(jīng)常被簡稱為,string),是字符的一組序列,即由多個(gè)字符構(gòu)成的這個(gè)序列,稱為字符串。它的表現(xiàn)形式有兩種,一種是字面量字符串,一種是字符數(shù)組。我們都來說一下,以及它們的使用。


字面量字符串

字符可以用字面量的形式呈現(xiàn),也可以用數(shù)字呈現(xiàn),這表現(xiàn)出字符的兩種形態(tài)。字符串也是這樣。第一種呈現(xiàn)形式是通過雙引號(hào)的形式出現(xiàn)的。比如 "Hello, world!\n" 就是一個(gè)合格的字面量字符串寫法,用雙引號(hào)把所有原封不動(dòng)的字符序列包括起來。

不過,字面量字符串如何賦值和輸出呢?賦值的話,它的類型應(yīng)該是什么呢?

之前說過,字符串是一系列字符,所以它肯定不是單純的 char 類型了。實(shí)際上,它可以使用字符指針來表示,也可以用字符數(shù)組表示:

C 語言允許第一種寫法,讓 char 類型的指針(干脆就叫 char * 類型)來“接收”這個(gè)字符串,這樣的話,這個(gè)指針將會(huì)指向這個(gè)字符串的首地址(和數(shù)組一致,指向數(shù)組的第 0 號(hào)元素,即 charPointer 本身就等價(jià)于 &charPointer[0])。這種表示方式的優(yōu)勢是,不用去數(shù)和關(guān)心字符串到底有多長。

第二種寫法也是允許的,C 語言會(huì)自動(dòng)把這個(gè)字符串拆解為一個(gè)字符數(shù)組,然后挨個(gè)存放進(jìn)去,最后得到這個(gè)數(shù)組的首地址。所以第二種寫法下,charArray 變量名依舊等價(jià)于數(shù)組的首地址。

不過,需要你額外注意一點(diǎn)。它和普通元素類型的數(shù)組不同,字符串會(huì)被處理成字符數(shù)組的形式存儲(chǔ),然后返回的首地址可以用字符指針變量名或字符數(shù)組變量名接收。但是,字符串會(huì)自動(dòng)為末尾添加一個(gè)結(jié)束標(biāo)記字符 \0。這個(gè)字符是計(jì)算機(jī)內(nèi)表達(dá)這個(gè)字符的寫法,輸出并非是一個(gè)反斜杠和一個(gè)數(shù)字 0,而是啥都沒有。

\0 這個(gè)字符僅用于標(biāo)記字符串的結(jié)尾用,沒有其它的功能。而如果你非要把它當(dāng)整數(shù)形式表示的話,它在 ASCII 碼表里對應(yīng)的整數(shù)也就是 0。所以 0 對應(yīng) \0 這個(gè)字符。

所以,這個(gè)知識(shí)點(diǎn)告訴我們,Hello, world! 這個(gè)字符串整體長度是 14,除了字面量給定的 10 個(gè)英文字母、2 個(gè)符號(hào)、一個(gè)空格以外,還默認(rèn)在末尾帶有一個(gè)字符 \0 標(biāo)記,所以這個(gè)字符串長度是 14,并不是 13;而在第二種賦值格式里,這個(gè)中括號(hào)里就應(yīng)該是 14,而不是 13。

輸出字面量字符串的方式可以用 %s 的方式輸出:

這樣就可以完整輸出 s 這個(gè)字符串的所有內(nèi)容。另外,這樣書寫每次都必須寫上 %s,所以你可以改寫為這樣:

即直接使用 puts 函數(shù)來輸出一個(gè)字符串。


字符數(shù)組

顯然,字面量字符串會(huì)被處理為字符數(shù)組,所以其實(shí)還可以書寫為字符數(shù)組。

但請注意,如果寫成字符數(shù)組,系統(tǒng)就不會(huì)自己給你補(bǔ)充 \0 字符了。所以這種寫法必須自己補(bǔ)充一個(gè) \0 符號(hào)在字符數(shù)組的末尾。

當(dāng)然,你把 \0 寫在字符數(shù)組的中間某處也可以,不過這個(gè)字符串就會(huì)從這個(gè)地方截?cái)啵?/span>

這樣的話,這個(gè)字符數(shù)組長度就是 7 而不是原本的 13 或者 14 了。也就是說,這個(gè) s 接收到的完整的字符數(shù)組序列到第一個(gè) \0 就結(jié)束了,后面的內(nèi)容都不在 s 里。不過在內(nèi)存里,這些字符確實(shí)是挨著存儲(chǔ)的,不過你必須通過語法的 bug 越界訪問數(shù)組,才看得到它們了。

同樣地,字符數(shù)組也具有退化賦值的特性,所以我們依舊可以使用這一點(diǎn),把字符數(shù)組賦值給一個(gè)指針。

字符串的使用

講完了兩種字符串的書寫格式后,我們來說明一下字符串的基本使用。

考慮如下實(shí)例。假設(shè)我們在寫一個(gè)代碼,輸出一個(gè)數(shù)字是否是質(zhì)數(shù),代碼大部分已經(jīng)寫好:

這就是前面的例子,只是我為了邏輯清晰,把 isPrimeint 改為了 bool 類型(只是這么做就只能讓代碼運(yùn)行在允許 C99 標(biāo)準(zhǔn)的地方了)。

現(xiàn)在,考慮輸出語句。可以從輸出語句里看到,它們大部分輸出信息都是相同的,只是多了一個(gè) not?,F(xiàn)在我們可以考慮把代碼寫成一個(gè)三目運(yùn)算符的方式:

?printf("%d is %sa prime.\n", digit, isPrime ? "" : "not ");

注意輸出語句里有一個(gè) %sa,其實(shí)它是 %s 和一個(gè)字符 a 而已。它想要表示的是,某某數(shù)字,是(或不是)一個(gè)質(zhì)數(shù),這樣的輸出格式。當(dāng) isPrimetrue 的時(shí)候,我們就不需要 not 這個(gè)單詞的修飾,所以這個(gè)輸出一個(gè)空的字符串(只有一個(gè) \0,反正里面其它東西都沒有,到時(shí)候計(jì)算機(jī)會(huì)幫我們作出處理);否則加一個(gè) not 修飾符來表示它”不是“質(zhì)數(shù)。


常見字符串函數(shù)

我們經(jīng)常要使用到一些字符串的處理模式,比如提取字符串里其中一部分字符、求長度等等。下面就來看看它們。


求字符串長度

我們需要實(shí)現(xiàn)一個(gè)函數(shù) strlen,獲取一個(gè)字符串的長度。這個(gè)算法比較容易實(shí)現(xiàn):

可以從代碼里看到,這就是一個(gè)基本的計(jì)算方式。首先我們定義一個(gè)結(jié)果 count 變量來表示一共多少字符,然后一個(gè)指針變量指向它的第一個(gè)元素,這樣一會(huì)兒我們就可以使用 ++ 將變量移動(dòng)指向,讓其指向下一個(gè)字符信息。然后最終當(dāng) cur 指向 \0 的時(shí)候,表示字符統(tǒng)計(jì)完畢,跳出 while 循環(huán),返回結(jié)果 count 即可。

另外,參數(shù) str 在過程里都不用修改變量的本身指向和指向的內(nèi)容,所以我們可以對 str 使用 const 修飾。

這個(gè)算法可以改寫為這樣:

使用 for 循環(huán)就會(huì)簡單不少。另外,cur 指針如果不是指向 \0 字符就一直遍歷,這個(gè)條件是 *cur != '\0',而前文說過 \0 的 ASCII 碼表編碼數(shù)值是 0,所以就相當(dāng)于 *cur != 0,而這種寫法在條件判斷一節(jié)的時(shí)候說過,它等價(jià)于不寫 != 0 部分,所以最終可以直接寫成 *cur 來表示 *cur != '\0'。另外,str 就等價(jià)于 &str[0],所以初始賦值也可以不要地址符號(hào)和索引器部分 [0]


取出字符串的一部分字符

嘗試寫出一個(gè) strstr 函數(shù),來獲取某個(gè)字符串里指定起始點(diǎn)和長度的其中一部分字符。

首先判斷輸入的所有參數(shù)是否都符合條件。如果取出的長度 length 比 0 還小,或者比字符串長度還大,是不滿足要求的;同時(shí),如果獲取元素的起始索引 startIndex 比 0 小,或超過字符串長度,也依然是無效的。所以這個(gè)時(shí)候我們給用戶輸出一個(gè)空字符串,來表示錯(cuò)誤(當(dāng)然你也可以給它另外的東西,或者執(zhí)行指定的某個(gè)行為來表示輸入信息錯(cuò)誤)。

否則,我們嘗試讓 ptr 指向 str[startIndex] 處的元素,然后不斷更新 lastptr 的數(shù)值。當(dāng) last 減到 0 的時(shí)候就是獲取結(jié)束的時(shí)候。

最后得到結(jié)果后,我們把 ptr 指向的字符改寫為 \0 表示從這里截?cái)?,表示這里是字符串的結(jié)束。最后返回 str[startIndex] 的地址就可以了。

當(dāng)然你也可以改寫一下:

注意,返回值也可以使用 const 修飾符來表示不可以修改。

第 17 講:指針和字符的評(píng)論 (共 條)

分享到微博請遵守國家法律
贡嘎县| 东兰县| 昭苏县| 秀山| 五原县| 定陶县| 杭锦旗| 桐柏县| 长葛市| 象州县| 正安县| 喀什市| 墨竹工卡县| 泸西县| 商都县| 教育| 阿拉善右旗| 磐石市| 万全县| 额敏县| 凤阳县| 同德县| 松阳县| 双城市| 阿城市| 大兴区| 当雄县| 莎车县| 海口市| 闻喜县| 疏附县| 渭源县| 增城市| 金湖县| 大港区| 贵港市| 鹤岗市| 正宁县| 澄迈县| 阿巴嘎旗| 淳化县|