常用c语言字符串库函数(自行实现)

    • strlen
    • strcpy
    • strcat
    • strstr
    • strcmp
    • strchr
    • memcpy
    • memmove
    • 优化版冒泡函数
    • 经典的二分查找
    • 求第N个斐波那契数
    • 联合体判断系统大端小端

strlen

#include 
#include 
//利用assert断言防止野指针,循环计数
int my_strlen(const char *arr)
{
    int count = 0;
    assert(arr != NULL);
    while(*arr++ != '\0')
    {
        count++;
    }
    return count;
}
int main()
{
    char arr[] = "hello dear";
    printf("%d\n", my_strlen(arr));
}

strcpy

#include 
#include 
//源字符串const,返回值char *
char * my_strcpy(char * dest, const char * src)
{
    assert(dest);
    assert(src);
    char * ret = dest;
    //++的优先级大于*,但由于是后置,所以先完成解引用赋值后++
    //当src指向\0时表达式为假
    while (*dest++ = *src++) {
    }
    return ret;

}
int main()
{
    char strA[] = "hello";
    char strB[] = "boy";
    printf("%s", my_strcpy(strA, strB));
    system("pause");
}

strcat

#include 
#include 

//源字符串const,返回值char *
char * my_strcat(char * dest, const char * src)
{
    assert(dest);
    assert(src);
    char * ret = dest;
    while (*dest) {
        dest++;
    }
    //++的优先级大于*,但由于是后置,所以先完成解引用赋值后++
    //当src指向\0时表达式为假
    while (*dest++ = *src++) {
    }
    return ret;

}
int main()
{
    char strA[] = "hello";
    char strB[] = "boy";
    printf("%s", my_strcat(strA, strB));
    system("pause");
}

strstr

#include 
#include 

//源字符串const,返回值char *
char * my_strstr(const char * dest, const char * src)
{
    assert(dest);
    assert(src);
    char *pdest = dest;
    char *psrc = src;
    char *pa = dest;
    char *pb = src;
    if (!*pb) {
        return NULL;
    }
    //目标串为空,则其中不包含源串
    while (*pdest) {
        pa = pdest;
        pb = psrc;
        while (*pa && *pb) {
            if (*pa == *pb) {
                pa++;
                pb++;
                continue;
            }
            break;
        }
        if (!*pb) {
            return pdest;
        }
        pdest++;
    }
    return NULL;

}
int main()
{
    char strA[] = "hello123";
    char strB[] = "llo";
    printf("%s", my_strstr(strA, strB));
    system("pause");
}

strcmp

#include 
#include 

int  my_strcmp(const char * dest, const char * src)
{
    assert(dest);
    assert(src);
    //比较到最后只有两个串同时为\0,才会相等
    while (*dest || *src) {
        if (*dest > *src) {
            return 1;
        }
        else if (*dest < *src) {
            return -1;
        }
        dest++;
        src++;
    }
    return 0;
}
int main()
{
    char strA[] = "aBc";
    char strB[] = "ab";
    printf("%d", my_strcmp(strA, strB));
    system("pause");
}

strchr

#include 
#include 

char *  my_strchr(const char * dest, const char ch)
{
    assert(dest);
    while (*dest && ch != *dest) {
        dest++;
    }
    return (*dest == ch )? dest : NULL;
}
int main()
{
    char strA[] = "aBc";
    char ch = 'B';
    printf("%s", my_strchr(strA, ch));
    system("pause");
}

memcpy

#include 
#include 

void * mymcpy(void * dest, const void * src, int count)
{
    assert(dest);
    assert(src);
    void * ret = dest;
    while (count--) {
        *(char *)dest = *(char *)src;
        dest = (char *)dest + 1;
        src = (char *)src + 1;
    }
    return ret;
}
int main()
{
    char strA[] = "aBc";
    char strB[] = "aaa";
    printf("%s", memcpy(strA, strB, 3));
    system("pause");
}

如果src空间地址小于 dest,那么会发生重复拷贝。例如

char strA[] = “aBccc”;
printf(“%s”, memmove(strA+1, strA, 4));

在memmov中考虑这个问题。

memmove

#include 
#include 

void * memmove(void * dest, const void * src, int count)
{
    assert(dest);
    assert(src);
    void * ret = dest;
    //src地址低于dest,或者 src结束地址在dest地址之间
    //从后面往前复制
    if (src < dest || (char*)dest> ((char*)src+count)) {
        dest = (char *)dest + count - 1;
        src = (char *)src + count - 1;
        while (count--) {
            *(char *)dest = *(char *)src;
            dest = (char *)dest - 1;
            src = (char *)src - 1;
        }
    }
    else {
        while (count--) {
            *(char *)dest = *(char *)src;
            dest = (char *)dest + 1;
            src = (char *)src + 1;
        }
    }
    return ret;
}
int main()
{
    char strA[] = "aBccc";
    printf("%s", memmove(strA+1, strA, 4));
    system("pause");
}

优化版冒泡函数

写冒泡函数的要点是整明白冒泡过程,输入数据决定了总共有多少趟,每趟和多少个数字比较,每次比较都是相邻两个数字比,并且一趟排序完必定把符合规则的数字送到数组最后面。

#include 
#include 
void bubble_sort(int arr[], int length)
{
    int i = 0, j = 0;
    int tmp = 0;
    int flag = 1;
    for(i=0; i1; i++){
        flag = 1;
        for(j=0; j1-i; j++){
            if(arr[j] > arr[j+1]){
                tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
                flag = 0;
            }
            if(flag){
                return ;
            }
        }
    }
}
int main()
{
    int i = 0;
    int testArr[10] = {9,8,7,6,5,4,3,2,1};
    int length = sizeof(testArr)/sizeof(testArr[0]);
    bubble_sort(testArr, length);
    for(i=0; i<10; i++){
        printf("%d\t", testArr[i]);
    }
}

经典的二分查找

首先函数参数中必然有数组的大小(传进来的指针不能计算大小),然后循环条件是左小于等于右(防止最后一次左=右找不到),然后mid 没有直接写成 left + right / 2(防止溢出)

#include 

int binary_search(int arr[], int length, int key)
{
    int left = 0, right = length-1;
    while (left <= right)
    {
        int mid = left + ((right - left)>>1);
        if(arr[mid] == key)
        {
            return mid;
        }
        else if (arr[mid] > key)
        {
            right = mid - 1;
        }
        else if (arr[mid] left = mid + 1;
        }
    }
    return -1;
}
int main()
{
    int i = 0;
    int testArr[10] = {1,2,3,4,5,6,7,8,9};
    int length = sizeof(testArr)/sizeof(testArr[0]);
    int key = 6;

    if (binary_search(testArr, length, key) != -1)
    {
        printf("找到了%d, 在%d位置\n", key, binary_search(testArr, length, key));

    }
    else
    {
        printf("未找到");
    }

}

求第N个斐波那契数

注意点是循环条件从3开始

#include 
int n_fib(int nfib)
{
    int a = 1;
    int b = 1;
    int c = 1;
    if(nfib <= 2){
        return 1;
    }
    while(nfib > 2)
    {
        c = a + b;
        a = b;
        b = c;
        nfib--;
    }
    return c;
}
int main()
{
    int nfib = 4;
    printf("第%d个斐波那契数是%d\n", nfib, n_fib(nfib));

}

联合体判断系统大端小端

原理是char 和int 公用一块地址,利用存取权限不同,取出低字节序来判断。

#include 

union UN{
    int i;
    char ch;
};
int check_sys()
{
    union UN Un;
    Un.i = 1;
    return Un.ch;
}
int main()
{
    if(check_sys())
    {
        printf("小端\n");
    }
    else
    {
        printf("大端\n");
    }
}

你可能感兴趣的:(c/c++编程艺术)