一、获取字符串长度函数
头文件:#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的错误
说明只能通过变量名修改值