跳转至

C语言字符函数、字符串函数与内存函数

约 1803 个字 500 行代码 预计阅读时间 12 分钟

字符函数

Note

使用时字符函数需要包含头文件ctype.h

字符类型函数

函数 需要满足的条件返回真
iscntrl 任何控制字符
isspace 空白字符:空格、换页符、换行、回车、制表符或垂直制表符
isdigit 十进制数字字符0~9
isxdigit 十六进制数字,包括所有十进制数字字符,小写字母a~f或大写字母A~F
islower 小写字母a~z
isupper 大写字母A~Z
isalpha 字母
isalnum 字母或者数字,a~z,A~Z,0~9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印在控制台)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符

字符转换函数

函数 函数作用
tolower 将大写字母转成小写字母
toupper 将小写字母转成大写字母

字符串函数

Note

字符串函数使用需要包含头文件string.h

strlen函数

函数作用:计算一个字符串有多少个字符,但是不包含\0

C
1
2
3
4
5
函数原型
size_t strlen ( const char * str );

参数说明
char*指针str指向需要计算字符的字符串
  • 字符串以 \0 作为结束标志,strlen函数返回的是在字符串中 \0 前面出现的字符个数(不包含 \0 )
  • 参数指向的字符串必须要以 \0 结束
  • 函数的返回类型为size_t

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <string.h>//包含头文件string.h

int main()
{
    const char* p = "hello world";

    size_t sz = strlen(p);//返回类型为size_t

    printf("%zd\n", sz);

    return 0;
}
输出结果
11

strcpy函数

函数作用:将源数组中的内容拷贝到目标数组,包括\0

C
1
2
3
4
5
6
7
8
9
函数原型
char* strcpy(char * destination, const char * source );

参数说明
第一个参数char*类型的指针表示目标数组拷贝的内容放置于此
第二个参数char*类型的指针表示源头数组需要从此数组中拷贝

返回类型
函数返回char*类型的指针该指针指向目标空间的起始地址
  • 源字符串必须以 \0 结束
  • 会将源字符串中的 \0 拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串
  • 目标空间必须可修改

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    char* p = "hello world";//字符串长度为11,包括\0时长度为12,目标数组必须大于等于12

    char arr[20] = { 0 };//
    const char arr1[20] = { 0 };//尽管使用了const指针对数组进行了修饰限制,但是只是限制数组不能被直接修改
                                //但是仍然可以通过指针间接修改,而strcpy函数的第一个参数恰好是一个指针,故此时用const修饰的数组仍可以被修改,但是这种做法不安全

    char* str = "aaaaaaaaaaaaa";//此时str指针指向的是常量字符串所在的空间,与数组空间对比,常量字符串所在空间无法被修改,故此时会拷贝失败

    char* p1 = strcpy(arr1, p);
    //char* p2 = strcpy(str, p);

    printf("%s\n", p1);
    printf("%s\n", arr1);//也可以直接使用数组名进行输出而不进行函数返回值接受
    return 0;
}
输出结果
hello world
hello world

strcat函数

函数作用:在一个目标空间中出现\0的位置开始追加新的字符

C
1
2
3
4
5
6
7
8
9
函数原型
char * strcat ( char * destination, const char * source );

参数说明
第一个参数是char*类型的指针指向被追加的目标空间的地址
第二个参数是char*类型的指针指向需要追加的字符的源空间的地址

返回类型
函数返回char*类型的指针该指针指向目标空间的起始地址
  • 源字符串必须以\0结束
  • 目标字符串中也得有 \0 ,否则没办法知道追加开始的位置(strcat函数从目标空间的\0位置开始追加,并且会覆盖目标空间的\0
  • 目标空间必须有足够的大,能容纳下源字符串的内容
  • 目标空间必须可修改

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    char* p = "hello world";
    char arr[20] = { 0 };
    char* str = "aaaaaaaaaaaaa";
    char arr2[20] = "abc";
    char arr3[20] = { 'x' };//尽管在目标数组空间中没有显式得写出\0,但是数组在初始化时,如果给了内容,那么其余没有给内容的空间将默认以0(\0)填充,但是注意源空间必须包含\0

    char* p3 = strcat(arr2, p);
    strcat(arr, p);//当目标空间没有字符串,则strcat函数实现的效果与strcpy函数类似
    strcat(arr3, p);
    //strcat(str, p);//无法追加,目标空间不可修改

    printf("%s\n", p3);
    printf("%s\n", arr);
    printf("%s\n", arr3);

    return 0;
}
输出结果
abchello world
hello world
xhello world

Note

尽量不要使用strcat函数自己给自己追加,即目标空间和源空间尽量不要是同一空间,可能会导致未定义的行为

因为strcat函数在执行时,会首先找到目标字符串的结束位置(即\0字符的位置),然后从这个位置开始,将源字符串的内容复制过来。如果源字符串和目标字符串是同一个字符串,那么在复制过程中,源字符串的内容可能会被目标字符串的新内容覆盖,这就导致了源字符串的内容在复制过程中被改变,从而引发未定义的行为

strcmp函数

函数作用:比较两个字符串的大小

Note

注意此处比较的不是两个字符串的长度,而是两个字符串中的对应字符两两比较

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
函数原型
int strcmp ( const char * str1, const char * str2 );

参数说明
第一个参数是char*类型的指针指向需要比较的第一个字符串
第二个参数是char*类型的指针指向需要比较的第二个字符串

返回类型
函数返回int类型有以下三种情况
个字符串于第二个字符串则返回于0的正整数数值
个字符串等于第二个字符串则返回0
个字符串于第二个字符串则返回小于0的负整数数值
  • 根据每个字符在ASCII表中对应的数值进行字符大小比较

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    char* p = "abcdef";
    char* p1 = "abd";

    int ret = strcmp(p, p1);
    if (ret)
    {
        printf("第一个字符串比第二个字符串大");
    }
    else if(ret < 0)
    {
        printf("第一个字符串比第二个字符串小");
    }
    else
    {
        printf("两个字符串相等");
    }

    return 0;
}
输出结果
第一个字符串比第二个字符串大

strncpy函数

函数作用:与strcpy基本相同,但是多了一个拷贝字符数量限制

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
函数原型
char * strncpy ( char * destination, const char * source, size_t num );

参数说明
第一个参数是char*类型的指针指向拷贝的目标空间的地址
第二个参数是char*类型的指针指向需要拷贝的源空间的地址
第三个参数是size_t类型的变量代表需要拷贝的字符的数量最大数量),注意此处的num表示字符个数*char类型在内存中占用的大小即字符个数*1

返回类型
函数返回类型是一个char*类型的指针该指针指向目标空间的起始位置
  • 拷贝num个字符从源字符串到目标空间
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    char* p = "hello world";
    char arr[20] = { 0 };
    char arr1[6] = "xxxxxx";
    char arr2[15] = "xxxxxxxxxxxxxxx";

    strncpy(arr, p, 5);//由于arr数组初始化时已经有了0(\0),故可以不用手动添加\0
    strncpy(arr1, p, 5);//注意strncpy函数在拷贝的字符个数小于源字符串字符个数并且目标空间进行了完全初始化时,需要手动添加\0,否则会打印出随机值
    strncpy(arr2, p, 15);//源字符串长度小于最大字符串长度时,会在目标空间中写入\0,一直写到总共字符串数量长度达到最大字符串长度

    printf("%s\n", arr);
    printf("%s\n", arr1);
    arr1[5] = '\0';//为最后一个元素添加'\0'
    printf("%s\n", arr1);
    printf("%s\n", arr2);

    return 0;
}
输出结果
hello
hellox烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫hello world
hello
hello world

strncat函数

函数作用:与strcat函数类似,多了一个参数表示需要向目标空间中追加的字符个数

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
函数原型
char * strncat ( char * destination, const char * source, size_t num );

参数说明
第一个参数是char*类型的指针指向被追加的目标空间的地址
第二个参数是char*类型的指针指向需要追加的字符的源空间的地址
第三个参数是size_t类型的变量表示需要追加的字符个数最大字符个数),注意此处的num表示字符个数*char类型在内存中占用的大小即字符个数*1

返回类型
函数返回一个char*类型的指针该指针指向目标空间的起始地址
  • source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字符
  • 如果source指向的字符串的长度小于num的时候,只会将字符串中到\0 的内容追加到destination指向的字符串末尾
C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    char* p = "hello world";
    char arr[20] = { 0 };
    char arr2[20] = "abc";

    strncat(arr2, p, 5);

    printf("%s\n", arr2);

    return 0;
}
输出结果
abchello

strncmp函数

函数作用:与strcmp函数类似,但是多了一个参数表示需要比较的字符的个数

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
函数原型
int strncmp ( const char * str1, const char * str2, size_t num );

参数说明
第一个参数为char*类型的指针指向需要比较的第一个字符串
第二个参数为char*类型的指针指向需要比较的第二个字符串
第三个参数为size_t类型的变量表示需要比较的字符串的个数最大字符个数),注意此处的num表示字符个数*char类型在内存中占用的大小即字符个数*1

返回类型
函数返回int类型的值需要满足的条件与strcmp相同

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    char* p = "abcdef";
    char* p1 = "abd";

    int ret = strncmp(p, p1, 2);
    if (ret)
    {
        printf("第一个字符串比第二个字符串大");
    }
    else if(ret < 0)
    {
        printf("第一个字符串比第二个字符串小");
    }
    else
    {
        printf("两个字符串相等");
    }

    return 0;
}
输出结果
两个字符串相等

strstr函数

函数作用:在一个字符串中找与第二个字符串相同的字符

C
1
2
3
4
5
6
7
8
9
函数原型
char * strstr ( const char * str1, const char * str2);

参数说明
第一个参数为char*类型的指针指向需要进行检索的字符串
第二个参数为char*类型的指针指向需要查找的字符串

返回类型
函数返回一个char*类型的指针表示找到完全匹配的字符后返回成功找到后的第一个字符的地址
  • 函数返回字符串str2在字符串str1中第⼀次出现的位置
  • 字符串的比较匹配不包含 \0 字符,以 \0 作为结束标志

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    char* p = "abcdef";
    char* str = "abbbcdef";
    char* str1 = "abdbcdef";
    char* p1 = "abd";
    char* p2 = "bcd";

    char* ptr = strstr(p, p1);//找不到时返回null,注意不是NULL,尽管都是表示值为0
    char* ptr1 = strstr(str, p2);//返回找到后的第一个字符的地址,即str指向的空间的第三个'b'的地址
    char* ptr2 = strstr(str1, p2);//返回找到后的第一个字符的地址,即str指向的空间的第二个'b'的地址

    printf("%s\n", ptr);
    printf("%s\n", ptr1);
    printf("%s\n", ptr2);

    return 0;
}
输出结果
(null)
bcdef
bcdef

strtok函数

函数作用:将字符串按照字符集中的字符进行分割

C
1
2
3
4
5
6
7
8
9
函数原型
char * strtok ( char * str, const char * sep);

参数说明
第一个参数为char*类型的指针指向需要进行分割的字符串
第二个参数为char*类型的指针指向分割字符集合的字符串

返回类型
函数返回char*类型的指针指向分割后的字符串的起始地址
  • strtok函数找到str中的标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
  • strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下一个标记。如果字符串中不存在更多的标记,则返回 NULL 指针

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    char str[] = "zhangsan@gmail.com";//待分隔字符串
    char* p = "@.";//分隔符集合字符串

    for (char* p4 = strtok(str, p)/*先使用strtok进行第一次分割,如果分割完成则返回非空指针给p4*/; p4 != NULL/*当p4是空指针时,说明已经分割完毕*/; p4 = strtok(NULL, p)/*当传入NULL时代表在同一个字符串中从上次分割后成功替换为\0的位置开始*/)
    {
        printf("%s\n", p4);
    }

    return 0;
}
输出结果
zhangsan
gmail
com

strerror函数

函数作用:返回参数部分错误码对应的错误信息的字符串地址

Note

在不同的系统和C语言标准库的实现中都规定了一些错误码,一般是放在 errno.h 这个头文件中说明的,C语言程序启动的时候就会使用一个全面的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会讲对应的错误码,存放在errno中,而一个错误码的数字是整数很难理解是什么意思,所以每一个错误码都是有对应的错误信息的。

C
1
2
3
4
5
6
7
8
函数原型
char * strerror ( int errnum );

参数说明
int类型变量代表错误码

返回类型
函数会返回char*类型的指针该指针指向错误码对应的错误信息的字符串的地址

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
    FILE * pFile;
    pFile = fopen ("unexist.ent","r");
    if (pFile == NULL)
        printf ("Error opening file unexist.ent: %s\n", strerror(errno));//传入错误码变量,函数返回错误码对应的错误信息字符串起始地址
    return 0;
}
输出结果
Error opening file unexist.ent: No such file or directory

perror函数

函数作用:将错误信息字符串打印在控制台

C
1
2
3
4
5
函数原型
void perror ( const char * str );

参数说明
函数接收一个char*类型的指针该指针默认优先指向用户指定需要打印的内容再指向错误信息如果没有用户指定需要打印的内容则只打印错误信息
  • perror函数打印完参数部分的字符串后,再打印一个冒号和一个空格,再打印错误信息

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
    FILE * pFile;
    pFile = fopen ("unexist.ent","r");
    if (pFile == NULL)
        perror("Error opening file unexist.ent");//先打印用户指定的信息,再打印错误信息,并且二者之间会有冒号:和一个空格
    return 0;
}
输出结果
Error opening file unexist.ent: No such file or directory

内存函数

Note

使用内存函数需要包含头文件string.h

memcpy函数

函数作用:将一个空间中的任意类型的数据复制指定大小到另一个空间

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
函数原型
void * memcpy ( void * destination, const void * source, size_t num );

参数说明
第一个参数为void*指针指向复制至的目标空间
第二个参数为void*指针指向需要复制的内容的源空间
第三个参数为size_t类型的变量表示需要复制数据个数注意此处的num表示字符个数*对应数据类型在内存中占用的大小即字符个数*sizeof(数据类型)

返回类型
函数返回类型为void*指针指向目标空间的起始位置
  • 如果sourcedestination有任何的重叠,复制的结果都是未定义的

Note

strcpy函数不同的是,memcpy函数在遇到 \0 的时候并不会停下来

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr1[20] = { 0 };

    memcpy(arr1, arr, 10 * sizeof(int));

    for (int i = 0; i < 10; i++)
    {
        printf("%d ", arr1[i]);
    }

    return 0;
}
输出结果
1 2 3 4 5 6 7 8 9 10

memmove函数

函数作用:与memcpy函数类似,区别就是memmove函数大多数用于目标空间和源空间有重叠

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
函数原型
void * memmove ( void * destination, const void * source, size_t num );

参数说明
第一个参数为void*指针指向复制至的目标空间
第二个参数为void*指针指向需要复制的内容的源空间
第三个参数为size_t类型的变量表示需要复制数据个数注意此处的num表示字符个数*对应数据类型在内存中占用的大小即字符个数*sizeof(数据类型)

返回类型
函数返回类型为void*指针指向目标空间的起始位置

Note

如果源空间和目标空间出现重叠,尽量使用memmove函数处理

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    int arr2[15] = { 1,2,3,4,5,6,7,8,9,10 };

    memmove(arr2+2, arr2, 10 * sizeof(int));//从arr2数组的第三个元素开始拷贝,目标空间和源空间有重叠

    for (int i = 0; i < 15; i++)
    {
        printf("%d ", arr2[i]);

    }
    return 0;
}
输出结果
1 2 1 2 3 4 5 6 7 8 9 10 0 0 0

memset函数

函数作用:将内存中的值以字节为单位设置成想要的内容

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
函数原型
void * memset ( void * ptr, int value, size_t num );

参数说明
第一个参数为void*类型的指针指向需要更改的目标空间
第二个参数为int类型的变量表示需要修改为的内容并且是一个字节一个字节进行设置即将每个字节都设置该值包括char类型的字符类型
第三个参数为size_t类型的变量表示需要修改的内容的个数单位是字节

返回类型
函数返回void*类型的指针指向目标空间的起始位置

代码实例

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <string.h>
int main ()
{
    char str[] = "hello world";
    memset (str,'x',6);
    printf(str);

    int arr2[15] = { 1,2,3,4,5,6,7,8,9,10 };

    memset(arr2, 6, 1);//整型是4个字节,如果在第三个参数中传4并不是代表第一个数据只改最后一位字节,而是4个字节每一个字节都会更改
                        //而需要改变第一个数值,则只需要改变第一个字节就行,即第三个参数传入1

    for (int i = 0; i < 15; i++)
    {
        printf("%d ", arr2[i]);

    }

    return 0;
}
    return 0;
}
输出结果
xxxxxxworld
6 2 3 4 5 6 7 8 9 10 0 0 0 0 0

memcmp函数

函数作用:以字节为单位比较两个空间中的内容

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
函数原型
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

参数说明
第一个参数为void*类型的指针指向需要比较的第一个空间
第二个参数为void*类型的指针指向需要比较的第二个空间
第三个参数为size_t类型的变量表示需要比较的字节数

返回类型
函数返回int类型的数值满足下面三种情况
个空间内容于第二个空间内容则返回于0的正整数数值
个空间内容等于第个空间内容则返回0
个空间内容于第个空间内容则返回于0的负整数数值

代码实例:

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#define _CRT_SECURE_NO_WARNINGS 1

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

int main()
{
    int arr2[15] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr3[10] = { 1,2,3,4,6 };

    int ret = memcmp(arr2, arr3, 16);//比较前16个字节(4个整型数值)
    int ret1 = memcmp(arr2, arr3, 17);//比较前17个字节(4个整型数值+下一个整型的最低位)

    if (ret)
    {
        printf("第一个空间内容大于第二个空间内容\n");
    }
    else if (ret < 0)
    {
        printf("第一个空间内容小于第二个空间内容\n");
    }
    else
    {
        printf("两个空间内容相同\n");
    }

    if (ret1)
    {
        printf("第一个空间内容大于第二个空间内容\n");
    }
    else if (ret1 < 0)
    {
        printf("第一个空间内容小于第二个空间内容\n");
    }
    else
    {
        printf("两个空间内容相同\n");
    }

    return 0;
}
输出结果
两个空间内容相同
第一个空间内容大于第二个空间内容