C语言复习—模拟实现C库函数、atoi

模拟实现C语言库函数

str库函数

\#include <stdio.h>
\#include <stdlib.h>
\#include <assert.h>

1.模拟实现strcpy
将源字符串src拷贝赋值到目标字符串dest中

char *my_strcpy(char *dest, const char* src)
{
    assert(dest);
    assert(src); 
    char *ret = dest;
    while (*dest++ = *src++)
        ;
    return ret;
}

2.模拟实现strlen
从字符串起始位置开始到\0结束,结果不包括\0的长度

一、计数法
int my_strlen(const char* str)
{
    assert(str);

    int count = 0;
    while (*str)
    {
        count++;
        str++;
    }
    return count;
}

二、指针相减法
int my_strlen2(const char* str)
{
    assert(str);

    const char*ptr = str;
    while (*str)
    {
        str++;
    }
    return str - ptr;
}

三、递归法
int my_strlen3(const char* str)
{
    assert(str);

    if (*str)
    {
        return 1 + my_strlen3(str+1);
    }
    return 0;
}

3.模拟实现strcat
字符串追加函数,先让目标字符串指针指到字符串末尾,然后加上源字符串

char* my_strcat(char* dest, const char* src)
{
    assert(dest);
    assert(src);

    char* ptr = dest;
    while (*dest)
    {
        dest++;
    }
    while (*dest++ = *src++)
    {
        ;
    }
    return ptr;
}

4.模拟实现strcmp
比较每一位字符的ASCII码值,返回值为0说明相等

int my_strcmp(char* dest, const char* src)
{
    assert(dest);
    assert(src);

    while ((*dest == *src) && (*dest != '\0'))
    {
        dest++;
        src++;
    }
    return *dest - *src;   //返回相应字符ASCII码之差
}

5.模拟实现strstr
在str1中查找str2,找到了返回第一次出现的位置

char *my_strstr(const char* str1, const char* str2)
{
    assert(str1);
    assert(str2); 
    if (*str2 == '\0')
    {
        return (char*)str1;
    }
    while (*str1 != '\0')
    {
        const char* p1 = str1;
        const char* p2 = str2;
        while ((*p2 != '\0') && (*p1 == *p2))
        {
            p1++;
            p2++;

            if (*p2 == '\0')
            {
                return (char*)str1;
            }
        }
        str1++;
    }
    return NULL;
}

6.模拟实现strchr
在str中查找字符ch第一次出现的位置,返回字符位置指针

char* my_strchr(const char* str, char ch)
{
    assert(str);
    while (*str != '\0')
    {
        if (*str == ch)
        {
            return (char*)str;
        }
        str++;
    }
    return NULL;
}

7.模拟实现strrchr
/在字符串str中查找字符ch最后一次出现的位置,返回字符位置指针

一、从前往后找
char *my_strrchr(const char* str, char ch)
{
    assert(str);
    char* pos = 0;           //记录位置的指针变量
    while (*str != '\0')
    {
        if (*str == ch)
        {
            pos = str;
            str++; 
        }
        else
        {
            str++;
        }
    }
    if (pos == 0)
        return NULL;
    else
        return pos;
}

二、从后往前找
char* my_strrchr2(const char* str, char ch, int len)
{
    assert(str);
    str = str + len - 1;
    while (*str != '\0')
    {
        if (*str == ch)
        {
            return str;
        }
        str--;
    }
    return NULL;
}

8.模拟实现strncpy
从源字符串src中拷贝n个字符赋值到目标字符串dest中

char* my_strncpy(char* dest, const char*src, int n)
{
    assert(dest);
    assert(src);

    char* ret = dest;
    while (n)
    {
        *dest++ = *src++;
        if ('\0' == *src)
        {
            dest++;
        }
        n--;
    }
    return ret;
}

9.模拟实现strncat
先让目标字符串指针指到字符串末尾,然后加上源字符串中的n个字符

char* my_strncat(char* dest, const char* src, int n)
{
    assert(dest);
    assert(src);
    char* ret = dest;
    while (*dest != '\0')
    {
        dest++;
    }
    while (n)
    {
        *dest++ = *src++;
        if (*src == '\0')
        {
            break;
        }
        n--;
    }
    return ret;
}

10.模拟实现strncmp
比较两个字符串中的n个字符的ASCII码

char* my_strncmp(const char* dest, const char* src, int n)
{
    assert(dest);
    assert(src);

    while (n && (*dest++ == *src++))
    {
        if (*src == '\0')
        {
            return 0;
        }
        n--;
    }
    if (n == 0)
    {
        return 0;
    }
    if (*dest > *src)
    {
        return 1;
    }
    else
        return -1;
}

11.模拟实现strlwr、strupr
转化字符大小写

char* my_strlwr(char* src)        //将字符全部转化为小写
{
    assert(src);
    char *ret = src;
    while (*src != '\0')
    {
        if (*src >= 'A' && *src <= 'Z')
        {
            *src += 0x20;
        }
        src++;
    }
    return ret;
}

char* my_strupr(char* src)        //将字符全部转化为大写
{
    assert(src);
    char*ret = src;
    while (*ret != '\0')
    {
        if (*ret >= 'a' && *ret <= 'z')
        {
            *ret = *ret - 32;
        }
        ret++;

    }

    return src;
}
内存操作函数

1.模拟实现memcpy
src和dest是指向内存中的两块空间,从内存中的src位置开始复制num个字节到dest位置,返回指向dest的指针,可能会存在内存重叠问题

void *my_memcpy(void* dest, const void* src, size_t num)
{
    assert(dest);
    assert(src);

    void* ret = dest;
    char* pdest = (char*)dest;
    char* psrc = (char*)src;

    while (num--)
    {
        *pdest++ = *psrc++;
    }
    return ret;
}

2.模拟实现memmove
可以有效的解决内存重叠,只要二者之间的内存空间间隔在num个字节之外

void* my_memmove(void *dest, const void *src, size_t num)
{
    assert(dest);
    assert(src);

    void* ret = dest;
    char* pdest = (char*)dest;
    char* psrc = (char*)src;
    if (pdest <= psrc && pdest >= psrc + num)    //正常情况下从前往后拷贝
    {
        while (num--)
        {
            *pdest++ = *psrc++;
        }
    }
    else
    {
        while (num--)
        {
            *(pdest + num) = *(psrc + num);       //出现内存覆盖时从后往前拷贝
        }
    }
    return ret;
}
模拟实现atoi函数

atoi函数是将字符串转化为整型,函数原型是:
int atoi(con​​st char * str);
在实现这个函数时,应该考虑以下问题:
1.空字符串
2.前面有空格
3.正负号
4.异常字符
5.输出数据溢出问题

enum State{
    NORMAL,
    ABNORMAL
}state;
state = ABNORMAL;    //初始化为异常状态

int my_atoi(const char* str)
{
    assert(str);
    int flag = 1;    //记录为正
    long long ret = 0;

    while (*str == ' ')      //跳过空格字符
    {
        str++;
    }

    if ((*str == '+') || (*str == '-'))   //判断正负号
    {
        if (*str == '+')
        {
            str++;
        }
        else
        {
            flag = -1;
            str++;  
        }
    }
    if (*str == '\0')
    {
        return 0;
    }

    while (*str != '\0')
    {
        if ((*str >= '0') && (*str <= '9'))
        {
            ret = ret * 10 + flag*(*str - '0');
            if ((ret > INT_MAX) || (ret < INT_MIN))
            {
                ret = 0;
                break;
            }
        }
        else            //如果是异常字符,直接返回
            break;
        str++;
    }
    if (*str == '\0')
    {
        state = NORMAL;   //走完了 说明字符串无异常
    }
    return (int)ret;
}
测试代码
int main()
{
    //char arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    //char arr2[10] = { 1,2,3,4,5,7,4 };
    //int i = 0;
    ////my_memcpy(arr1, arr2, 10);
    //my_memmove(arr1, arr2, 10);
    //for (i = 0; i < 10; i++)
    //{
    //  printf("%d ", arr1[i]);
    //}
    char* arr[10] = { 0 };
    char* p = "-1234";
    char* q = "     345";
    char* r = "67rg";
    char* c = "abcdef";
    char* s = "";
    char* t = NULL;
    char* u = "2200000000";
    char* v = "-2000000000"; 
    int tmp = my_atoi(c);
    printf("%d\n", tmp);

    system("pause");
    return 0;
}


//int main()
//{
//  char arr1[20] = "ADFGBDabcd";
//  char arr2[10] = "qwer";
//  char *p = "qwerqasddggfh";
//  char *q = "qwer ";
//  char *s = "Hello World!";
//
//  //char* ch = my_strcpy(arr, p);
//  //int ret = my_strlen3(p);
//  //char* str = my_strcat(arr, p);
//  /*int ret = my_strncmp(p, q, 5);
//  if (ret == 0)
//      printf("p等于q\n");
//  else if (ret < 0)
//      printf("p小于q\n");
//  else{
//      printf("p大于q\n");
//  }*/
//
//  char* str3 = my_strlwr(arr1);
//  printf("%s\n", str3);
//
//
//  /*char* str4 = my_strupr(arr1);
//  printf("%s\n", str4);*/
//
//
//  /*char* str = my_strncpy(arr1, arr2, 4);
//  printf("%s\n", str);*/
//
//  //char* str1 = my_strncat(arr1, arr2, 4);
//  //printf("%s\n", str1);
//  //char *ch = my_strchr(p, 'a');
//  //printf("%s\n", ch);
//
//  //char *chend = my_strrchr(p, 'd');
//  //printf("%s\n", chend);
//
//  //char *chend2 = my_strrchr(p, 'd', my_strlen(p));
//  //printf("%s\n", chend);
//  ////char* ret = my_strstr(p, q);
//  //printf("%s\n", ret);
//
//  //printf("%s\n", ch);
//  //printf("%d\n", ret);
//  //printf("%s\n", str);
//  system("pause");
//  return 0;
//}

猜你喜欢

转载自blog.csdn.net/qq_40840459/article/details/81331904