摘要:四函數字符串追加函數介紹函數的返回值類型為,可以返回被追加的字符串的起始地址。利用函數所需的頭文件函數的使用代碼運行結果為函數的特點及注意事項源字符串必須以結束。目標空間必須有足夠的大,能容納下源字符串的內容。
strlen函數是用于求字符串長度的(不包括/0),例如字符串“abc”的長度為3,在代碼中我們如何使用strlen函數呢?
#include int main(){ const char*str1 = "abcdef"; const char*str2 = "bbb"; if(strlen(str2)-strlen(str1)>0) { printf("str2>str1/n"); } else { printf("srt1>str2/n"); } return 0; }
程序結果如圖:
我們的程序的結果可能會感到吃驚,字符串str2的長度為3,字符串str1的長度為6,那為什么最后打印的卻是str2>str1呢?
經過查閱資料發現,strlen函數返回值的類型為size_t(無符號整型),因此無符號整型之間的運算結果仍然是無符號整型。3-6的確等于-3,而最終打印的是-3的補碼,而-3是二進制原碼得到的。-3的原碼為10000000000000000000000000000011而-3的補碼為01111111111111111111111111111101,是個正數,因此strlen(str2)-strlen(str1)的結果是大于0的。
strlen的特點及注意事項:
方法一:計數器法
#include #include int my_strlen(const char* str){ int count = 0; while (*str++!="/0") { count++; } return count;}int main(){ char* str1 = "abcdef"; int ret = my_strlen(str1); printf("%d", ret); return 0;}
代碼運行結果:(以下的運行結果跟下圖一致)
方法二:遞歸方法
#include #include int my_strlen(const char* str){ if(*str == "/0") return 0; else return 1+my_strlen(str+1);}int main(){ char* str = "abcdef"; int ret = my_strlen(str); printf("%d", ret); return 0;}
方法三:指針減指針的方式
int my_strlen(char *s) { char *p = s; while(*p != ‘/0’ ) p++; return p-s; }int main(){ char* str = "abcdef"; int ret = my_strlen(str); printf("%d", ret); return 0;}
先看strcpy函數的返回值類型與傳值。
查閱資料我們可以看到,strcpy函數傳入的第一個參數為目標地址處,第二個參數為源地址處,返回值類型為char*類型。
例如以下代碼:
#include #include int main(){ char str1[20] = "abcdef"; char str2[] = "zjr"; strcpy(str1, str2); printf("%s", str1); return 0;}
代碼執行結果如圖:
strpy函數的特點及注意事項:
char *my_strcpy(char *dest, const char*src){ char *ret = dest; assert(dest != NULL); assert(src != NULL); while((*dest++ = *src++)) { ; } return ret;}#include #include int main(){ char str1[20] = "abcdef"; char str2[] = "zjr"; my_strcpy(str1, str2); printf("%s", str1); return 0;}
在my_strcpy函數的形參中的源字符串地址使用了const的原因是:保證修改的是目的地字符串的內容而不是源字符串的內容。my_strcpy函數內部使用了assert函數的目的是保證傳入的目的地字符串地址與源字符串地址都不為空指針,如果為空指針則程序代碼執行時會報錯。
如上代碼運行結果為:
簡單介紹下assert函數:
頭文件為assert.h
傳入的為空指針就會報錯,否則不影響程序執行。
strcat函數的返回值類型為char*,可以返回被追加的字符串的起始地址。而第一個參數為目的地字符串的地址,第二個參數為源字符串的地址。
利用strcat函數所需的頭文件:
strcat函數的使用:
#include #include int main(){ char str1[20] = "abcd"; char str2[] = "efgh"; char* ret = strcat(str1, str2); printf("%s", ret); return 0;}
代碼運行結果為:
strcat函數的特點及注意事項:
char *my_strcat(char *dest, const char*src)//保證源字符串不被修改 { char *ret = dest; assert(dest != NULL); assert(src != NULL); while(*dest) { dest++;//先到目的地字符串的/0地址處 } while((*dest++ = *src++))//先解引用后++,因此最后能將源字符串內的/0也追加進去 { ; } return ret; }#include #include int main(){ char str1[20] = "abcd"; char str2[] = "efgh"; char* ret = my_strcat(str1, str2); printf("%s", ret); return 0;}
代碼執行結果:
strcmp函數的返回值類型為int,第一個參數為一個字符串首字母的地址,第二個參數為另一個字符串首字母的地址,依次往后作比較,這strcmp函數比較的是字符串的內容,而不是字符串的長度。
對于strcmp函數的返回值,C語言規定如果第一個字符串的內容小于第二個字符串的內容,則返回小于0的值;如果第一個字符串的內容等于第二個字符串的內容,則返回0,如果第一個字符串的內容大于第二個字符串的內容,則返回大于0的值。
#include #include int main(){ char str1[] = "abcd"; char str2[] = "abc"; int ret = strcmp(str1, str2); printf("%d", ret); return 0;}
代碼運行結果:(結果雖然返回大于0的值都為1,但是每個編譯器此處規定返回大于0的值有所不同,此處會有差異)。
假如以上例子對strcmp函數是比較字符串內容不夠清晰,以下例子能更好地觀察:
#include #include int main(){ char str1[] = "abcd"; char str2[] = "abq"; int ret = strcmp(str1, str2); printf("%d", ret); return 0;}
代碼運行結果:
#include #include my_strcmp(const char* s1, const char* s2){ assert(s1 && s2); while (*s1 == *s2) { if (*s1 == "/0") return 0; s1++; s2++; } return *s1 - *s2;//比較字符串內容}#include int main(){ char str1[] = "abcd"; char str2[] = "abq"; int ret = my_strcmp(str1, str2); printf("%d", ret); return 0;}
代碼運行結果:
strcpy、strcat、strcmp
都是長度不受限制的字符串函數,所以就顯得不夠安全。所以就有了strncpy、strncat、strncmp
函數。
strncpy函數的返回值類型為char*類型,該函數第一個參數為目的地字符串的首字母地址,第二個參數為源字符串的首字母地址,第三個參數為需要拷貝過去的字符個數。
使用strncpy函數所需的頭文件:
strncpy的使用:
#include #include int main(){ char str1[20] = "abcd"; char str2[] = "kpl"; char* ret = strncpy(str1, str2, 2); printf("%s", ret); return 0;}
代碼運行結果:
#include #include char* my_strncpy(char* dest, char* src, size_t count){ while (count--)//先使用count再減1 { *(dest + count) = *(src + count); } return dest;}int main(){ char str1[20] = "abcd"; char str2[] = "kpl"; char* ret = my_strncpy(str1, str2, 2); printf("%s", ret); return 0;}
strncat函數與其他的受限制的庫函數的返回值類型與參數幾乎一樣,此處不再進行說明。
使用strncat函數所需頭文件:
#include #include #include char* my_strncat(char* dest, char* src, size_t count){ assert(dest && src); char* ret = dest; while (*dest) { dest++;//到目的地字符串的/0位置 } while (count--) { *(dest + count) = *(src + count);//字符串追加 } return ret;}int main(){ char str1[20] = "abcd"; char str2[] = "kpl"; char* ret = my_strncat(str1, str2, 2); printf("%s", ret); return 0;}
strncmp函數的返回值類型為int型,返回值的規則跟strcmp函數相同,此處不再細講。第一個與第二個參數:因為兩個字符串只是用來作比較,如果修改則不滿足strncmp函數的使用規則,因此在前面兩個參數前面加上const保證字符串內容不被修改。第三個參數為比較的字符個數。
使用strncmp函數所需的頭文件:
strncmp函數的使用:
#include #include int main(){ char str1[] = "abcd"; char str2[] = "abkl"; int ret = strncmp(str1, str2, 2); printf("%d", ret); return 0;}
代碼運行結果:
#include #include #include int my_strncmp(char* s1, char* s2, size_t count){ assert(s1 && s2); while (count--) { if (*s1 == *s2) { s1++; s2++; } } return *s1 - *s2;}int main(){ char str1[] = "abcd"; char str2[] = "abkl"; int ret = my_strncmp(str1, str2, 2); printf("%d", ret); return 0;}
代碼執行結果:
strstr函數的返回值類型為char類型,第一個參數是被查找的字符串,第二個參數是在第一個參數中需要查找的字符串。例如:第一個字符串為i am a student,第二個字符串為a,則返回的char類型用字符串形式打印的結果為am a student 。
使用strstr函數所需的頭文件:
strstr函數的使用:
#include #include int main(){ char str1[] = "abcdefdgh"; char str2[] = "d"; char* ret = strstr(str1, str2); printf("%s", ret); return 0;}
代碼執行結果:
#include #include char* my_strstr(const char* str1, const char* str2){ char* s1, * s2; char* cp = str1; if (*str2 == "/0") { return str1; } while (*cp) { s1 = cp; s2 = str2; while (*s1 && *s2 && *s1 == *s2)//開始遍歷尋找 { s1++; s2++; } if (*s2 == "/0") { return cp; } cp++;//當字符查找途中發現有不相同的字符,則從剛開始查找處的下一個字符開始查找 } return NULL;}int main(){