C 语言笔记:字符串处理函数

一、获取字符串长度函数

头文件:#include <string.h>
函数定义:size_t strlen(const char *s);
函数功能:
测字符指针 s 指向的字符串中字符的个数,不包括’\0’ 返回值:字符串中字符个数

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

int main()
{
    char s1[100] = "hello";
    printf("s1_len = %d\n", strlen(s1));
    printf("s1_size = %d\n", sizeof(s1));

    char s2[100] = "hel\0lo";
    printf("s2_len = %d\n", strlen(s2));
    printf("s2_size = %d\n", sizeof(s2));

    char *s3 = "hello";
    printf("s3_len = %d\n", strlen(s3));
    printf("s3_size = %d\n", sizeof(s3));

    return 0;
}

执行结果:

s1_len = 5
s1_size = 100
s2_len = 3
s2_size = 100
s3_len = 5
s3_size = 8

strlen() 在获取字符串长度时,遇到第一个 \0 结束,且这个 \0 不算做字符串长度中。
s3 是一个指针变量,在 64 位操作系统中占 8 字节。

二、字符串拷贝函数

头文件:#include <string.h>
函数的定义:char *strcpy(char *dest, const char *src);
函数的说明:
拷贝 src 指向的字符串到 dest 指针指向的内存中,\0 也会拷贝
函数的返回值:目的内存的地址

注意:在使用此函数的时候,必须保证 dest 指向的内存空间足够大,否则会出现内存污染。(前面比后面长)

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

int main()
{
    char s1[32] = "hello world";
    char s2[32] = "abcdefg";

    strcpy(s1, s2);
    printf("s1 = %s\n", s1);

    int i;
    for(i = 0;i < 32;i++)
    {
        printf("[%c] - %d\n", s1[i], s1[i]);
    }
    return 0;
}

执行结果:

s1 = abcdefg
[a] - 97
[b] - 98
[c] - 99
[d] - 100
[e] - 101
[f] - 102
[g] - 103
[] - 0
[r] - 114
[l] - 108
[d] - 100
[] - 0

...

[] - 0

[字符] - ASCII码值

char *strncpy(char *dest, const char *src, size_t n);
函数的说明:
将 src 指向的字符串前 n 个字节,拷贝到 dest 指向的内存中
返回值:目的内存的首地址
注意:
(1)strncpy 不拷贝 \0
(2)如果 n 大于 src 指向的字符串中的字符个数,则在 dest 后面填充 n - strlen(src)\0

三、字符串追加函数

1. strcat() 函数

头文件:#include <string.h>
函数定义:char *strcat(char *dest, const char *src);
函数功能:
strcat 函数追加 src 字符串到 dest 指向的字符串的后面。追加的时候会追加’\0’ 注意:保证 dest 指向的内存空间足够大。

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

int main()
{
    char s1[32] = "hello world";
    char s2[32] = "ABCDEF";

    strcat(s1, s2);

    printf("s1 = %s\n", s1);

    return 0;
}

执行结果:

s1 = hello worldABCDEF

strcat() 是从 s1 的 \0 位置开始追加,直到 s2 的第一个 \0 位置复制完结束。

2. strncat() 函数

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

这个函数接受三个参数:
dest:指向目标字符串的指针,即将源字符串连接到其末尾。
src:指向源字符串的指针,即要连接到目标字符串末尾的字符串。
n:要连接的 src 字符串的最大长度。

strncat() 函数会将源字符串 src 的前 n 个字符连接到目标字符串 dest 的末尾,然后在连接后的字符串末尾添加一个 null 字符,以表示字符串的结束。连接后的字符串 dest 将会被修改,并且返回指向 dest 的指针。

strncat() 函数与 strcat() 函数的区别:
strncat() 函数允许指定要连接的 src 字符串的最大长度 n,以防止 src 字符串长度超过 dest 字符串剩余空间而导致的缓冲区溢出。

四、字符串比较函数

1. strcmp() 函数

头文件:#include <string.h>
函数原型:int strcmp(const char *str1, const char *str2);
这个函数接受两个参数:
str1:指向第一个要比较的字符串的指针。
str2:指向第二个要比较的字符串的指针。
返回值:
strcmp() 函数将会按照字典顺序(ASCII 码顺序)比较两个字符串。
如果第一个字符串 str1 按照字典顺序排在第二个字符串 str2 之前,则返回一个负整数;
如果两个字符串相等,则返回 0;
如果第一个字符串 str1 按照字典顺序排在第二个字符串 str2 之后,则返回一个正整数。

例:

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

int main()
{
    char s1[] = "hello";
    char s2[] = "hella";

    int ret = strcmp(s1, s2);

    if(ret == 0)
    {
        printf("s1=s2\n");
    }
    else if(ret>0)
    {
        printf("s1>s2\n");
    }
    else
    {
        printf("s1<s2\n");
    }
    return 0;
}

执行结果

s1>s2

当把"hella"改成"w"后,执行结果为:

s1<s2

这是因为,strcmp() 函数是逐字符比较的,只要出现不一样的 ASCII 码值,就会返回

2. strncmp() 函数

头文件:#include <string.h>
函数原型:int strncmp(const char *str1, const char *str2, size_t n);
这个函数接受三个参数:
str1:指向第一个要比较的字符串的指针。
str2:指向第二个要比较的字符串的指针。
n:要比较的字符数量。
返回值:
strncmp() 函数将会按照字典顺序(ASCII 码顺序)比较两个字符串的前 n 个字符。
如果第一个字符串 str1 的前 n 个字符按照字典顺序排在第二个字符串 str2 的前 n 个字符之前,则返回一个负整数;
如果两个字符串的前 n 个字符相等,则返回 0;
如果第一个字符串 str1 的前 n 个字符按照字典顺序排在第二个字符串 str2 的前 n 个字符之后,则返回一个正整数。

例:

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

int main()
{
    char s1[] = "hello";
    char s2[] = "hella";

    int ret = strncmp(s1, s2, 4);

    if(ret == 0)
    {
        printf("s1=s2\n");
    }
    else if(ret>0)
    {
        printf("s1>s2\n");
    }
    else
    {
        printf("s1<s2\n");
    }
    return 0;
}

执行结果:

s1=s2

五、字符查找函数

1. strchr() 函数

头文件:#include <string.h>
函数原型:char *strchr(const char *str, int c);
这个函数接受两个参数:
str:指向要搜索的字符串的指针。
c:要查找的字符,以 ASCII 码的形式表示。
strchr() 函数会在字符串 str 中查找字符 c 第一次出现的位置,并返回一个指向该位置的指针。
返回值:
如果在字符串 str 中找到了字符 c,则返回指向该字符的指针;
如果在字符串 str 中未找到字符 c,则返回空指针 NULL。

例:

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

int main()
{
    char s[] = "he6llo wo6rld";
    char *ret = strchr(s, '6');

    if(ret == NULL)
    {
        printf("not found\n");
    }
    else
    {
        printf("found it, pos = %d\n", ret - s);
    }
    return 0;
}

执行结果:

found it, pos = 2

2. strrchr() 函数

strrchr()用于在字符串中查找指定字符的最后一次出现的位置。
头文件:#include <string.h>
函数原型:char *strrchr(const char *str, int c);
这个函数接受两个参数:
str:指向要搜索的字符串的指针。
c:要查找的字符,以 ASCII 码的形式表示。
strrchr() 函数会在字符串 str 中从后向前查找字符 c 最后一次出现的位置,并返回一个指向该位置的指针。
返回值:
如果在字符串 str 中找到了字符 c,则返回指向该字符的指针;
如果在字符串 str 中未找到字符 c,则返回空指针 NULL。

例:

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

int main()
{
    char s[] = "he6llo wo6rld";
    char *ret = strrchr(s, '6');

    if(ret == NULL)
    {
        printf("not found\n");
    }
    else
    {
        printf("found it, pos = %d\n", ret - s);
    }
    return 0;
}

执行结果:

found it, pos = 9

六、字符串匹配函数

strstr用于在字符串中查找指定子字符串的第一次出现的位置。
头文件:#include <string.h>
函数原型:char *strstr(const char *haystack, const char *needle);
这个函数接受两个参数:
haystack:指向要搜索的主字符串的指针。
needle:指向要搜索的子字符串的指针。
strstr() 函数会在主字符串 haystack 中查找子字符串 needle 的第一次出现的位置,并返回一个指向该位置的指针。
返回值:
如果在主字符串 haystack 中找到了子字符串 needle,则返回指向该子字符串的指针;
如果在主字符串 haystack 中未找到子字符串 needle,则返回空指针 NULL。

例:

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

int main()
{
    char s[] = "1234:5678:999:666";
    char *ret = strstr(s, "666");

    if(ret == NULL)
    {
        printf("没找到\n");
    }
    else
    {
        printf("找到了,在字符串的第%d个位置\n", ret - s);
    }
    return 0;
}

执行结果:

找到了,在字符串的第14个位置

七、字符串转换数值

atoi函数把字符串转换为 int 类型
头文件:#include <stdlib.h>
函数原型:int atoi(const char *nptr);\

int num;
num=atoi(“123”);

则 num 的值为 123

将字符串转换为 long 用 atol(const char *nptr);
将字符串转换为 double 用 atof(const char *nptr);

例:

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

int main()
{
    char s1[] = "1949";
    int ret1 = atoi(s1);
    printf("s1 = %d\n", ret1);

    char s2[] = "3.1415926";
    double ret2 = atof(s2);
    printf("s2 = %lf\n", ret2);
    return 0;
}

执行结果:

s1 = 1949
s2 = 3.141593

八、字符串切割函数

头文件:#include <string.h>
函数原型:char *strtok(char *str, const char *delim);
这个函数接受两个参数:
str:指向要切割的字符串的指针,第一次调用时传入要切割的字符串,后续调用时传入 NULL 表示继续处理上一次剩余的字符串。
delim:包含分隔符的字符串,用来指定在哪些字符处切割字符串。切割结果不包含 delim
strtok() 函数会从字符串 str 中按照 delim 中指定的分隔符进行切割,并返回第一个标记(token)。在第一次调用时,它会返回字符串 str 中第一个标记的指针,并用 null 字符替换标记的结尾,以便后续调用时能够从上一个标记的后面继续切割。在后续的调用中,如果传入的 str 参数是 NULL,则会继续处理上一次剩余的字符串,并返回下一个标记的指针。

例:

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

int main()
{
    char s[] = "111:222222:3333:44444444:55";
    char *ret;

    //第一次切割
    ret = strtok(s, ":");
    printf("ret = %s\n", ret);

    //后面所有切割,都要将NULL传入strtok的第一个参数
    while((ret = strtok(NULL, ":")) != NULL)
    {
        printf("ret = %s\n", ret);
    }
    return 0;
}

执行结果:

ret = 111
ret = 222222
ret = 3333
ret = 44444444
ret = 55

九、格式化字符串操作函数

1. sprintf() 函数

用于将格式化的数据写入到字符串中

头文件:#include <string.h>
函数原型:int sprintf(char *str, const char *format, ...);

这个函数接受至少两个参数:
str:指向目标字符串的指针,用于存储格式化后的数据。
format:格式控制字符串,包含了格式化输出的规则,类似于 printf() 函数中的格式控制字符串。
可变参数:根据格式控制字符串中的格式化说明符,提供要格式化的数据。

2. sscanf() 函数

用于从字符串中读取格式化的数据

头文件:#include <stdio.h>\ 函数原型:int sscanf(const char *str, const char *format, ...);`

这个函数接受至少两个参数:
str:指向包含要解析的字符串的指针。
format:格式控制字符串,包含了解析输入字符串的规则,类似于 scanf() 函数中的格式控制字符串。
可变参数:用于存储从字符串中解析得到的数据。

例:

#include <stdio.h>

void test1()
{
    char str[20];
    int a, b, c;

    sprintf(str, "%d:%d:%d", 2024, 5, 1);
    printf("str = %s\n", str);

    sscanf("2024:5:1", "%d:%d:%d", &a, &b, &c);
    printf("a = %d, b = %d, c = %d\n", a, b, c);
}

int main()
{
    test1();
    return 0;
}

执行函数:

str = 2024:5:1
a = 2024, b = 5, c = 1

sscanf()的高级用法

void test2()
{
    //1.跳过数据:用%*d或%*s
    char str1[20];
    sscanf("1234 5678", "%*d %s", str1);
    printf("%s\n", str1);

    //2.读取指定宽度的数据:%[width]s
    char str2[20];
    sscanf("12345678", "%4s", str2);
    printf("%s\n", str2);

    //3.支持集合操作
    //  %[a-z]表示匹配a到z中任意字符(尽可能多的匹配)
    //  %[aBc]匹配a、B、c中一员,贪婪性
    //  %[^aFc]匹配非a、F、c的任意字符,贪婪性
    //  %[^a-z]表示读取除a-z以外的所有字符
    char str3[20];
    sscanf("wr89gfhGKLw32", "%[a-z]", str3);
    printf("%s\n", str3);
}
int main()
{
    test2();
    return 0;
}

执行结果:

5678
1234
wr

十、const

1. 修饰全局变量,只读

只能使用不能修改
如果直接修改,那么编译直接报错
如果通过指针修改,那么程序异常结束

#include <stdio.h>

//1. const修饰全局变量
const int a = 100;
void test1()
{
    printf("a = %d", a);

    a = 666;//a只读,不能赋值直接修改
    printf("a = %d", a);

    int *p = &a;
    *p = 888;//也不能通过指针修改
    printf("a = %d", a);
}
int main()
{
    test1();
    return 0;
}

2. 修饰普通局部变量

不能直接通过变量名赋值修改,因为会编译报错,但可以通过地址修改

//2. const修饰普通局部变量
void test2()
{
    const int b = 100;
    printf("b = %d\n", b);

    // b = 666;//不能通过赋值直接修改
    // printf("b = %d\n", b);

    int *p = &b;
    *p = 888;
    printf("b = %d\n", b);
}
int main()
{
    test2();
    return 0;
}

执行结果:

b = 100
b = 888

3. 修饰指针变量

情况1:const修饰指针变量的类型

void test3()
{
    int c = 100;
    const int *p = &c;
    printf("*p = %d\n", *p);

    c = 666;
    printf("*p = %d\n", *p);

    *p = 777;
    printf("*p = %d\n", *p);

    int d = 888;
    p = &d;
    printf("*p = %d\n", *p);
}
int main()
{
    test3();
    return 0;
}

会报错:

说明不能通过指针修改地址里面的值

情况2:const修饰指针变量

const int *p = &c;改为int *const p = &c;

会报错:

说明无法修改指针变量里保存的地址

情况3:const既修饰类型又修饰变量

const int *p = &c;改为const int *const p = &c;

会同时报情况1和情况2的错误

说明只能通过变量名修改值

posted @ 2024-05-02 15:47  茴香豆的茴  阅读(167)  评论(0)    收藏  举报