C语言——字符函数、字符串函数和内存函数

0.前言

在C语言中,字符函数、字符串函数和内存函数是编程中常用的一些工具,它们为处理字符、字符串和内存提供了丰富的功能。本篇博客将介绍一系列与字符、字符串和内存相关的函数,并对其中一些函数进行模拟实现,以加深对它们的理解。

注意,本篇博客所提及的全部库函数的头文件分别为<ctype.h>和<string.h>(C++中为<cctype>和<cstring>),见下图:

(截图自legacy.cplusplus.com) 

1. 字符分类函数

以下函数均为字符分类函数:

1.1. isalnum - 判断字符是否为字母或数字

int isalnum(int c);
  • 功能: 检查字符是否是字母或数字。
  • 返回值: 如果字符是字母或数字,则返回非零值;否则返回零。

1.2. isalpha - 判断字符是否为字母

int isalpha(int c);
  • 功能: 检查字符是否是字母。
  • 返回值: 如果字符是字母,则返回非零值;否则返回零。

1.3. isblank - 判断字符是否为空白字符

int isblank(int c);
  • 功能: 检查字符是否是空白字符(空格或制表符)。
  • 返回值: 如果字符是空白字符,则返回非零值;否则返回零。

1.4. iscntrl - 判断字符是否为控制字符

int iscntrl(int c);
  • 功能: 检查字符是否是控制字符。
  • 返回值: 如果字符是控制字符,则返回非零值;否则返回零。

1.5. isdigit - 判断字符是否为数字

int isdigit(int c);
  • 功能: 检查字符是否是十进制数字。
  • 返回值: 如果字符是数字,则返回非零值;否则返回零。

1.6. isgraph - 判断字符是否有图形表示

int isgraph(int c);
  • 功能: 检查字符是否有图形表示,即除空格外的可打印字符。
  • 返回值: 如果字符有图形表示,则返回非零值;否则返回零。

1.7. islower - 判断字符是否为小写字母

int islower(int c);
  • 功能: 检查字符是否为小写字母。
  • 返回值: 如果字符是小写字母,则返回非零值;否则返回零。

1.8. isprint - 判断字符是否可打印

int isprint(int c);
  • 功能: 检查字符是否是可打印字符(包括空格)。
  • 返回值: 如果字符是可打印字符,则返回非零值;否则返回零。

1.9. ispunct - 判断字符是否为标点符号

int ispunct(int c);
  • 功能: 检查字符是否为标点符号。
  • 返回值: 如果字符是标点符号,则返回非零值;否则返回零。

1.10. isspace - 判断字符是否为空白字符

int isspace(int c);
  • 功能: 检查字符是否是空白字符(包括空格、制表符、换行符等)。
  • 返回值: 如果字符是空白字符,则返回非零值;否则返回零。

1.11. isupper - 判断字符是否为大写字母

int isupper(int c);
  • 功能: 检查字符是否为大写字母。
  • 返回值: 如果字符是大写字母,则返回非零值;否则返回零。

1.12. isxdigit - 判断字符是否为十六进制数字

int isxdigit(int c);
  • 功能: 检查字符是否是十六进制数字。
  • 返回值: 如果字符是十六进制数字,则返回非零值;否则返回零。

2. 字符转换函数

以下两个函数为字符转换函数:

2.1. tolower - 将大写字母转换为小写字母

int tolower(int c);
  • 功能: 将大写字母转换为小写字母。
  • 参数: 单个字符 c
  • 返回值: 如果 c 是大写字母,则返回对应的小写字母;否则返回 c 本身。

使用示例:

char uppercase = 'A'; 
char lowercase = tolower(uppercase); // 现在 lowercase 的值为 'a'

2.2. toupper - 将小写字母转换为大写字母

int toupper(int c);
  • 功能: 将小写字母转换为大写字母。
  • 参数: 单个字符 c
  • 返回值: 如果 c 是小写字母,则返回对应的大写字母;否则返回 c 本身。

使用示例:

char lowercase = 'b';
char uppercase = toupper(lowercase); // 现在 uppercase 的值为 'B'

这两个字符转换函数通常用于文本处理、大小写不敏感的字符串比较等场景。在需要统一字符大小写格式时,它们能够提供便捷的转换功能。请注意,这两个函数只对字母字符进行转换,对于其他字符,它们会原样返回。


3. strlen的使用和模拟实现

3.1 使用 strlen

strlen 函数用于计算字符串的长度,即字符串中的字符个数,不包括字符串结束符 \0

size_t strlen(const char *str);
  • 参数: 字符串指针 str
  • 返回值: 字符串的长度,即字符个数。

使用示例:

#include <stdio.h>
#include <string.h>

int main() 
{
    const char *message = "Hello, World!";
    size_t length = strlen(message);
    printf("The length of the string is: %zu\n", length);

    return 0;
}

 输出结果:

3.2 模拟实现 strlen

模拟实现 strlen 的基本思路是遍历字符串,直到遇到字符串结束符 \0,统计遍历过的字符个数。

size_t my_strlen(const char *str) 
{
    size_t length = 0;

    while (*str != '\0') 
    {
        length++;
        str++;
    }

    return length;
}

使用示例:

#include <stdio.h>

size_t my_strlen(const char *str);//函数声明,需要在主函数后加上函数定义

int main() 
{
    const char *message = "Hello, World!";
    size_t length = my_strlen(message);
    printf("The length of the string is: %zu\n", length);

    return 0;
}

模拟实现的 my_strlen 函数通过逐个检查字符是否为结束符 \0 来计算字符串的长度。这个简单的实现展示了 strlen 函数的基本原理。

需要注意的是,实际的 strlen 函数可能会进行一些优化,例如使用处理器指令集中的字符串长度指令,以提高性能。但基本思想仍然是遍历字符串直到遇到结束符。


4. strcpy的使用和模拟实现

4.1 使用 strcpy

strcpy 函数用于将源字符串复制到目标字符串,包括字符串结束符 \0

char *strcpy(char *dest, const char *src);
  • 参数:
    • dest:目标字符串的指针。
    • src:源字符串的指针。
  • 返回值: 指向目标字符串 dest 的指针。

使用示例:

#include <stdio.h>
#include <string.h>

int main() 
{
    char destination[20];
    const char *source = "Hello, World!";
    strcpy(destination, source);
    printf("Copied string: %s\n", destination);
    return 0;
}

输出结果:

4.2 模拟实现 strcpy

模拟实现 strcpy 的基本思路是逐个复制源字符串的字符到目标字符串,直到遇到源字符串的结束符 \0

char *my_strcpy(char *dest, const char *src) 
{
    char *original_dest = dest;

    while ((*dest++ = *src++) != '\0') 
    {
        ;// 复制字符直到遇到结束符 \0
    }
    return original_dest;
}

使用示例:

#include <stdio.h>

char *my_strcpy(char *dest, const char *src);

int main() 
{
    char destination[20];
    const char *source = "Hello, World!";

    my_strcpy(destination, source);

    printf("Copied string: %s\n", destination);

    return 0;
}

 模拟实现的 my_strcpy 函数通过逐个复制字符直到遇到结束符 \0 来实现字符串的复制。需要注意的是,在实际应用中,应确保目标字符串 dest 有足够的空间来容纳源字符串 src,以避免溢出。

5. strcat的使用和模拟实现

5.1 使用 strcat

strcat 函数用于将源字符串追加到目标字符串的末尾,包括字符串结束符 \0

char *strcat(char *dest, const char *src);
  • 参数:
    • dest:目标字符串的指针,必须有足够的空间容纳源字符串。
    • src:源字符串的指针。
  • 返回值: 指向目标字符串 dest 的指针。

使用示例:

#include <stdio.h>
#include <string.h>

int main() 
{
    char destination[20] = "Hello, ";
    const char *source = "World!";

    strcat(destination, source);

    printf("Concatenated string: %s\n", destination);

    return 0;
}

输出结果:

5.2 模拟实现 strcat

模拟实现 strcat 的基本思路是找到目标字符串的末尾,然后逐个追加源字符串的字符。

char *my_strcat(char *dest, const char *src) 
{
    char *original_dest = dest;

    // 定位目标字符串的末尾
    while (*dest != '\0') 
    {
        dest++;
    }
    // 逐个追加源字符串的字符
    while ((*dest++ = *src++) != '\0') 
    {
        // 追加字符直到遇到结束符 \0
    }
    return original_dest;
}

使用示例:

#include <stdio.h>

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

int main() 
{
    char destination[20] = "Hello, ";
    const char *source = "World!";

    my_strcat(destination, source);

    printf("Concatenated string: %s\n", destination);

    return 0;
}

 模拟实现的 my_strcat 函数首先找到目标字符串的末尾,然后逐个追加源字符串的字符直到遇到结束符 \0。在实际应用中,需要确保目标字符串 dest 有足够的空间来容纳源字符串 src,以避免溢出。


6. strcmp的使用和模拟实现

6.1 使用 strcmp

strcmp 函数用于比较两个字符串,判断它们是否相等。判断大小的依据是两个字符的ASCII码值。此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续向后比较,直到字符不同或达到'\0'为止。返回值为0表示相等,正数表示第一个字符串大,负数表示第二个字符串大。

int strcmp(const char *str1, const char *str2);
  • 参数:
    • str1:第一个字符串的指针。
    • str2:第二个字符串的指针。
  • 返回值: 比较结果,0 表示相等,正数表示 str1 大于 str2,负数表示 str1 小于 str2

使用示例:

#include <stdio.h>
#include <string.h>

int main() 
{
    const char *string1 = "Hello";
    const char *string2 = "World";

    int result = strcmp(string1, string2);

    if (result == 0) 
    {
        printf("Strings are equal.\n");
    } 
    else if (result < 0) 
    {
        printf("String1 is less than String2.\n");
    } 
    else     
    {
        printf("String1 is greater than String2.\n");
    }

    return 0;
}

输出结果:

6.2 模拟实现 strcmp

模拟实现 strcmp 的基本思路是逐个比较两个字符串的字符,直到遇到不同字符或者其中一个字符串结束符 \0

int my_strcmp(const char *str1, const char *str2) 
{
    while (*str1 != '\0' && *str1 == *str2) 
    {
        str1++;
        str2++;
    }

    return *(unsigned char *)str1 - *(unsigned char *)str2;
    // 使用 unsigned char 强制转换,以处理可能的符号扩展问题
}

使用示例:

#include <stdio.h>

int my_strcmp(const char *str1, const char *str2);

int main() 
{
    const char *string1 = "Hello";
    const char *string2 = "World";

    int result = my_strcmp(string1, string2);

    if (result == 0) 
    {
        printf("Strings are equal.\n");
    } 
    else if (result < 0) 
    {
        printf("String1 is less than String2.\n");
    } 
    else 
    {
        printf("String1 is greater than String2.\n");
    }

    return 0;
}

模拟实现的 my_strcmp 函数通过逐个比较字符直到遇到不同字符或者其中一个字符串结束符 \0 来模拟实现字符串的比较。在比较时,使用了 unsigned char 类型的强制转换,以处理可能的符号扩展问题。


7. strncpy函数的使用和模拟实现

7.1 使用 strncpy

strncpy 函数用于将源字符串的指定部分复制到目标字符串,最多复制指定的字符个数。如果源字符串长度小于指定的字符个数,则会用空字符 \0 填充剩余部分。

char *strncpy(char *dest, const char *src, size_t n);
  • 参数:
    • dest:目标字符串的指针。
    • src:源字符串的指针。
    • n:最多复制的字符个数。
  • 返回值: 指向目标字符串 dest 的指针。

使用示例:

#include <stdio.h>
#include <string.h>

int main() 
{
    char destination[20];
    const char *source = "Hello, World!";

    strncpy(destination, source, 5); // 复制前5个字符
    destination[5] = '\0'; // 手动添加字符串结束符

    printf("Copied string: %s\n", destination);

    return 0;
}

输出结果:

 

7.2 模拟实现 strncpy

模拟实现 strncpy 的基本思路是逐个复制源字符串的字符到目标字符串,最多复制指定的字符个数,同时确保在达到指定字符个数之后,用空字符 \0 填充剩余部分。

char *my_strncpy(char *dest, const char *src, size_t n) 
{
    char *original_dest = dest;

    // 逐个复制源字符串的字符,最多复制 n 个
    while (n > 0 && *src != '\0') 
    {
        *dest++ = *src++;
        n--;
    }

    // 如果已经达到指定字符个数,用空字符 \0 填充剩余部分
    while (n > 0)     
    {
        *dest++ = '\0';
        n--;
    }

    return original_dest;
}

使用示例:

#include <stdio.h>

char *my_strncpy(char *dest, const char *src, size_t n);

int main() 
{
    char destination[20];
    const char *source = "Hello, World!";

    my_strncpy(destination, source, 5); // 复制前5个字符
    destination[5] = '\0'; // 手动添加字符串结束符

    printf("Copied string: %s\n", destination);

    return 0;
}

 模拟实现的 my_strncpy 函数通过逐个复制字符到目标字符串,同时确保在达到指定字符个数之后,用空字符 \0 填充剩余部分。这样可以确保目标字符串总共包含指定的字符个数。

在实际应用中,strncpy 通常用于确保目标字符串的固定长度,避免溢出。


8. strncat函数的使用和模拟实现

8.1 使用 strncat

strncat 函数用于将源字符串的指定部分追加到目标字符串的末尾,最多追加指定的字符个数,且确保目标字符串以空字符 \0 结尾。

char *strncat(char *dest, const char *src, size_t n);
  • 参数:
    • dest:目标字符串的指针,必须有足够的空间容纳源字符串。
    • src:源字符串的指针。
    • n:最多追加的字符个数。
  • 返回值: 指向目标字符串 dest 的指针。

使用示例:

#include <stdio.h>
#include <string.h>

int main() 
{
    char destination[20] = "Hello,";
    const char *source = "World!";

    strncat(destination, source, 5); // 追加源字符串的前5个字符
    destination[11] = '\0'; // 手动添加字符串结束符

    printf("Concatenated string: %s\n", destination);

    return 0;
}

输出结果:

 

8.2 模拟实现 strncat

模拟实现 strncat 的基本思路是找到目标字符串的末尾,然后逐个追加源字符串的字符,最多追加指定的字符个数,同时确保目标字符串以空字符 \0 结尾。

char *my_strncat(char *dest, const char *src, size_t n) 
{
    char *original_dest = dest;

    // 定位目标字符串的末尾
    while (*dest != '\0')     
    {
        dest++;
    }

    // 逐个追加源字符串的字符,最多追加 n 个
    while (n > 0 && *src != '\0') 
    {
        *dest++ = *src++;
        n--;
    }

    // 确保目标字符串以空字符 \0 结尾
    *dest = '\0';

    return original_dest;
}

使用示例:

#include <stdio.h>

char *my_strncat(char *dest, const char *src, size_t n);

int main() 
{
    char destination[20] = "Hello, ";
    const char *source = "World!";

    my_strncat(destination, source, 5); // 追加源字符串的前5个字符
    destination[11] = '\0'; // 手动添加字符串结束符

    printf("Concatenated string: %s\n", destination);

    return 0;
}

模拟实现的 my_strncat 函数首先找到目标字符串的末尾,然后逐个追加源字符串的字符,最多追加指定的字符个数,同时确保目标字符串以空字符 \0 结尾。这样可以确保目标字符串总共包含指定的字符个数。

在实际应用中,strncat 通常用于确保目标字符串的固定长度,避免溢出。


9. strncmp函数的使用和模拟实现

9.1 使用 strncmp

strncmp 函数用于比较两个字符串的前 n 个字符,判断它们是否相等。返回值为0表示相等,正数表示第一个字符串大于第二个字符串,负数表示第一个字符串小于第二个字符串。

int strncmp(const char *str1, const char *str2, size_t n);
  • 参数:
    • str1:第一个字符串的指针。
    • str2:第二个字符串的指针。
    • n:比较的字符个数。
  • 返回值: 比较结果,0 表示相等,正数表示 str1 大于 str2,负数表示 str1 小于 str2

使用示例:

#include <stdio.h>
#include <string.h>

int main() {
    const char *string1 = "Hello";
    const char *string2 = "Heaven";

    int result = strncmp(string1, string2, 3); // 比较前3个字符

    if (result == 0) 
    {
        printf("Strings are equal.\n");
    } 
    else if (result < 0) 
    {
        printf("String1 is less than String2.\n");
    } 
    else     
    {
        printf("String1 is greater than String2.\n");
    }

    return 0;
}

9.2 模拟实现 strncmp

模拟实现 strncmp 的基本思路是逐个比较两个字符串的字符,最多比较前 n 个字符,直到遇到不同字符或者其中一个字符串结束符 \0

int my_strncmp(const char *str1, const char *str2, size_t n) 
{
    while (n > 0 && *str1 != '\0' && *str1 == *str2) 
    {
        str1++;
        str2++;
        n--;
    }
    if (n == 0) 
    {
        return 0; // 前 n 个字符相等
    }

    return *(unsigned char *)str1 - *(unsigned char *)str2;
    // 使用 unsigned char 强制转换,以处理可能的符号扩展问题
}

使用示例:

#include <stdio.h>

int my_strncmp(const char *str1, const char *str2, size_t n);

int main() 
{
    const char *string1 = "Hello";
    const char *string2 = "Heaven";

    int result = my_strncmp(string1, string2, 3); // 比较前3个字符

    if (result == 0) 
    {
        printf("Strings are equal.\n");
    } 
    else if (result < 0) 
    {
        printf("String1 is less than String2.\n");
    }  
    else 
    {
        printf("String1 is greater than String2.\n");
    }

    return 0;
}

模拟实现的 my_strncmp 函数通过逐个比较字符直到遇到不同字符、其中一个字符串结束符 \0,或者比较的字符个数达到 n 来模拟实现字符串的比较。在比较时,使用了 unsigned char 类型的强制转换,以处理可能的符号扩展问题。 


10. strstr的使用和模拟实现

10.1 使用 strstr

strstr 函数用于在一个字符串中查找另一个字符串的第一次出现的位置,并返回找到的子字符串的指针。

char *strstr(const char *str1, const char *str2);
  • 参数:
    • str1:目标字符串的指针。
    • str2:要查找的子字符串的指针。
  • 返回值: 如果找到了子字符串,则返回指向该位置的指针;否则返回 NULL

使用示例:

#include <stdio.h>
#include <string.h>

int main() 
{
    const char *str1 = "Hello, World!";
    const char *str2 = "World";

    char *result = strstr(str1, str2);

    if (result != NULL) 
    {
        printf("Substring found at position: %ld\n", result - str1);
    } 
    else 
    {
        printf("Substring not found.\n");
    }

    return 0;
}

输出结果: 

10.2 模拟实现 strstr

模拟实现 strstr 的基本思路是在目标字符串中逐个比较字符,如果找到了子字符串的第一个字符,则从这个位置开始逐个比较后续字符,直到完全匹配或者子字符串结束。

char *my_strstr(const char *str1, const char *str2) 
{
    while (*str1 != '\0') 
    {
        const char *h = str1;
        const char *n = str2;

        // 逐个比较字符
        while (*n != '\0' && *h == *n) 
        {
            h++;
            n++;
        }

        // 如果子字符串结束,表示完全匹配
        if (*n == '\0') 
        {
            return (char *)str1;
        }

        str1++;
    }

    return NULL; // 未找到子字符串
}

使用示例:

#include <stdio.h>

char *my_strstr(const char *str1, const char *str2);

int main() 
{
    const char *str1 = "Hello, World!";
    const char *str2 = "World";

    char *result = my_strstr(str1, str2);

    if (result != NULL) 
    {
        printf("Substring found at position: %ld\n", result - str1);
    }     
    else     
    {
        printf("Substring not found.\n");
    }

    return 0;
}

模拟实现的 my_strstr 函数通过在目标字符串中逐个比较字符来查找子字符串的位置。如果找到了子字符串的第一个字符,就从这个位置开始逐个比较后续字符,直到完全匹配或者子字符串结束。

这个例子简单的实现展示了 strstr 函数的基本原理。在实际应用中,strstr 通常用于搜索特定的子字符串,以便进行进一步处理。


11. strtok函数的使用

strtok 函数用于将字符串分解成标记(token),可以在字符串中按照指定的分隔符将字符串切分成多个部分。

char *strtok(char *str, const char *delimiters);
  • 参数:
    • str:第一次调用时传入需要分解的字符串,后续调用传入 NULL
    • delimiters:包含分隔符字符的字符串。
  • 返回值: 返回分解后的标记(token)的指针。

使用示例:

#include <stdio.h>
#include <string.h>

int main() 
{
    char str[] = "Hello,World,Token";
    const char delimiters[] = ",";

    // 第一次调用,分解字符串
    char *token = strtok(str, delimiters);

    while (token != NULL) 
    {
        printf("Token: %s\n", token);

        // 后续调用,继续分解字符串
        token = strtok(NULL, delimiters);
    }

    return 0;
}

输出结果:

在上述示例中,strtok 函数将字符串 "Hello,World,Token" 按照逗号 , 分隔成三个部分,并逐个输出这三个标记。

需要注意的是,strtok 函数是一个有状态的函数,它会修改输入的字符串。在第一次调用时,传入需要分解的字符串;后续调用时,传入 NULL 以继续使用相同的字符串。

注意事项:

  1. strtok 函数会将分隔符(delimiters)之间的空白字符(空格、制表符等)都视为分隔符。
  2. 在多线程环境中,strtok 不是线程安全的,可以考虑使用 strtok_r 或者 strcspnstrspn 等函数来实现类似的功能。


12. strerror函数的使用

strerror 函数用于将错误码转换为对应的错误消息字符串。这个函数通常用于处理系统调用或库函数返回的错误码,将其转换为易于理解的错误描述。

char *strerror(int errnum);
  • 参数:
    • errnum:表示错误码的整数。
  • 返回值: 返回一个指向错误消息字符串的指针。

使用示例:

#include <stdio.h>
#include <string.h>

int main() 
{
    // 模拟一个错误码
    int errnum = 2;

    // 使用 strerror 获取错误消息字符串
    const char *error_message = strerror(errnum);

    // 打印错误消息
    printf("Error Message: %s\n", error_message);

    return 0;
}

输出结果:

在上述示例中,strerror 函数被用来将错误码(errnum)转换为对应的错误消息字符串。该错误码用于模拟一个错误场景,然后 strerror 将其转换为相应的错误消息。

注意事项:

  1. strerror 函数是线程安全的,可以在多线程环境中安全使用。
  2. 错误码的值通常来自系统调用或者库函数的返回值,具体的错误码和含义可以参考系统或库函数的文档。


13. memcpy使用和模拟实现

13.1 使用 memcpy

memcpy 函数用于在内存中复制一块数据,将源地址的数据复制到目标地址。它是一种高效的内存复制操作。

#include <stdio.h>
#include <string.h>

int main() 
{
    char source[] = "Hello, World!";
    char destination[20];

    // 使用 memcpy 复制数据
    memcpy(destination, source, sizeof(source));

    printf("Source: %s\n", source);
    printf("Destination: %s\n", destination);

    return 0;
}

在上述示例中,memcpy 函数被用来将源数组 source 中的数据复制到目标数组 destination

13.2 模拟实现 memcpy

模拟实现 memcpy 的基本思路是逐个字节地从源地址复制到目标地址,直到复制指定的字节数。

#include <stdio.h>

void *my_memcpy(void *dest, const void *src, size_t n) 
{
    char *char_dest = (char *)dest;
    const char *char_src = (const char *)src;

    // 逐字节复制数据
    while (n > 0)     
    {
        *char_dest++ = *char_src++;
        n--;
    }

    return dest;
}

使用示例:

#include <stdio.h>

void *my_memcpy(void *dest, const void *src, size_t n);

int main() 
{
    char source[] = "Hello, World!";
    char destination[20];

    // 使用模拟实现的 memcpy 复制数据
    my_memcpy(destination, source, sizeof(source));

    printf("Source: %s\n", source);
    printf("Destination: %s\n", destination);

    return 0;
}

模拟实现的 my_memcpy 函数通过逐字节地从源地址复制到目标地址,直到复制指定的字节数。这个简单的实现展示了 memcpy 函数的基本原理。


14. memmove使用和模拟实现

14.1 使用 memmove

memmove 函数用于在内存中复制一块数据,与 memcpy 不同的是,memmove 能够处理源地址和目标地址重叠的情况。

#include <stdio.h>
#include <string.h>

int main() 
{
    char data[] = "Hello, World!";
    char buffer[20];

    // 使用 memmove 处理重叠的源和目标地址
    memmove(data + 7, data + 2, 7);

    printf("Data: %s\n", data);

    return 0;
}

在上述示例中,memmove 函数被用来从 data 的第3个字符(包括)开始,复制7个字符到 data 的第8个位置。这里 data 的源空间和目标空间是重叠的。

14.2 模拟实现 memmove

模拟实现 memmove 的基本思路是考虑源地址和目标地址的相对位置,采用一种安全的逐字节复制方式,以防止重叠的问题。

#include <stdio.h>

void *my_memmove(void *dest, const void *src, size_t n) 
{
    char *char_dest = (char *)dest;
    const char *char_src = (const char *)src;

    // 源地址在目标地址之前,从前往后逐字节复制
    if (char_dest <= char_src || char_dest >= char_src + n) 
    {
        while (n > 0) 
        {
            *char_dest++ = *char_src++;
            n--;
        }
    } 
    else 
    {
        // 源地址在目标地址之后,从后往前逐字节复制
        char_dest += n - 1;
        char_src += n - 1;

        while (n > 0) 
        {
            *char_dest-- = *char_src--;
            n--;
        }
    }

    return dest;
}

使用示例:

#include <stdio.h>

void *my_memmove(void *dest, const void *src, size_t n);

int main() 
{
    char data[] = "Hello, World!";
    char buffer[20];

    // 使用模拟实现的 memmove 处理重叠的源和目标地址
    my_memmove(data + 7, data + 2, 7);

    printf("Data: %s\n", data);

    return 0;
}

 模拟实现的 my_memmove 函数通过考虑源地址和目标地址的相对位置,采用一种安全的逐字节复制方式,以防止重叠的问题。这个简单的实现展示了 memmove 函数的基本原理。在实际应用中,为了提高效率,标准库的实现通常会使用更加高效的底层操作。


15. memset函数的使用

memset 函数用于将一块内存的内容设置为指定的值。这个函数通常用于初始化数组或者清零内存块。

#include <stdio.h>
#include <string.h>

int main() 
{
    char buffer[20];

    // 使用 memset 将 buffer 中的内容设置为 'A'
    memset(buffer, 'A', sizeof(buffer));

    // 打印设置后的 buffer
    printf("Buffer: %s\n", buffer);

    return 0;
}

在上述示例中,memset 函数被用来将 buffer 中的内容设置为字符 'A'

注意事项:

  • memset 的第一个参数是要设置的内存块的起始地址,第二个参数是要设置的值,第三个参数是要设置的字节数。
  • memset 是按字节设置的,因此如果要设置的是非字符类型的数据,可能需要使用类型转换。
  • 在实际应用中,可以用 memset 来快速初始化数组或清零内存块。

注意: 在 C 语言中,字符型数据与整型数据在内存中占用的字节数是一样的,所以使用 memset 设置字符型数组或整型数组都是可以的。


16. memcmp函数的使用

memcmp 函数用于比较两块内存区域的内容。这个函数通常用于比较字符串或数组是否相等。

#include <stdio.h>
#include <string.h>

int main() 
{
    char str1[] = "Hello";
    char str2[] = "World";

    // 使用 memcmp 比较两个字符串
    int result = memcmp(str1, str2, sizeof(str1));

    if (result == 0) 
    {
        printf("Strings are equal.\n");
    } 
    else if (result < 0) 
    {
        printf("String1 is less than String2.\n");
    } 
    else 
    {
        printf("String1 is greater than String2.\n");
    }

    return 0;
}

在上述示例中,memcmp 函数被用来比较两个字符串 str1str2 的内容。

注意事项:

  • memcmp 的第一个参数是要比较的第一个内存块的起始地址,第二个参数是要比较的第二个内存块的起始地址,第三个参数是要比较的字节数。
  • memcmp 返回一个整数,表示比较结果。如果两块内存区域的内容相等,返回 0;如果第一个内存区域的内容小于第二个,返回负数;如果第一个内存区域的内容大于第二个,返回正数。
  • memcmp 通常用于比较字符串或数组的内容,但需要注意,比较的字节数不能超过实际字符串或数组的长度。

注意: 在实际应用中,为了提高安全性,可以使用 strncmp 函数来比较字符串,而不是直接使用 memcmp。因为 strncmp 会限制比较的字符个数,避免不必要的内存访问。

17.结语

在本博客中,我们深入探讨了 C 语言中一些关键的字符、字符串和内存操作函数,包括字符分类、字符转换、字符串处理以及内存操作等方面。通过了解这些函数的使用方法和模拟实现,我们不仅提升了对 C 语言标准库的认识,还加深了对底层操作的理解。这些函数是 C 语言编程中常用且重要的工具,能够帮助程序员更灵活、高效地处理字符、字符串和内存。在编写代码时,熟练使用这些函数,结合深刻理解其原理,将有助于提升代码的质量和性能。希望本文的内容对您在 C 语言编程的学习和实践中提供了实质性的帮助。

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值