程式設計實現C庫函式
1.memcpy函式
memcpy 函式用於 把資源記憶體(src所指向的記憶體區域) 拷貝到目標記憶體(dest所指向的記憶體區域);拷貝多少個?有一個size變數控制拷貝的位元組數;
函式原型:void *memcpy(void *dest, void *src, unsigned int count);
用法:可以拷貝任何型別的物件,因為函式的引數型別是void*(未定義型別指標),也就是說傳進去的實參可以是int*,short*,char*等等,但是由於函式拷貝的過程是一個位元組一個位元組的拷貝的,所以實際操作的時候要把void*強制轉化為char*,這樣在指標加的時候才會保證每次加一個位元組;
1 /********memcpy()函式原型為:void* memcpy(void* dest, const void* src, size_t n); 返回指向dest的空型別指標*********/ 2 //返回void* 型別的原因,是為了使用鏈式表達,即strlen((char*)(memcpy(dest,src,n)),這樣可以直接計算dest的長度,是程式程式碼更簡潔 3 /****注意void* 指標的使用,即該函式允許傳入任何型別的指標資料****/ 4 void* memcpy(void *dest,const void *src, size_t n) 5 { 6assert((dest != NULL) && (src != NULL)); 7 char *dest_t = (char*)dest; //轉換成字元型一個個複製拷貝,由於函式拷貝的過程是一個位元組一個位元組的拷貝的, 8 //所以實際操作的時候要把void*強制轉化為char*, 9 char *src_f = (char*)src; //這樣在指標加的時候才會保證每次加一個位元組 10while (n-- > 0) 11 { 12 *(dest_t++) = *(src_f++); 13 } 14 return dest;//void* 一定要返回一個值(指標),這個和void不太一樣!函式返回指向dest的指標 15 16 }
注1:與strcpy相比,memcpy並不是遇到'\0'就結束,而是一定會拷貝完n個位元組。
2:如果目標陣列dest本身已有資料,執行memcpy()後,將覆蓋原有資料(最多覆蓋n)。
//memcpy用來做記憶體拷貝,你可以拿它拷貝任何資料型別的物件,可以指定拷貝的資料長度; char a[100], b[50]; memcpy(b, a,sizeof(b)); //注意如用sizeof(a),會造成b的記憶體地址溢位。 strcpy就只能拷貝字串了,它遇到'\0'就結束拷貝;例: char a[100], b[50]; strcpy(a,b);
2.strcpy函式
寫法一、
1 char * strcpy( char *strDest, const char *strSrc )
2 {
3 assert( (strDest != NULL) && (strSrc != NULL) );//檢測輸入指標是否能訪問
4 char *address = strDest;
5 while( (*strDest++ = * strSrc++) != ‘\0’ ); //複製字串
6 return address;//返回指標
7 }
寫法二、
/********strcpy()函式原型為:char *strcpy(char* dest, const char *src); 返回指向dest的指標*********/
//返回char* 型別的原因,是為了使用鏈式表達,即strlen(strcpy(dest,src)),這樣可以直接計算dest的長度,是程式程式碼更簡潔
char* strcpy(char *dest, char *src)
{
if(dest == NULL || src == NULL)
return NULL;
char *res = dest;//儲存原始dst的首地址
while(*src != '\0')
{
*dest = *src;
dest++;
src++;
}
*dest = '\0';
return res;
}
3.strcat函式
功能:把src所指字串新增到dest結尾處(覆蓋dest結尾處的'\0')。說明:src和dest所指記憶體區域不可以重疊且dest必須有足夠的空間來容納src的字串。返回指向dest的指標。
#include <stdio.h> #include <iostream> using namespace std; char* strcat(char *dest, char *src) { if (dest == NULL) return NULL; if (src == NULL) return dest; char *head = dest; while (*dest != '\0') dest++; while (*src != '\0') { *dest = *src; dest++; src++; } *dest = '\0'; return head; } int main() { char dest[] = "nihao"; char src[] = "zhouyang"; char *res = strcat(dest, src); cout << dest << endl; system("pause"); return 0; }
4.strcmp函式
功能:比較兩個字串大小。
實際上是對字元的ASCII碼進行比較,實現原理如下:首先比較兩個串的第一個字元,若不相等,則停止比較並得出兩個ASCII碼大小比較的結果;如果相等就接著比較第二個字元然後第三個字元等等。無論兩個字串是什麼樣,strcmp函式最多比較到其中一個字串遇到結束符'/0'為止,就能得出結果。
返回結果:①str1小於str2,返回負值或者-1(VC返回-1);②str1等於str2,返回0;③str1大於str2,返回正值或者1(VC返回1);
#include <stdio.h> #include <iostream> #include <assert.h> using namespace std; /****strcmp原型: int strcmp(const char *str1, const char *str2)*****/ int strcmp(const char *str1, const char *str2) { assert((str1 != NULL) && (str2 != NULL)); while ((*str1 != '\0') && (*str2 != '\0')) { if (*str1 == *str2) { str1++; str2++; } else { if (*str1 > *str2) return 1; else return -1; } } if (*str1 == '\0' && *str2 == '\0') return 0; else if (*str1 == '\0' && *str2 != '\0') return -1; else if (*str1 != '\0' && *str2 == '\0') return 1; } int main() { char *str1 = "78"; char *str2 = "789"; int res = strcmp(str1, str2); cout << res << endl; system("pause"); return 0; }
5.strlen函式
功能:返回字串的長度。
#include <stdio.h> #include <iostream> #include <assert.h> using namespace std; /********strlen()函式原型為:int strlen(const char *src); 返回字串的長度*********/ size_t strlen(const char *str) { assert(str != NULL); int num = 0; while(*str != '\0') { str++; num++; } return num; } int main() { char *str = "123456"; int temp = strlen(str); cout << temp << endl; return 0; }
6.strncpy
功能:將字串src中最多n個字元複製到字元陣列dest中(它並不像strcpy一樣遇到NULL才停止複製,而是等湊夠n個字元才開始複製),返回指向dest的指標。
要求:如果n > dest串長度,dest棧空間溢位產生崩潰異常。該函式注意的地方和strcpy類似,但是n值需特別注意。
#include <iostream> #include <stdio.h> using namespace std; /***string.h,char *strncpy(char *dest, const char *src, size_t n), 把src所指向的字串中以src地址開始的前n個位元組複製到dest所指的陣列中,並返回dest。**/ char* mystrncpy(char *dest, const char *src, size_t n) { if (dest == NULL || src == NULL || n < 0) return NULL; char *res = dest; while (n--) { *dest = *src; dest++; src++; } *dest = '\0'; return res; } int main() { char *src = "hello world"; char c[10]; char *res = mystrncpy(c, src, 7); cout << res << endl; system("pause"); return 0; }
7.strstr函式
功能:給出字串str1, str2,判斷str2是否為str1的子字串,如果是,返回str2在str1中對應的起始地址。
#include <stdio.h> #include <iostream> #include <assert.h> using namespace std; /**** 函式原型: extern char *strstr(const char *str1, const char *str2); str1: 被查詢目標 string expression to search. str2: 要查詢物件 The string expression to find. 返回值:若str2是str1的子串,則返回str2在str1的首次出現的地址;如果str2不是str1的子串,則返回NULL。 ****/ const char* strstr(const char *str1, const char *str2) { if (str1== NULL || str2 == NULL) return NULL; const char *temp = str1; const char *res = str2;while (*str1 != '\0') { temp = str1; res = str2; while (*temp== *res){ temp++; res++; } if (*res == '\0')return str1; str1++; } return NULL; } int main() { char *src = "1234567"; char *dest = "345"; const char *res = strstr(src, dest); cout << res<< endl;//cout<<過載了,會直接輸出字串內容而不是地址 system("pause"); return 0; }
8.printf()
寫法一
1 #include <stdio.h> 2 #include <stdarg.h> 3 /* 4 * 函式名: myPrintf 5 * 函式功能: 列印格式字串 6 * 引數: 1. 包含格式符的字串地址 2.可變參 7 * 返回值: 無 8 */ 9 void myPrintf(char *s, ...) 10 { 11 int i = 0; 12 13 /* 可變參第一步 */ 14 va_list va_ptr; 15 16 /* 可變參第二部 */ 17 va_start(va_ptr, s); 18 19 /* 迴圈列印所有格式字串 */ 20 while (s[i] != '\0') 21 { 22 /* 普通字元正常列印 */ 23 if (s[i] != '%') 24 { 25 putchar(s[i++]); 26 continue; 27 } 28 29 /* 格式字元特殊處理 */ 30 switch (s[++i]) // i先++是為了取'%'後面的格式字元 31 { 32 /* 根據格式字元的不同來呼叫不同的函式 */ 33 case 'd': printDeci(va_arg(va_ptr,int)); 34 break; 35 case 'o': printOct(va_arg(va_ptr,unsigned int)); 36 break; 37 case 'x': printHex(va_arg(va_ptr,unsigned int)); 38 break; 39 case 'c': putchar(va_arg(va_ptr,int)); 40 break; 41 case 'p': printAddr(va_arg(va_ptr,unsigned long)); 42 break; 43 case 'f': printFloat(va_arg(va_ptr,double)); 44 break; 45 case 's': printStr(va_arg(va_ptr,char *)); 46 break; 47 default : break; 48 } 49 50 i++; // 下一個字元 51 } 52 53 /* 可變參最後一步 */ 54 va_end(va_ptr); 55 }
寫法二、
1 /*(轉載) 2 * A simple printf function. Only support the following format: 3 * Code Format 4 * %c character 5 * %d signed integers 6 * %i signed integers 7 * %s a string of characters 8 * %o octal 9 * %x unsigned hexadecimal 10 */ 11 int my_printf( const char* format, ...) 12 { 13 va_list arg; 14 int done = 0; 15 16 va_start (arg, format); 17 18 while( *format != '\0') 19 { 20 if( *format == '%') 21 { 22 if( *(format+1) == 'c' ) 23 { 24 char c = (char)va_arg(arg, int); 25 putc(c, stdout); 26 } else if( *(format+1) == 'd' || *(format+1) == 'i') 27 { 28 char store[20]; 29 int i = va_arg(arg, int); 30 char* str = store; 31 itoa(i, store, 10); 32 while( *str != '\0') putc(*str++, stdout); 33 } else if( *(format+1) == 'o') 34 { 35 char store[20]; 36 int i = va_arg(arg, int); 37 char* str = store; 38 itoa(i, store, 8); 39 while( *str != '\0') putc(*str++, stdout); 40 } else if( *(format+1) == 'x') 41 { 42 char store[20]; 43 int i = va_arg(arg, int); 44 char* str = store; 45 itoa(i, store, 16); 46 while( *str != '\0') putc(*str++, stdout); 47 } else if( *(format+1) == 's' ) 48 { 49 char* str = va_arg(arg, char*); 50 while( *str != '\0') putc(*str++, stdout); 51 } 52 53 // Skip this two characters. 54 55 format += 2; 56 } else { 57 putc(*format++, stdout); 58 } 59 } 60 61 va_end (arg); 62 63 return done; 64 }
1 C常用庫函式實現 2 // ---------- strlen ------------- 3 int strlen(char *t){ 4 int length = 0; 5 if(t == NULL) 6 return -1; 7 8 while (*t != '\0') { 9 t++; 10 length++; 11 } 12 return length; 13 } 14 15 size_t strlen(const char *s) 16 { 17 const char *sc; 18 19 for (sc = s; *sc != '\0'; ++sc); 20 21 return sc - s; 22 } 23 24 // ---------- trim ------------- 25 26 void ltrim ( char *s ) 27 { 28 char *p; 29 p = s; 30 while ( *p == ' ' || *p == '\t' ) {p++;} 31 strcpy ( s,p ); 32 } 33 34 void rtrim ( char *s ) 35 { 36 int i; 37 38 i = strlen ( s )-1; 39 while ( ( s[i] == ' ' || s[i] == '\t' ) && i >= 0 ) {i--;}; 40 s[i+1] = '\0'; 41 } 42 43 void trim ( char *s ) 44 { 45 ltrim ( s ); 46 rtrim ( s ); 47 } 48 49 // ---------- strcpy ------------- 50 51 char *strcpy(char *dest, const char *src) 52 { 53 char *tmp = dest; 54 55 while ((*dest++ = *src++) != '\0'); 56 57 return tmp; 58 } 59 60 // ---------- strcat ------------- 61 62 char *strcat(char *dest, const char *src) 63 { 64 char *tmp = dest; 65 66 while (*dest) 67 dest++; 68 while ((*dest++ = *src++) != '\0'); 69 70 return tmp; 71 } 72 73 // ---------- strstr ------------- 74 75 char *strstr(const char *s1, const char *s2) 76 { 77 int l1, l2; 78 79 l2 = strlen(s2); 80 if (!l2) 81 return (char *)s1; 82 l1 = strlen(s1); 83 while (l1 >= l2) { 84 l1--; 85 if (!memcmp(s1, s2, l2)) 86 return (char *)s1; 87 s1++; 88 } 89 90 return NULL; 91 } 92 93 94 // ---------- memcmp ------------- 95 96 int memcmp(char *cs, char *ct, size_t count) 97 { 98 char *su1, *su2; 99 int res = 0; 100 101 for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) 102 if ((res = *su1 - *su2) != 0) 103 break; 104 return res; 105 } 106 107 // ---------- strcmp ------------- 108 109 int strcmp(const char *cs, const char *ct) 110 { 111 unsigned char c1, c2; 112 113 while (1) { 114 c1 = *cs++; 115 c2 = *ct++; 116 if (c1 != c2) 117 return c1 < c2 ? -1 : 1; 118 if (!c1) 119 break; 120 } 121 122 return 0; 123 }