我們在上節(jié)博客中介紹了 C 語言中字符串相關(guān)的概念,那么我們今天就來看看在字符串這塊的典型問題。
開魯網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián)公司,開魯網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為開魯千余家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站建設(shè)要多少錢,請找那個售后服務(wù)好的開魯做網(wǎng)站的公司定做!
A、我們先來看看下面的示例代碼會輸出什么,代碼如下
#include <stdio.h> int main() { char buf[15] = {0}; char src[] = "hello %s"; snprintf(buf, sizeof(buf), src); printf("buf = %s\n", buf); return 0; }
我們先來說說 snprintf 函數(shù),它本身是可變參數(shù)的函數(shù),原型是這樣的:int snprintf(char* buf, int buf_size, const char* fomart, ...)。當(dāng)函數(shù)只有3個參數(shù)時,如果第三個參數(shù)沒有包含格式化信息,函數(shù)調(diào)用沒有問題;相反,如果第三個參數(shù)包含了格式化信息,但缺少后續(xù)對應(yīng)參數(shù),則程序行為不穩(wěn)定。上面的程序中第8行調(diào)用了 snprintf 函數(shù),但是在第6行定義的 src 字符數(shù)組中包含了 %s,則它的行為是不確定的。我們來看看編譯結(jié)果
我們看到編譯其實(shí)已經(jīng)提示了,打印的結(jié)果果然是不確定的。那么我們在 snprintf 函數(shù)中再加上第四個參數(shù)字符串“world”試試(或者直接把第6行后面的 %s 變成 world 也是同樣的效果)。編譯結(jié)果如下
那么我們看到編譯沒有警告,程序也完美運(yùn)行。
B、我們再來看看下面這份示例代碼
#include <stdio.h> #include <string.h> int main() { #define STR "Hello, \0World\0" char* src = STR; char buf[255] = {0}; snprintf(buf, sizeof(buf), src); printf("strlen(STR) = %d\n", strlen(STR)); printf("sizeof(STR) = %d\n", sizeof(STR)); printf("strlen(src) = %d\n", strlen(src)); printf("sizeof(src) = %d\n", sizeof(src)); printf("strlen(buf) = %d\n", strlen(buf)); printf("sizeof(buf) = %d\n", sizeof(buf)); printf("src = %s\n", src); printf("buf = %s\n", buf); return 0; }
我們先來分析下這個程序,第6行定義了一個宏,但是它里面有兩個 \0,實(shí)際上是3個,因?yàn)榫幾g器還會為字符串自動去分配個 \0。在程序的第11行進(jìn)行 src 到 buf 的內(nèi)容復(fù)制。我們在上屆說過字符數(shù)組是以 \0 結(jié)尾的,因此第13行打印的長度為7。但第14行打印的是它整個宏定義的長度,所以為15。第16行打印的也便是 7 了,第17行打印的指針的長度,便是4。第19行打印的 buf 中內(nèi)容的長度同樣也是 7,第20行打印的 數(shù)組 buf 的長度便是 255。第22和23行分別打印 src 和 buf 中的內(nèi)容,便是 hello 了。我們來看看編譯結(jié)果
結(jié)果和我們分析的一致,字符串字面量的本質(zhì)為數(shù)組。
C、再來看第三個示例程序,代碼如下
#include <stdio.h> #include <string.h> int main() { #define s1 "hello world" #define s2 "hello world" if( s1 == s2 ) { printf("Equal\n"); } else { printf("Non Equal\n"); } if( strcmp(s1, s2) == 0) { printf("Equal\n"); } else { printf("Non Equal\n"); } return 0; }
我們先來分析下,我們在第6和7行分別定義了兩個宏字符串(但是它們的內(nèi)容是相同的)。接下來我們直接將 s1 和 s2 進(jìn)行判斷是否相等。那么在這塊我們判斷的應(yīng)當(dāng)是他兩的地址,它們在這塊就是數(shù)組,兩個數(shù)組怎么可能進(jìn)行相等比較呢。如果是判斷地址,第一個 if 語句應(yīng)當(dāng)打印出不相等的。下面的 if 語句是用 strcmp 函數(shù)進(jìn)行判斷的餓,那么這個當(dāng)然是相等的啦,因?yàn)檫@個函數(shù)判斷的是他兩的內(nèi)容。所以經(jīng)我們分析,第一個 if 語句打印出 Non Equal,第二個 if 語句打印出 Equal。我們來看看編譯器就是是怎么處理的
我們看到第一個和我們分析的不一樣,那么我們再來看看 BCC 編譯器
那么 BCC 編譯器的結(jié)果和我們分析的是一致的。在 gcc 編譯器中它做了優(yōu)化,當(dāng)我們定義 s1 之后,進(jìn)行 s2 的定義時。編譯器發(fā)現(xiàn)他倆內(nèi)容是一樣的,便將 s2 也指向了 s1 的地址,因?yàn)樗X得你是在浪費(fèi)內(nèi)存。我們在程序中加上打印 s1 和 s2 的地址的語句,gcc 打印結(jié)果如下
gcc 編譯器果然是將他倆放在一個地址上了。但是我們看看 BCC 呢
我們看到 BCC 是這樣的,所以我們在以后不能寫出依賴于某種編譯器的代碼,這樣的話,代碼的可移植性就降低了。所以我們在進(jìn)行字符串之間的相等比較時需要用 strcmp 完成,不可直接用 == 進(jìn)行字符串直接進(jìn)行比較。完全相同的媳婦吃字面量的 == 比較結(jié)果為 false。一些現(xiàn)代編譯器能夠?qū)⑾嗤淖址置媪坑成涞酵粋€無名字符數(shù)組,因此 == 比較結(jié)果為 true。
D、最后我們再來看個關(guān)于字符串循環(huán)右移的問題,這也是一道筆試面試題。代碼如下
#include <stdio.h> #include <string.h> void right_shift_r(const char* src, char* result, unsigned int n) { const unsigned int len = strlen(src); int i = 0; for(i=0; i<len; i++) { result[(i+n) % len] = src[i]; } result[len] = '\0'; } int main() { char result[255] = {0}; right_shift_r("abcde", result, 2); printf("%s\n", result); right_shift_r("abcde", result, 5); printf("%s\n", result); right_shift_r("abcde", result, 8); printf("%s\n", result); return 0; }
我們可以利用求余的的方式進(jìn)行字符串的賦值。那么我們用一個 for 循環(huán)就完成右移,它的時間復(fù)雜度為 O(n),這個效率無疑是最高的。
歡迎大家一起來學(xué)習(xí) C 語言,可以加我QQ:243343083。
當(dāng)前標(biāo)題:C之典型字符串(二十八)
網(wǎng)頁路徑:http://jinyejixie.com/article28/poescp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供云服務(wù)器、網(wǎng)站營銷、網(wǎng)站設(shè)計(jì)、網(wǎng)站維護(hù)、自適應(yīng)網(wǎng)站、做網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)