第七章 字符串处理函数
7.1 获取字符串长度函数
头文件:#include <string.h>
函数定义:size_t strlen(const char *s)
函数功能:
测字符指针s指向的字符串中字符的个数,不包括’\0’
**返回值:**字符串中字符个数
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
// 使用strlen()函数获取字符串的长度
// strlen()获取的字符串的长度遇到第一个\0结束
char s1[100] = "hel\0lo world!";
printf("s1_len = %lu\n", strlen(s1));
printf("s1_size = %lu\n", sizeof(s1));
char *s2 = "hel\0lo world!";
printf("s2_len = %lu\n", strlen(s2));
printf("s2_size = %lu\n", sizeof(s2));
return 0;
}
执行结果:
7.2 字符串拷贝函数
头文件:#include <string.h>
函数的定义:char *strcpy(char *dest, const char *src);
函数的说明:
拷贝src指向的字符串到dest指针指向的内存中,'\0’也会被拷贝
函数的返回值:
目的内存的地址
**注意:**在使用此函数的时候,必须保证dest指向的内存空间足够大,否则会出现内存污染
函数的定义:char *strncpy(char *dest, const char *src, size_t n);
函数的说明:
将src指向的字符串前n个字节,拷贝到dest指向的内存中
返回值:
目的内存的首地址
注意:
- strncpy不拷贝’\0’
- 如果n大于src指向的字符串中的字符个数,则在dest后面填充n-strlen(src)个’\0’
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
// 使用strcpy()函数拷贝字符串
char s1[32] = "hello world";
// 使用strcpy函数时,必须保证第一个函数的参数的内存足够大
char s1[5] = "hello";
char s2[32] = "abcdefg";
strcpy(s1, s2);
printf("s1 = %s\n", s1);
for (size_t i = 0; i < 32; i++)
{
printf("[%c] -- %d\n", s1[i], s1[i]);
}
return 0;
}
执行结果:
7.3 字符串追加函数
头文件:#include <string.h>
函数定义:char *strcat(char *dest, const char *src);
函数功能:
strcat函数追加src字符串到dest指向的字符串的后面,追加的时候会追加’\0’
注意:
保证dest指向的内存空间足够大
函数定义:char *strncat(char *dest, const char *src, size_t n);
函数功能:
追加src指向的字符串的前n个字符,到dest指向的字符串的后面
注意:
如果n大于src的字符个数,则只将src字符串追加到dest指向的字符串的后面,追加的时候会追加’\0’
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
// 使用strcat函数追加字符串
char s1[32] = "hello world";
char s2[32] = "abcdef";
// strcat是从s1的\0的位置开始追加,直到s2的第一个\0复制完毕后结束
strcat(s1, s2);
printf("s1 = %s\n", s1);
return 0;
}
执行结果:
7.4 字符串比较函数
头文件:#include <string.h>
函数定义:int strcmp(const char *s1, const char *s2);
函数说明:
比较s1和s2指向的字符串的大小
比较的方法,逐个字符去比较ascll码,一旦比较出大小返回,如果所有字符都一样,返回0
返回值:
比较结果 | 返回值 |
---|---|
s1指向的字符串大于s2指向的字符串 | 1 |
s1指向的字符串等于s2指向的字符串 | 0 |
s1指向的字符串小于s2指向的字符串 | -1 |
函数定义:int strncmp(const char *s1, const char *s2, size_t n);
函数说明:
比较s1和s2指向的字符串中的前n个字符
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
// 使用strcmp函数比较两个字符串的内容是否一致
// strcmp函数一个字符一个字符比较,只要出现不一样的,就会立即返回
char s1[] = "hello";
char s2[] = "hello";
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;
}
执行结果:
7.5 字符串查找函数
头文件:#include <string.h>
函数定义: char *strchr(const char *s, int c);
函数说明:
在字符指针s指向的字符串中,找ascii码为c的字符。
注意:
是首次匹配,如果说s指向的字符串中有多个ascll为c的字符,则找的是第一个字符
返回值:
- 找到了,返回找到的字符的地址
- 找不到,返回NULL
函数定义:char *strrchr(const char *s, int c);
函数说明:
末次匹配,在s指向的字符串中,找最后一次出现ascll为c的字符
返回值:
末次匹配字符的地址
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
// 使用strchr函数中一个字符串中查找字符
char s[] = "hel6lo wor6ld";
char *ret = strchr(s, '6');
if (ret == NULL)
{
printf("没有找到\n");
}
else
{
printf("找到了,在数组的第%ld个位置\n", ret - s);
}
return 0;
}
执行结果:
7.6 字符串匹配函数
头文件:#include <string.h>
函数定义: char *strstr(const str *haystack, const char *needle);
函数说明:
在haystack指向的字符串中查找needle指向的字符串,也是首次匹配
返回值:
- 找到了,找到的字符串的首地址
- 没找到,返回NULL
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
// 使用strstr函数在一个字符串中查找另一个字符串
char s[] = "1234:4567:666:789:666:7777";
// strstr查找的时候,查找的是第二个参数的第一个\0之前的内容
char *ret = strstr(s, "666");
if (ret == NULL)
{
printf("没找到\n");
}
else
{
printf("找到了,在第%ld个位置\n", ret -s);
}
return 0;
}
7.7 字符串转换数值
头文件:#include <stdlib.h>
函数定义1:int atoi(const char *nptr);
函数定义2:long atol(const char *nptr);
函数定义3:double atof(const char *nptr);
函数的功能:
将nptr指向的字符串转换整数并返回
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
// 使用atoi将数字型字符串转换为整形数据
char s1[] = "7896";
int ret1 = atoi(s1);
printf("ret1 = %d\n", ret1);
// 使用atof将浮点型字符串转化为浮点型数据
char s2[] = "3.1415926";
double ret2 = atof(s2);
printf("ret2 = %lf\n", ret2);
return 0;
}
7.8 字符串切割函数
头文件:#include <string.h>
函数定义:*strtok(char *str, const char *delim);
函数功能:
对字符串进行切割
参数:
- str:要切割的字符串。第一次切割,就传入的指定的字符串,后面所有次的切割传NULL
- delim:标识符。要根据指定的delim进行切割,切割的结果不包含delim
返回值:
返回切割下来的字符串的首地址,如果都切割完毕,则返回NULL
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
// 使用strtok函数切割字符串
char s[] = "1111:22:3333:44:555";
char *ret;
// 第一次切割
ret = strtok(s, ":");
printf("ret = %s\n", ret);
// 后面所有的切割时,都要将strtok的第一个参数传NULL
while((ret = strtok(NULL, ":")) != NULL)
printf("ret = %s\n", ret);
return 0;
}
执行结果:
7.9 格式化字符串操作函数
函数定义:int sprintf(char *buf, const char *format, ...);
**函数功能:**输出到buf指定的内存区域
例如:
char buf[20];
sprintf(bufm "%d:%d:%d", 2013, 10, 1);
printf("buf=%s\n", buf);
函数定义:int sscanf(const char *buf, const char *format, ...);
**函数功能:**从buf指定的内存区域读入信息
例如:
sscanf("2013:10:1", "%d:%d:%d", &a, &b, &c);
printf("%d %d %d\n", a, b, c);
#include <stdio.h>
#include <string.h>
void test1()
{
char buf[20];
int a, b, c;
sprintf(buf, "%d:%d:%d", 2013, 10, 1);
printf("buf = %s\n", buf);
sscanf("2013:10:1", "%d:%d:%d", &a, &b, &c);
printf("a=%d, b=%d, c=%d\n", a, b, c);
}
// sscanf()高级用法
void test2()
{
// 1. 跳过数据:%*s或 %*d
char buf1[20];
sscanf("1234 5678", "%*d %s", buf1);
printf("%s\n", buf1);
// 2. 读指定宽度的数据: %[width]s
char buf2[20];
sscanf("12345678", "%4s", buf2);
printf("%s\n", buf2);
// 3. 支持集合操作:只支持获取字符串
// %[a-z] 表示匹配到a到z中任意字符,尽可能多的匹配
// %[aBc] 表示匹配a、B、c中的一员,贪婪性
// %[^aBc] 表示非a、B、c的任意字符,贪恋性
// %[^a-z] 表示读取除a-z以外的所有字符
char buf3[30];
sscanf("agcd32DajfDdFF", "%[a-z]", buf3);
printf("%s\n", buf3);
}
int main(int argc, char const *argv[])
{
test1();
test2();
return 0;
}
执行结果:
7.10 const
- const修饰普通变量,代表只读的意思
const int a = 100; //定义了一个只读变量a值为100
以后的程序里,不能再给a赋值了
a = 200; // 错误的,a只读
const修饰全局变量
#include <stdio.h>
// const 修饰全局变量
const int a = 100;
void test1()
{
// 此时全局变量只能使用,但是不能修改
printf("a = %d\n", a);
// 如果直接拿全局变量修改值,编译直接报错
a = 666;
printf("a = %d\n", a);
// 如果使用全局变量的地址修改值,运行时程序异常结束
int *p = &a;
*p = 888;
printf("a = %d\n", a);
}
int main(int argc, char const *argv[])
{
test1();
return 0;
}
a. 此时全局变量可以直接使用
b. 如果直接拿全局变量修改值,编译直接报错
c. 如果使用全局变量的地址修改值,运行时程序异常结束
const修饰普通局部变量:
#include <stdio.h>
// 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(int argc, char const *argv[])
{
test2();
return 0;
}
a. 可以直接读取变量的值
b. 不能直接通过变量进行修改值,会编译报错
c. 可以通过变量的地址修改值(但是存在警告“警告:使用类型为“const int *”的表达式初始化“int *”将丢弃限定符”)
- const修饰指针
const char *str
,意思是str指向的内存的内容不能通过str来修改
用来保护str指向的内存的内容,但是str的指向是可以改变的
例如:char *strcpy(char *dest, const char *src);
#include <stdio.h>
// const修饰指针变量
void test3()
{
int c = 100;
// const修饰指针变量的类型,无法通过指针变量修改地址里面的值
const int *p = &c;
// const修饰指针变量,无法修改指针变量保存的地址
int * const p1 = &c;
// const既修饰指针变量的类型,又修饰指针变量,只能通过修改原本变量修改值
const int * const p2 = &c;
printf("*p = %d, *p1 = %d, *p2 = %d\n", *p, *p1, *p2);
c = 666;
printf("*p = %d, *p1 = %d, *p2 = %d\n", *p, *p1, *p2);
// *p = 777;
*p1 = 777;
printf("*p1 = %d\n", *p1);
*p2 = 777;
printf("*p = %d, *p1 = %d, *p2 = %d\n", *p, *p1, *p2);
int d = 888;
p = &d;
printf("*p = %d\n", *p);
p1 = &d;
p2 = &d;
printf("*p = %d, *p1 = %d, *p2 = %d\n", *p, *p1, *p2);
}
int main(int argc, char const *argv[])
{
test3();
return 0;
}
- const修饰指针变量的类型,无法通过指针变量修改地址里面的值
#include <stdio.h>
// const修饰指针变量
void test3()
{
int c = 100;
// const修饰指针变量的类型,无法通过指针变量修改地址里面的值
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(int argc, char const *argv[])
{
test3();
return 0;
}
- const修饰指针变量,无法修改指针变量保存的地址
#include <stdio.h>
// const修饰指针变量
void test3()
{
int c = 100;
// const修饰指针变量,无法修改指针变量保存的地址
int * const p1 = &c;
printf("*p1 = %d\n", *p1);
c = 666;
printf("*p1 = %d\n", *p1);
*p1 = 777;
printf("*p1 = %d\n", *p1);
int d = 888;
p1 = &d;
printf("*p1 = %d\n", *p1);
}
int main(int argc, char const *argv[])
{
test3();
return 0;
}
- const既修饰指针变量的类型,又修饰指针变量,只能通过修改原本变量修改值
#include <stdio.h>
// const修饰指针变量
void test3()
{
int c = 100;
// const既修饰指针变量的类型,又修饰指针变量,只能通过修改原本变量修改值
const int * const p2 = &c;
printf("*p2 = %d\n", *p2);
c = 666;
printf("*p2 = %d\n", *p2);
*p2 = 777;
printf("*p2 = %d\n", *p2);
int d = 888;
p2 = &d;
printf("*p2 = %d\n", *p2);
}
int main(int argc, char const *argv[])
{
test3();
return 0;
}