標籤:c 指標 字元 字串
第九章字串、字元和位元組
這一塊在初學的時候很容易被大家忽視,但字串作為一種重要的資料類型,沒有在C中顯式的說明。這樣看起來C++定義了string的資料類型實在是帶來了不少福音。
如果想用C玩OJ或者資料結構與演算法的話,這一章需要仔細閱讀,因為這是你僅有能用到的字串處理的標準庫。
總結:
C的字串標準庫使用需要聲明"string.h"。
strlen用於計算一個字串的長度,它的返回值是一個無符號的整數。後面會說可能存在的問題。
strcpy函數把一個字串從一個位置賦值到另一個位置。
strcat函數把一個字串的一份拷貝添加到另一個字串的後面。
strcmp函數對兩個字串進行詞典序的比較。它的返回值提示第一個字串是大於、小於還是等於。
strncpy/strncat/strncmp對應不受限制的版本,它們可以完美判斷是否操作溢出。另外還要加一個長度參數。
strncpy長度指定了多少個字元被寫入到目標字元數組中。
strncat長度制定了從源字串賦值的最大數目,結尾包含‘\0‘。
strcmp長度制定了比較的數目。
關於尋找的字串:
strchr尋找一個字串中的某個字元第一次出現的位置。
strrchr同上,但是返回最後一次出現的位置。
strpbrk在一個字串尋找一個指定字元集中任一字元(不是子串!是任意一個字元!)第一次出現的位置。
strstr是尋找子串第一次出現的位置。
在這裡我不想涉及到進階尋找函數,功能太詭異。
strerror把一個錯誤碼作為它的參數,返回一個指向字串的指標,該字串用於描述這個錯誤。
關於測試和轉換字元的函數:
用它們的意義在於,代碼的移植性可以大大提高。
toupper把一個小寫字母換成大寫字母。
tolower把一個大寫字母換成小寫字母。
iscntrl檢查是不是一個控制字元。
...很多這樣的。。。它們會返回一個整型值,表示真或假。
關於記憶體操作:
memxxx函數提供類似字串的操作,但是遇到NUL時候不會停止操作。同時會包括一個長度參數。
memmove/memcpy賦值指定長度位元組數
memcmp比較
memchr尋找一個特定值
memset將一個序列初始化為一個特定的值。
警告:
1、應該使用有符號數的運算式使用strlen函數。
因為strlen在定義的時候返回值為size_t,這是一個無符號數,所以:
if(strlen(x) >= strlen(y))...
if(strlen(x) - strlen(y) >=0)...
這兩個是可能不相同的,前者會像預想的那樣正常工作,但是後者不能表達一個負數值。
最好將strlen返回值強制轉換為int 。
2、在運算式中混有有符號數和無符號數。
同上。
3、使用strcpy函數把一個長字串賦值到一個較短的數組中,導致溢出。
如果太長,strcpy不會考慮溢出問題,它的操作結果將是覆蓋後面的記憶體空間。
4、使用strcat函數把一個字串添加到一個數組中,導致數組溢出。
同上。
5、把strcmp函數的返回值1和-1進行比較,或者當做布爾值比較。
這是一種不好的風格,最好的的方法是與0進行比較。
if(strcmp(a,b))這樣就是結果很可能a,b是相等的,但是返回一個假。
6、使用並非以NUL字元截尾的字元序列作為以上函數的傳遞值。
比如strcmp、strlen這些函數都是在找NUL作為終止的條件,如果沒有個NUL,返回值將會不確定。
7、使用strncpy函數產生不易NUL位元組結尾的字串。
在使用strncpy函數後,如果複製的長度超過剩餘長度,雖然不會溢出,但是它的結果不會以NUL結尾。
8、把strncpy函數和strxxx族函數混用。
呵呵的警告。
編程提示:
1、不要試圖自己編寫功能相同的函數來取代庫函數。
庫函數有時候用彙編來寫的,從而有最大速度。如果想改進效率,還是看看你的其他代碼吧。
2、使用字元分類和轉換函式可以提高函數的移植性。
C和指標 (pointers on C)——第九章:字串、字元和位元組(上)