<kbd id="9plqc"><label id="9plqc"></label></kbd>

        <th id="9plqc"></th>
        1. <center id="9plqc"><video id="9plqc"></video></center>
          <sub id="9plqc"><form id="9plqc"><pre id="9plqc"></pre></form></sub>
          <nav id="9plqc"><form id="9plqc"><legend id="9plqc"></legend></form></nav>
          字符串 您所在的位置:網(wǎng)站首頁 屬猴的住幾樓好 字符串

          字符串

          2023-12-14 21:46| 來源: 網(wǎng)絡(luò)整理| 查看: 265

          字符串簡介字符串變量的聲明strlen()strcpy()strncpy()strcat()strncat()strcmp()strncmp()sprintf(),snprintf()字符串?dāng)?shù)組字符串簡介

          C 語言沒有單獨的字符串類型,字符串被當(dāng)作字符數(shù)組,即char類型的數(shù)組。比如,字符串“Hello”是當(dāng)作數(shù)組{'H', 'e', 'l', 'l', 'o'}處理的。

          編譯器會給數(shù)組分配一段連續(xù)內(nèi)存,所有字符儲存在相鄰的內(nèi)存單元之中。在字符串結(jié)尾,C 語言會自動添加一個全是二進(jìn)制0的字節(jié),寫作\0字符,表示字符串結(jié)束。字符\0不同于字符0,前者的 ASCII 碼是0(二進(jìn)制形式00000000),后者的 ASCII 碼是48(二進(jìn)制形式00110000)。所以,字符串“Hello”實際儲存的數(shù)組是{'H', 'e', 'l', 'l', 'o', '\0'}。

          所有字符串的最后一個字符,都是\0。這樣做的好處是,C 語言不需要知道字符串的長度,就可以讀取內(nèi)存里面的字符串,只要發(fā)現(xiàn)有一個字符是\0,那么就知道字符串結(jié)束了。

          char localString[10];

          上面示例聲明了一個10個成員的字符數(shù)組,可以當(dāng)作字符串。由于必須留一個位置給\0,所以最多只能容納9個字符的字符串。

          字符串寫成數(shù)組的形式,是非常麻煩的。C 語言提供了一種簡寫法,雙引號之中的字符,會被自動視為字符數(shù)組。

          {'H', 'e', 'l', 'l', 'o', '\0'}// 等價于"Hello"

          上面兩種字符串的寫法是等價的,內(nèi)部存儲方式都是一樣的。雙引號里面的字符串,不用自己添加結(jié)尾字符\0,C 語言會自動添加。

          注意,雙引號里面是字符串,單引號里面是字符,兩者不能互換。如果把Hello放在單引號里面,編譯器會報錯。

          // 報錯'Hello'

          另一方面,即使雙引號里面只有一個字符(比如"a"),也依然被處理成字符串(存儲為2個字節(jié)),而不是字符'a'(存儲為1個字節(jié))。

          如果字符串內(nèi)部包含雙引號,則該雙引號需要使用反斜杠轉(zhuǎn)義。

          "She replied, \"It does.\""

          反斜杠還可以表示其他特殊字符,比如換行符(\n)、制表符(\t)等。

          "Hello, world!\n"

          如果字符串過長,可以在需要折行的地方,使用反斜杠(\)結(jié)尾,將一行拆成多行。

          "hello \world"

          上面示例中,第一行尾部的反斜杠,將字符串拆成兩行。

          上面這種寫法有一個缺點,就是第二行必須頂格書寫,如果想包含縮進(jìn),那么縮進(jìn)也會被計入字符串。為了解決這個問題,C 語言允許合并多個字符串字面量,只要這些字符串之間沒有間隔,或者只有空格,C 語言會將它們自動合并。

          char greeting[50] = "Hello, ""how are you ""today!";// 等同于char greeting[50] = "Hello, how are you today!";

          這種新寫法支持多行字符串的合并。

          char greeting[50] = "Hello, " "how are you " "today!";

          printf()使用占位符%s輸出字符串。

          printf("%s\n", "hello world") 字符串變量的聲明

          字符串變量可以聲明成一個字符數(shù)組,也可以聲明成一個指針,指向字符數(shù)組。

          // 寫法一char s[14] = "Hello, world!";// 寫法二char* s = "Hello, world!";

          上面兩種寫法都聲明了一個字符串變量s。如果采用第一種寫法,由于字符數(shù)組的長度可以讓編譯器自動計算,所以聲明時可以省略字符數(shù)組的長度。

          char s[] = "Hello, world!";

          上面示例中,編譯器會將數(shù)組s的長度指定為14,正好容納后面的字符串。

          字符數(shù)組的長度,可以大于字符串的實際長度。

          char s[50] = "hello";

          上面示例中,字符數(shù)組s的長度是50,但是字符串“hello”的實際長度只有6(包含結(jié)尾符號\0),所以后面空出來的44個位置,都會被初始化為\0。

          字符數(shù)組的長度,不能小于字符串的實際長度。

          char s[5] = "hello";

          上面示例中,字符串?dāng)?shù)組s的長度是5,小于字符串“hello”的實際長度6,這時編譯器會報錯。因為如果只將前5個字符寫入,而省略最后的結(jié)尾符號\0,這很可能導(dǎo)致后面的字符串相關(guān)代碼出錯。

          字符指針和字符數(shù)組,這兩種聲明字符串變量的寫法基本是等價的,但是有兩個差異。

          第一個差異是,指針指向的字符串,在 C 語言內(nèi)部被當(dāng)作常量,不能修改字符串本身。

          char* s = "Hello, world!";s[0] = 'z'; // 錯誤

          上面代碼使用指針,聲明了一個字符串變量,然后修改了字符串的第一個字符。這種寫法是錯的,會導(dǎo)致難以預(yù)測的后果,執(zhí)行時很可能會報錯。

          如果使用數(shù)組聲明字符串變量,就沒有這個問題,可以修改數(shù)組的任意成員。

          char s[] = "Hello, world!";s[0] = 'z';

          為什么字符串聲明為指針時不能修改,聲明為數(shù)組時就可以修改?原因是系統(tǒng)會將字符串的字面量保存在內(nèi)存的常量區(qū),這個區(qū)是不允許用戶修改的。聲明為指針時,指針變量存儲的值是一個指向常量區(qū)的內(nèi)存地址,因此用戶不能通過這個地址去修改常量區(qū)。但是,聲明為數(shù)組時,編譯器會給數(shù)組單獨分配一段內(nèi)存,字符串字面量會被編譯器解釋成字符數(shù)組,逐個字符寫入這段新分配的內(nèi)存之中,而這段新內(nèi)存是允許修改的。

          為了提醒用戶,字符串聲明為指針后不得修改,可以在聲明時使用const說明符,保證該字符串是只讀的。

          const char* s = "Hello, world!";

          上面字符串聲明為指針時,使用了const說明符,就保證了該字符串無法修改。一旦修改,編譯器肯定會報錯。

          第二個差異是,指針變量可以指向其它字符串。

          char* s = "hello";s = "world";

          上面示例中,字符指針可以指向另一個字符串。

          但是,字符數(shù)組變量不能指向另一個字符串。

          char s[] = "hello";s = "world"; // 報錯

          上面示例中,字符數(shù)組的數(shù)組名,總是指向初始化時的字符串地址,不能修改。

          同樣的原因,聲明字符數(shù)組后,不能直接用字符串賦值。

          char s[10];s = "abc"; // 錯誤

          上面示例中,不能直接把字符串賦值給字符數(shù)組變量,會報錯。原因是字符數(shù)組的變量名,跟所指向的數(shù)組是綁定的,不能指向另一個地址。

          為什么數(shù)組變量不能賦值為另一個數(shù)組?原因是數(shù)組變量所在的地址無法改變,或者說,編譯器一旦為數(shù)組變量分配地址后,這個地址就綁定這個數(shù)組變量了,這種綁定關(guān)系是不變的。C 語言也因此規(guī)定,數(shù)組變量是一個不可修改的左值,即不能用賦值運算符為它重新賦值。

          想要重新賦值,必須使用 C 語言原生提供的strcpy()函數(shù),通過字符串拷貝完成賦值。這樣做以后,數(shù)組變量的地址還是不變的,即strcpy()只是在原地址寫入新的字符串,而不是讓數(shù)組變量指向新的地址。

          char s[10];strcpy(s, "abc");

          上面示例中,strcpy()函數(shù)把字符串a(chǎn)bc拷貝給變量s,這個函數(shù)的詳細(xì)用法會在后面介紹。

          strlen()

          strlen()函數(shù)返回字符串的字節(jié)長度,不包括末尾的空字符\0。該函數(shù)的原型如下。

          // string.hsize_t strlen(const char* s);

          它的參數(shù)是字符串變量,返回的是size_t類型的無符號整數(shù),除非是極長的字符串,一般情況下當(dāng)作int類型處理即可。下面是一個用法實例。

          char* str = "hello";int len = strlen(str); // 5

          strlen()的原型在標(biāo)準(zhǔn)庫的string.h文件中定義,使用時需要加載頭文件string.h。

          #include #include int main(void) { char* s = "Hello, world!"; printf("The string is %zd characters long.\n", strlen(s));}

          注意,字符串長度(strlen())與字符串變量長度(sizeof()),是兩個不同的概念。

          char s[50] = "hello";printf("%d\n", strlen(s)); // 5printf("%d\n", sizeof(s)); // 50

          上面示例中,字符串長度是5,字符串變量長度是50。

          如果不使用這個函數(shù),可以通過判斷字符串末尾的\0,自己計算字符串長度。

          int my_strlen(char *s) { int count = 0; while (s[count] != '\0') count++; return count;} strcpy()

          字符串的復(fù)制,不能使用賦值運算符,直接將一個字符串賦值給字符數(shù)組變量。

          char str1[10];char str2[10];str1 = "abc"; // 報錯str2 = str1; // 報錯

          上面兩種字符串的復(fù)制寫法,都是錯的。因為數(shù)組的變量名是一個固定的地址,不能修改,使其指向另一個地址。

          如果是字符指針,賦值運算符(=)只是將一個指針的地址復(fù)制給另一個指針,而不是復(fù)制字符串。

          char* s1;char* s2;s1 = "abc";s2 = s1;

          上面代碼可以運行,結(jié)果是兩個指針變量s1和s2指向同一字符串,而不是將字符串s1的內(nèi)容復(fù)制給s2。

          C 語言提供了strcpy()函數(shù),用于將一個字符串的內(nèi)容復(fù)制到另一個字符串,相當(dāng)于字符串賦值。該函數(shù)的原型定義在string.h頭文件里面。

          strcpy(char dest[], const char source[])

          strcpy()接受兩個參數(shù),第一個參數(shù)是目的字符串?dāng)?shù)組,第二個參數(shù)是源字符串?dāng)?shù)組。復(fù)制字符串之前,必須要保證第一個參數(shù)的長度不小于第二個參數(shù),否則雖然不會報錯,但會溢出第一個字符串變量的邊界,發(fā)生難以預(yù)料的結(jié)果。第二個參數(shù)的const說明符,表示這個函數(shù)不會修改第二個字符串。

          #include #include int main(void) { char s[] = "Hello, world!"; char t[100]; strcpy(t, s); t[0] = 'z'; printf("%s\n", s); // "Hello, world!" printf("%s\n", t); // "zello, world!"}

          上面示例將變量s的值,拷貝一份放到變量t,變成兩個不同的字符串,修改一個不會影響到另一個。另外,變量t的長度大于s,復(fù)制后多余的位置(結(jié)束標(biāo)志\0后面的位置)都為隨機(jī)值。

          strcpy()也可以用于字符數(shù)組的賦值。

          char str[10];strcpy(str, "abcd");

          上面示例將字符數(shù)組變量,賦值為字符串“abcd”。

          strcpy()的返回值是一個字符串指針(即char*),指向第一個參數(shù)。

          char* s1 = "beast";char s2[40] = "Be the best that you can be.";char* ps;ps = strcpy(s2 + 7, s1);puts(s2); // Be the beastputs(ps); // beast

          上面示例中,從s2的第7個位置開始拷貝字符串beast,前面的位置不變。這導(dǎo)致s2后面的內(nèi)容都被截去了,因為會連beast結(jié)尾的空字符一起拷貝。strcpy()返回的是一個指針,指向拷貝開始的位置。

          strcpy()返回值的另一個用途,是連續(xù)為多個字符數(shù)組賦值。

          strcpy(str1, strcpy(str2, "abcd"));

          上面示例調(diào)用兩次strcpy(),完成兩個字符串變量的賦值。

          另外,strcpy()的第一個參數(shù)最好是一個已經(jīng)聲明的數(shù)組,而不是聲明后沒有進(jìn)行初始化的字符指針。

          char* str;strcpy(str, "hello world"); // 錯誤

          上面的代碼是有問題的。strcpy()將字符串分配給指針變量str,但是str并沒有進(jìn)行初始化,指向的是一個隨機(jī)的位置,因此字符串可能被復(fù)制到任意地方。

          如果不用strcpy(),自己實現(xiàn)字符串的拷貝,可以用下面的代碼。

          char* strcpy(char* dest, const char* source) { char* ptr = dest; while (*dest++ = *source++); return ptr;}int main(void) { char str[25]; strcpy(str, "hello world"); printf("%s\n", str); return 0;}

          上面代碼中,關(guān)鍵的一行是while (*dest++ = *source++),這是一個循環(huán),依次將source的每個字符賦值給dest,然后移向下一個位置,直到遇到\0,循環(huán)判斷條件不再為真,從而跳出循環(huán)。其中,*dest++這個表達(dá)式等同于*(dest++),即先返回dest這個地址,再進(jìn)行自增運算移向下一個位置,而*dest可以對當(dāng)前位置賦值。

          strcpy()函數(shù)有安全風(fēng)險,因為它并不檢查目標(biāo)字符串的長度,是否足夠容納源字符串的副本,可能導(dǎo)致寫入溢出。如果不能保證不會發(fā)生溢出,建議使用strncpy()函數(shù)代替。

          strncpy()

          strncpy()跟strcpy()的用法完全一樣,只是多了第3個參數(shù),用來指定復(fù)制的最大字符數(shù),防止溢出目標(biāo)字符串變量的邊界。

          char* strncpy( char* dest, char* src, size_t n);

          上面原型中,第三個參數(shù)n定義了復(fù)制的最大字符數(shù)。如果達(dá)到最大字符數(shù)以后,源字符串仍然沒有復(fù)制完,就會停止復(fù)制,這時目的字符串結(jié)尾將沒有終止符\0,這一點務(wù)必注意。如果源字符串的字符數(shù)小于n,則strncpy()的行為與strcpy()完全一致。

          strncpy(str1, str2, sizeof(str1) - 1);str1[sizeof(str1) - 1] = '\0';

          上面示例中,字符串str2復(fù)制給str1,但是復(fù)制長度最多為str1的長度減去1,str1剩下的最后一位用于寫入字符串的結(jié)尾標(biāo)志\0。這是因為strncpy()不會自己添加\0,如果復(fù)制的字符串片段不包含結(jié)尾標(biāo)志,就需要手動添加。

          strncpy()也可以用來拷貝部分字符串。

          char s1[40];char s2[12] = "hello world";strncpy(s1, s2, 5);s1[5] = '\0';printf("%s\n", s1); // hello

          上面示例中,指定只拷貝前5個字符。

          strcat()

          strcat()函數(shù)用于連接字符串。它接受兩個字符串作為參數(shù),把第二個字符串的副本添加到第一個字符串的末尾。這個函數(shù)會改變第一個字符串,但是第二個字符串不變。

          該函數(shù)的原型定義在string.h頭文件里面。

          char* strcat(char* s1, const char* s2);

          strcat()的返回值是一個字符串指針,指向第一個參數(shù)。

          char s1[12] = "hello";char s2[6] = "world";strcat(s1, s2);puts(s1); // "helloworld"

          上面示例中,調(diào)用strcat()以后,可以看到字符串s1的值變了。

          注意,strcat()的第一個參數(shù)的長度,必須足以容納添加第二個參數(shù)字符串。否則,拼接后的字符串會溢出第一個字符串的邊界,寫入相鄰的內(nèi)存單元,這是很危險的,建議使用下面的strncat()代替。

          strncat()

          strncat()用于連接兩個字符串,用法與strcat()完全一致,只是增加了第三個參數(shù),指定最大添加的字符數(shù)。在添加過程中,一旦達(dá)到指定的字符數(shù),或者在源字符串中遇到空字符\0,就不再添加了。它的原型定義在string.h頭文件里面。

          char* strncat( const char* dest, const char* src, size_t n);

          strncat()返回第一個參數(shù),即目標(biāo)字符串指針。

          為了保證連接后的字符串,不超過目標(biāo)字符串的長度,strncat()通常會寫成下面這樣。

          strncat( str1, str2, sizeof(str1) - strlen(str1) - 1);

          strncat()總是會在拼接結(jié)果的結(jié)尾,自動添加空字符\0,所以第三個參數(shù)的最大值,應(yīng)該是str1的變量長度減去str1的字符串長度,再減去1。下面是一個用法實例。

          char s1[10] = "Monday";char s2[8] = "Tuesday";strncat(s1, s2, 3);puts(s1); // "MondayTue"

          上面示例中,s1的變量長度是10,字符長度是6,兩者相減后再減去1,得到3,表明s1最多可以再添加三個字符,所以得到的結(jié)果是MondayTue。

          strcmp()

          如果要比較兩個字符串,無法直接比較,只能一個個字符進(jìn)行比較,C 語言提供了strcmp()函數(shù)。

          strcmp()函數(shù)用于比較兩個字符串的內(nèi)容。該函數(shù)的原型如下,定義在string.h頭文件里面。

          int strcmp(const char* s1, const char* s2);

          按照字典順序,如果兩個字符串相同,返回值為0;如果s1小于s2,strcmp()返回值小于0;如果s1大于s2,返回值大于0。

          下面是一個用法示例。

          // s1 = Happy New Year// s2 = Happy New Year// s3 = Happy Holidaysstrcmp(s1, s2) // 0strcmp(s1, s3) // 大于 0strcmp(s3, s1) // 小于 0

          注意,strcmp()只用來比較字符串,不用來比較字符。因為字符就是小整數(shù),直接用相等運算符(==)就能比較。所以,不要把字符類型(char)的值,放入strcmp()當(dāng)作參數(shù)。

          strncmp()

          由于strcmp()比較的是整個字符串,C 語言又提供了strncmp()函數(shù),只比較到指定的位置。

          該函數(shù)增加了第三個參數(shù),指定了比較的字符數(shù)。它的原型定義在string.h頭文件里面。

          int strncmp( const char* s1, const char* s2, size_t n);

          它的返回值與strcmp()一樣。如果兩個字符串相同,返回值為0;如果s1小于s2,strcmp()返回值小于0;如果s1大于s2,返回值大于0。

          下面是一個例子。

          char s1[12] = "hello world";char s2[12] = "hello C";if (strncmp(s1, s2, 5) == 0) { printf("They all have hello.\n");}

          上面示例只比較兩個字符串的前5個字符。

          sprintf(),snprintf()

          sprintf()函數(shù)跟printf()類似,但是用于將數(shù)據(jù)寫入字符串,而不是輸出到顯示器。該函數(shù)的原型定義在stdio.h頭文件里面。

          int sprintf(char* s, const char* format, ...);

          sprintf()的第一個參數(shù)是字符串指針變量,其余參數(shù)和printf()相同,即第二個參數(shù)是格式字符串,后面的參數(shù)是待寫入的變量列表。

          char first[6] = "hello";char last[6] = "world";char s[40];sprintf(s, "%s %s", first, last);printf("%s\n", s); // hello world

          上面示例中,sprintf()將輸出內(nèi)容組合成“hello world”,然后放入了變量s。

          sprintf()的返回值是寫入變量的字符數(shù)量(不計入尾部的空字符\0)。如果遇到錯誤,返回負(fù)值。

          sprintf()有嚴(yán)重的安全風(fēng)險,如果寫入的字符串過長,超過了目標(biāo)字符串的長度,sprintf()依然會將其寫入,導(dǎo)致發(fā)生溢出。為了控制寫入的字符串的長度,C 語言又提供了另一個函數(shù)snprintf()。

          snprintf()只比sprintf()多了一個參數(shù)n,用來控制寫入變量的字符串不超過n - 1個字符,剩下一個位置寫入空字符\0。下面是它的原型。

          int snprintf(char*s, size_t n, const char* format, ...);

          snprintf()總是會自動寫入字符串結(jié)尾的空字符。如果你嘗試寫入的字符數(shù)超過指定的最大字符數(shù),snprintf()會寫入 n - 1 個字符,留出最后一個位置寫入空字符。

          下面是一個例子。

          snprintf(s, 12, "%s %s", "hello", "world");

          上面的例子中,snprintf()的第二個參數(shù)是12,表示寫入字符串的最大長度不超過12(包括尾部的空字符)。

          snprintf()的返回值是寫入格式字符串的字符數(shù)量(不計入尾部的空字符\0)。如果n足夠大,返回值應(yīng)該小于n,但是有時候格式字符串的長度可能大于n,那么這時返回值會大于n,但實際上真正寫入變量的還是n-1個字符。如果遇到錯誤,返回一個負(fù)值。因此,返回值只有在非負(fù)并且小于n時,才能確認(rèn)完整的格式字符串寫入了變量。

          字符串?dāng)?shù)組

          如果一個數(shù)組的每個成員都是一個字符串,需要通過二維的字符數(shù)組實現(xiàn)。每個字符串本身是一個字符數(shù)組,多個字符串再組成一個數(shù)組。

          char weekdays[7][10] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};

          上面示例就是一個字符串?dāng)?shù)組,一共包含7個字符串,所以第一維的長度是7。其中,最長的字符串的長度是10(含結(jié)尾的終止符\0),所以第二維的長度統(tǒng)一設(shè)為10。

          因為第一維的長度,編譯器可以自動計算,所以可以省略。

          char weekdays[][10] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};

          上面示例中,二維數(shù)組第一維的長度,可以由編譯器根據(jù)后面的賦值,自動計算,所以可以不寫。

          數(shù)組的第二維,長度統(tǒng)一定為10,有點浪費空間,因為大多數(shù)成員的長度都小于10。解決方法就是把數(shù)組的第二維,從字符數(shù)組改成字符指針。

          char* weekdays[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};

          上面的字符串?dāng)?shù)組,其實是一個一維數(shù)組,成員就是7個字符指針,每個指針指向一個字符串(字符數(shù)組)。

          遍歷字符串?dāng)?shù)組的寫法如下。

          for (int i = 0; i


          【本文地址】

          公司簡介

          聯(lián)系我們

          今日新聞

          推薦新聞

          專題文章
            CopyRight 2018-2019 實驗室設(shè)備網(wǎng) 版權(quán)所有
            黄色免费网站在线看,韩国精品在线观看,韩国美女一区二区,99国产热 新邵县| 南涧| 宜宾县| 凯里市| 阜新市| 德庆县| 台中县| 乐陵市| 扶沟县| 阿合奇县| 徐汇区| 河源市| 巴南区| 布拖县| 江川县| 中方县| 蚌埠市| 怀宁县| 万安县| 济阳县| 武邑县| 阿坝| 宣威市| 怀仁县| 湖南省| 宁蒗| 嫩江县| 中江县| 收藏| 平阴县| 宾阳县| 同心县| 凤台县| 马鞍山市| 天水市| 济阳县| 无为县| 宝清县| 芦溪县| 南宁市| 绍兴县| http://444 http://444 http://444 http://444 http://444 http://444