C語言字元串函數及如何實作這些函數
近期在複習C語言字元串相關的知識,在觀看了 翁恺 老師的 C語言程式設計 課程後,打算對C語言标準庫以及 string.h 内的函數進行整理,并寫出自己的實作方式(部分函數涉及系統底層和複雜操作,隻給出簡單的C語言表示形式,數組同樣可以做出相應的函數,但本文以指針角度進行闡釋)。有不足之處還請大神指正。
1.putchar函數(屬于stdio.h庫函數)
函數原型: int putchar( int c )
函數作用:向标準輸出輸出一個字元
函數的傳回值:
- 1:輸出成功
- n( n為整數 ) :輸出了多個字元
- EOF (-1) :輸出失敗
#include <stdio.h>
#undef
int myputchar(int c) {
return fputc(c,stdout);
//fputc函數功能:将字元c寫到檔案指針fp所指向的檔案的目前寫指針的位置,
//fputc函數原型:int fputc (int c, FILE *fp)
}
2.getchar函數(屬于stdio.h庫函數)
函數原型: int putchar( void )
函數作用:向标準輸出讀入一個字元
函數的傳回值:
- 以整數形式傳回讀入的字元
- EOF (-1) :讀入失敗
這裡推薦一篇優質文章,主要講解getchar工作原理
3.strlen函數(屬于string.h庫函數)
函數原型: *size_t strlen( const char s )
函數作用:傳回s的字元串長度
函數的傳回值:整數,表示s的字元串長度,字元串結尾的‘\0’不計入長度。
函數的自實作
int mystrlen(const char *s){
int len = 0;
while( *s != '\0' ){
len++;
s++;
}
return len;
} //使用指針實作
4.strcmp函數(屬于string.h庫函數)
函數原型: **int strcmp( const char s1, const char s2 )
函數作用:比較兩個字元串,并傳回值
函數的傳回值:
- 0 : s1 == s2
- n : s1 > s2 , 且s1與s2內插補點為n(n為正整數)
- -n : s1 < s2 , 且s1與s2的內插補點為-n(n為正整數)
函數的自實作
int mystrcmp(const char *s1, const char *s2){
while(*s1 == *s2 && s1 != '\0'){
s1++;
s2++;
}
return *s1 - *s2;
} //使用指針實作
5.strcpy函數(屬于string.h庫函數)
函數原型: **char *strcpy(char restrict dst, const restrict src)
函數作用:将src的字元串拷貝到dst(注: 關鍵字restrict表示src和dst不重疊(在記憶體中的儲存位置不重疊)(c99))并傳回dst
函數的傳回值:dst (傳回值是為了使該函數能夠參與到其他運算中去)
//使用示例:複制一個字元串
char *dst = (char*)malloc(strlen(src)+1);
//strlen不包含結尾’/0‘的長度,需要在傳回值上+1機關長度
strcpy(dst,src);
函數的自實作
char *mystrcpy(char *dst, const char *src){
while(*src != '\0'){
*dst = *src;
dst++;
src++;
}
*dst = '\0';
return dst;
} //使用指針實作
//在 翁恺 老師的課程中提及此函數有更簡潔的表達方式(不影響編譯和實際效率)
char *mystrcpy(char *dst, const char *src){
while(*dst++ = *src++);
*dst = '\0';
return dst;
}
6.strcat函數(屬于string.h庫函數)
函數原型: **char *strcpy(char restrict s1, const restrict s2)
函數作用:将s2拷貝到s1的後面,将二者拼接為一個長的字元串并傳回s1
函數的傳回值:s1 (必須保證s1具有足夠的空間)
函數的自實作
char *mystrcat(char *s1, const char *s2){
while(*s1 != '\0') s1++;
while(*s1++ = *s2++); //這裡采用更為簡略的寫法
*s1 = '\0';
return s1;
} //使用指針實作
7.strchr函數和strrchr(屬于string.h庫函數)
函數原型: **char strchr(const char s, int c)
函數作用:從左向右搜尋指定字元
函數原型:**char strrchr(const char s, int c)
函數的傳回值:從左/右向右/左搜尋指定字元
- 若字元串中存在該字元,則傳回第一次周遊到的該字元的指針
- 若字元串中不存在該字元,則傳回NULL
函數的自實作
char *mystrchr(const char *s, int c){
while(*s != c && *s != '\0') s++;
return (char*)s;
} //使用指針實作
//(PS:如有更優解決方案請指出,我在嘗試将s++寫進while判斷條件裡的時候遇到了一些問題:)
// while(*s++ != c && *s++ != '\0');
//此語句在執行過程中遇到一些奇怪的問題,比如一些字元(如'e')無法搜尋到,而其他字元能夠正常搜尋到,暫未深究...
//mystrrchr省略,原理大緻相同
8.strstr函數和strcasestr(屬于string.h庫函數)
函數原型: **char *strstr(const char s1, const char s2)
函數作用:搜尋指定字元串(在s1中搜尋s2)
函數原型: **char *strcasestr(const char s1, const char s2)
函數作用:忽略大小寫搜尋指定字元串(在s1中搜尋s2)
函數的傳回值:
- 若str2是str1的子串,則傳回str2在str1的首次出現的位址
- 如果str2不是str1的子串,則傳回NULL
char *strstr(const char *s1,const char *s2)
{
char *p = s1;
const len = strlen(s2);
while((p=strchr(p,*s2))){
if(strncmp(p,s2,len)==0) return (char*)p;
p++;
}
return NULL;
} //使用指針實作,由于展開再寫一遍搜尋函數無意義,先使用string.h裡的部分函數(具體實作方法見前文)
①strncpy
函數原型: **char *strncpy(char restrict dst, char restrict src, size_t n)
②strncat
函數原型: **char *strncat(char restrict s1, char restrict s2, size_t n)
③strncmp
函數原型: **int strncpy(char restrict s1, char restrict s2, size_t n)