1. 程式人生 > >程式設計實現C庫函式

程式設計實現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 {
 6
assert((dest != NULL) && (src != NULL)); 7 char *dest_t = (char*)dest; //轉換成字元型一個個複製拷貝,由於函式拷貝的過程是一個位元組一個位元組的拷貝的, 8 //所以實際操作的時候要把void*強制轉化為char*, 9 char *src_f = (char*)src; //這樣在指標加的時候才會保證每次加一個位元組 10
while (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 }