C语言字符串相关函数及其实现(部分)

32 阅读2分钟

strlen

// 计数器实现
int my_strlen_count(const char* parr) {
    int count = 0;
    assert(parr);
    while (*parr != '\0') {  // 不严谨,对指针解引用必须是非空指针
        parr++;
        count++;
    }
    return count;
}
// 不允许创建临时变量,用递归
int my_strlen_recursive(const char* parr) {
    if (*parr == '\0')
        return 0;
    return 1 + my_strlen_recursive(parr + 1);
}
// 指针-指针版本
int my_strlen_ptr(const char* parr) {
    assert(parr);
    const char* tmp = parr;
    while (*parr) {  // a
        parr++;
    }
    return parr - tmp;
}
int main() {
    //strlen
    char arr[] = "abc";
    int len = my_strlen_ptr(arr);
    int sz = sizeof(arr);
    printf("%d\n", sz);
    printf("%d\n", len);
    return 0;
}

// 试题
int main() {
    if (strlen("abc") - strlen("abcdefg") > 0) {
        printf(">\n");
    } else {
        printf("<=\n");
    }
    return 0;
}
// 输出结果是>
// size_t strlen(const char* str);
// 返回值是size_t
// C语言中typedef unsigned __int64 size_t;
// 是无符号整形

可见,strlen("abc") - strlen("abcdefg")确实是小于0的数,但是返回值是无符号整形,所以要进行转换

最后的结果是一个很大的整数

strcpy

函数原型

char* strcpy(char* dest, const char* src);
// 模拟实现
char* my_strcpy(char* dest, const char* src) {
    assert(src && dest);
    char* tmp = dest;
    while (*dest++ = *src++); 
    return tmp;
}
int main() {
    char arr[20] = { 0 };
    char* parr = "hello!";
    my_strcpy(arr, parr);
    printf("%s\n", arr);
    return 0;
}

strcat

char *strcat( char *strDestination, const char *strSource );
// 源字符串必须以'\0' 结束。
// 目标空间必须有足够的大,能容纳下源字符串的内容。
// 目标空间必须可修改。
// 模拟实现
// strcat
char* my_strcat(char* dest, const char* src) {
    assert(dest && src);
    char* tmp = dest;
    while (*dest) {
        dest++;
    }
    while (*dest++ = *src++);
    return tmp;
}
int main() {
    char arr[20] = { 'h', 'e', 'l', '\0', 'm'};
    char arr2[10] = " world";
    printf("%s\n", my_strcat(arr, arr2));
    return 0;
}

strcmp

int strcmp( const char *string1, const char *string2 );
// 模拟实现
// 版本1
int my_strcmp01(const char* string1, const char* string2) {
    assert(string1 && string2);
    while (*string1 || *string2) {
        if (*string1 != *string2)
            return *string1 - *string2;
        if (*string1 == *string2) {
            string1++;
            string2++;
        }
    }
    return 0;
}
// 版本2
int my_strcmp(const char* string1, const char* string2) {
    assert(string1 && string2);
    while (*string1 == *string2 && *string) {
        string1++;
        string2++;
    }
    return *string1 - *string2;
}


int main() {
    char arr[] = "hello";
    char arr2[] = "hp";
    if (my_strcmp(arr,arr2)> 0) {
        printf(">\n");
    } else if (my_strcmp(arr, arr2) == 0) {
        printf("=\n");
    } else {
        printf("<\n");
    }
    return 0;
}

strncmp

int strncmp(const char* str1, const char* str2, size_t count);
// 模拟实现
int my_strncmp(const char* str1, const char* str2, size_t count) {
    assert(str1 && str2);
    char* tmp_str1 = str1;
    for (int i = 0; i < count; i++) {
        tmp_str1++;
    }
    //char* tmp_str2 = str2;
    while (*str1 == *str2 && *str1) {
        if (str1 < tmp_str1) {
            str1++;
            str2++;
        }
    }
    return *str1 - *str2;
}

strncat

char* strncat(char* dest, char* src, size_t count);
// 模拟实现
char* my_strncat(char* dest, const char* src, int count) {
    int i = 0;
    char* tmp_dest = dest;
    char* tmp_src = src;
    while (*dest)
        dest++;
    while ( i < count) {
        src++;
        i++;
    }
    while (tmp_src < src) {
        *dest++ = *tmp_src++;
    }
    return tmp_dest;
}
int main() {
    char string1[20] = "hello";
    char* string2 = " world!";
    printf("%s\n", my_strncat(string1, string2, 5));
    return 0;
}

strstr

char *strstr( const char *string, const char *strCharSet );
// 模拟实现
char* my_strstr(const char* str1, const char* str2) {
    assert(str1 && str2);
    const char* s1 = NULL;
    const char* s2 = NULL;
    const char* cp = str1;
    if (*str2 == '\0')
        return (char*)str1;
    while (*cp) {
        s1 = cp;
        s2 = str2;
        while (*s1 && *s2 && (*s1 == *s2)) {
            s1++;
            s2++;
        }
        if ('\0' == *s2)
            return (char*)cp;
        if ('\0' == *s1)
            return NULL;
        cp++;
    }
    return NULL;
}

strtok

char *strtok( char *strToken, const char *strDelimit );
// strDelimit分隔符字符集

strerror

image-20230225131700176.png

include <errno.h>
// errno是一个全局的错误码,用的时候要包含头文件
strerro(errno);

错误信息

  • 联系

    • strerror

      • 是将错误码转换成错误信息,返回值是错误信息对应字符串的首地址

      • 引用头文件<string.h>

      • // 函数原型
        char* strerror(int errnum);
        
    • perror

      • 直接打印错误信息

      • 引用头文件<stdio.h>或者<stdlib.h>

      • // 函数原型
        void perror(const char* string)
        
  • image-20230225134649981.png perror(""),括号里面是自定义的,可以自己写,把自己写的内容打印出来后会加上一个冒号以及错误信息;

这里的错误信息是将错误码转换成错误信息才打印出来的

字符分类函数

需要引用<ctype.h> image-20230225135201200.png

字符转换函数

需要引用<ctype.h>

toupper();
tolower();