头文件:
#include <string>
知识点一:指针保存字符串
#include<stdio.h>
void main()
{
char* a = "hello111"; //指针变量a 指向 字符串首地址
printf("%s",a);
}
知识点二:测量字符串长度
返回值为字符串的长度不包含 '\0'
//s:被测量的字符串首元素地址
size_t strlen(const char *s) //strlen(被测量的字符串首元素地址(一般是数组名))
void test01()
{
char buf1[128] = "hehehe";
char buf2[] = "hehehe";
char buf3[] = "hehe\0he";
// \123 代表一个字符,\hhh 八进制转义h: 0~7
//\\表示'\'
char buf4[]="hehe\123\\he";
//\\x2f表示一个字符 \xdd 十六进制转义 d:0~9 a~f
char buf5[]="hehe\x2fhe";
printf("%d\n",sizeof(buf1));//128
printf("%d\n",strlen(buf1));//6
printf("%d\n",sizeof(buf2));//7
printf("%d\n",strlen(buf2));//6
printf("%d\n",sizeof(buf3));//8
printf("%d\n",strlen(buf3));//4
printf("%d\n",sizeof(buf4));//9
printf("%d\n",strlen(buf4));//8
printf("%s\n",buf4);
printf("%d\n",sizeof(buf5));//8
printf("%d\n",strlen(buf5));//7
char buf6[]="\0hehe\0hehe";
printf("%d\n",strlen(buf6));//0
return;
}
知识点三:字符串拷贝
1、strcpy
遇到'\0'会结束,只是'\0'也会拷贝过去
//功能:把 src 所指向的字符串 复制 到dest 所指向的空间中
原型:
char *strcpy(char *dest, const char *src)
//返回值:返回dest字符串的首地址
void test1()
{
char src[] = {"hello\0string"};
//保证dst足够大
char dst[128] = "";
strcpy(dst,src);
printf("dst = %s\n",dst); //hello
}
2、strncpy
'\0'不拷贝
//功能:把 src 指向字符串的前 num 个复制到 dest 所指向的空间中
原型:
char *strncpy( char *dest, const char *src, int num)
//返回值:返回dest字符串的首地址
void test1()
{
char src[] = {"hello string"};
//保证dst足够大
char dst[128] = "";
strncpy(dst,src,3);
printf("dst = %s\n",dst); //"hel"
}
知识点四:字符串拼接
1、strcat
char *strcat(char *dest, const char *src);
//将 src 的字符串拼接到 dst 的末尾(dst第一个'\0'的位置 )
void test1()
{
char src[] = {"wor\0ld"};
char dst[128] = "hello";
strcat(dst, src);
printf("dst = %s\n", dst); //hellowor
}
2、strncat
'\0'一起拷贝过去
//功能:将str2前num个字母连接到str1后面
原型:
char *strncat (char *str1, char *str2, int num)
返回值:返回str1字符串的首地址
void test1()
{
char src[] = {"world"};
char dst[128]="hello";
strncat(dst,src,2);
printf("dst = %s\n",dst); //hellowo
}
知识点五:字符串比较
1、strcmp
整个字符串的比较
//功能:将s1和s2指向的字符串逐个字符比较
int strcmp(const char *S1,const char *s2);
返回值:
>0:表示s1 > s2
<0:表示s1 < s2
==0:表示s1 == s2
void test1()
{
char s1[] = "hehe haha";
char s2[] = "hehe xixi";
if(strcmp(s1,s2) > 0)
{
printf("s1 > s2\n");
}
else if(strcmp(s1,s2) < 0) //<0
{
printf("s1 < s2\n");
}
else if(strcmp(s1,s2) == 0)
{
printf("s1 == s2\n");
}
}
2、strncmp
局部字符串的比较,比较两个字符串的前 n 个字节是否一样
void test1()
{
char s1[] = "hehe haha";
char s2[] = "hehe xixi";
if(strncmp(s1,s2,3) > 0)
{
printf("s1 > s2\n");
}
else if(strncmp(s1,s2,3) < 0)
{
printf("s1 < s2\n");
}
else if(strncmp(s1,s2,3) == 0) //== 0
{
printf("s1 == s2\n");
}
}
知识点六:字符查找函数
//功能:在字符串 str1 中查找字母 ch 出现的位置
原型:
char* strchr (const char *str1, char ch)
//返回值:返回 第一次 出现的 ch地址,如果找不到,返回NULL
void test1()
{
char str[] = "www.1000phone.com";
char *ret = NULL;
ret = strchr(str,'o');
if(ret != NULL)
{
*ret = '#';
}
printf("str=%s\n",str); //"www.1000ph#ne.com";
}
知识点七:字符串查找
//从 s1 中查找字符串 s2,返回 第一次 s2 出现的地址
char *strstr(const char *s1,const char *s2);
//查找失败返回NULL
void test1()
{
char s1[] = "www.sex.777.sex.com";
char s2[] = "sex";
char *ret = NULL;
ret = strstr(s1,s2);
if(ret == NULL)
{
return;
}
printf("%s\n",ret); //sex.777.sex.com
}
知识点八:替换字符函数
原型: void* memset (void *str, char C, int n)
功能:将 str 所指向的内存区的 前n个 全部用 c 填充
常用于清除指定空间,比如 数组 或 malloc 的空间
返回值:返回 str 的地址
知识点九:字符串转化数值
//功能:将 str 所指向的数字字符串转化为 int、long、double
//头文件:
#include<stdlib.h>
//转int
atoi(需要转的字符串)
//转long
atol(需要转的字符串)
//转double
atof(需要转的字符串)
void test1()
{
printf("%d\n", atoi("123")); //123
printf("%ld\n", atol("12356")); //12345
printf("%f\n", atof("12.3")); //12.300000
}
知识点十:字符串切割函数
//第一次切割:str必须指向要切割的字符串首元素地址,delim指向要切割的符号
//第2~n次切割: str必须指向NULL delim指向要切割的符号
char *strtok(char *str,const char *delim);
//返回值:切割成功返回切割到字符换片段的首元素地址,失败: NULL
//注意: strtok 不能切割字符串常量
/*
"hehe:haha:xixi:lala"
如果切制完成会产生 "hehe" "haha" "xixi" "lala"
一般选择char *arr[] 指针数组来存放上面独立的字符串的首元素地址
*/
void test1(void)
{
char buf[] ="hehehe:haha:xixi:lala:heihei:henhen";
char *arr [32]= {NULL} ;
int i=0;
//第1次切割
arr[i] = strtok(buf,":@#") ;
//第2~n切割
while(arr[i] != NULL) //保证上一次切割正常才有进行下一次切割的必要
{
i++ ;
arr[i] = strtok (NULL,":");
}
//遍历切割的内容
i=0;
while(arr[i] != NULL)
{
printf ("%s\n",arr[i]);
i++;
}
}
知识点十一:格式化输出
//str :用来存放组装好的数据
//"格式":组装格式
//数据: 各个零散的数据
int sprintf(char *str, "格式",数据)
返回值:返回值的是组好的报文的实际长度(不包含'\0')
void test1(void)
{
int year = 2020;
int mon = 2;
int day = 24;
int len = 0;
//需求:将2020 2 24组 成一个"2020年2月24日"
char buf[ 128] = "";
//%d 和 year 类型要一一对应
len = sprintf (buf, "%d年%d月%d日", year, mon, day);
printf("len = %d\n",len);
printf("buf=%s\n", buf);
}
知识点十二:提取格式字符串
从一个字符串中提取字符串,浮点数,整数等值,并将其保存到指定的变量中
sscanf(被提取的字符串,"提取格式",保存的地址,....);
//成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF
void test09()
{
char buf[] = "2020年2月24日";
int year = 0;
int mon = 0;
int day = 0;
char ch = 0;
char str_year[32] = "";
char str_mon[32] = "";
char str_day[32] = "";
//%d 只能提取'0'~'9'
sscanf(buf,"%d年%d月%d日", &year, &mon, &day );
printf("year = %d\n", year); //2020
printf("mon = %d\n", mon); //2
printf("day = %d\n", day); //24
//%c 提取一个字符 %f 提取提取浮点数
sscanf(buf,"%c", &ch);
printf("##%c##\n",ch); //'2'
//%s 提取一个字符串 遇到空格、回车、'\0' 停止获取
//buf==>"2020年2月24日"
sscanf(buf,"%s年%s月%s日", str_year, str_mon,str_day );
printf("str_year=%s\n", str_year); //"2020年2月24日"
printf("str_mon=%s\n", str_mon); //null
printf("str_day=%s\n", str_day); //null
}
sscanf高级用法
使用%*s %*d 跳过提取的内容(不要提取的内容)
void test1(void)
{
int datal = 0;
//sscanf("1234 5678", "1234 %d", &datal); //5678
//sscanf("1234 5678","%*d %d", &datal); //5678
sscanf("1234 5678","%*s %d", &datal); //5678
printf("datal = %d\n", datal);
}
使用%*ns %*nd提取指定宽度n的字符串或数据 n:需要的字节数
void test1(void)
{
int datal = 0;
int data2 = 0;
char buf[16]="";
sscanf ("12abc5678","%*5s%d",&datal) ;//5678
printf("datal=%d\n", datal);
sscanf ("12345678", "%*2s%2d%*2d%s",&data2,buf); //data2=34 buf="78";
printf("data2 = %d\n", data2); //34
printf("buf=%s\n",buf); //"78'
}
%[a-z]提取a-z的
字符串
void test1(void)
{
char buf[128]="";
//%[]都是按 字符串 提取
sscanf("abcDefABC", "%[a-z]",buf);
printf("buf=%s\n",buf); //"abc"
}
%[aBc] 提取 a B c
void test1(void)
{
char buf[128]="";
//%[]都是按 字符串 提取
sscanf("aaBBcEdef", "%[aBc]",buf);
printf("buf=%s\n",buf); //aaBBc
}
%[^abc]提取不是a b c其中一个的字符串
void test1(void)
{
char buf[128]="";
//%[]都是按 字符串 提取
sscanf("ABCcABC", "%[^abc]",buf);
printf("buf=%s\n",buf); //ABC
}
知识点十三:const关键字
const修饰 变量 为只读
void test1(void)
{
//const修饰num为只读变量 num 只能取值 num不能被赋值
//const 修饰的变量 尽量 初始化
const int num = 10;
printf("num = %d\n",num) ;//ok
//num = 100; //err num不能被赋值
printf("&num = %p\n",&num); //0019FED8
//但是如果知道num的地址也可以间接的修改num的值(一般不这么做)
*(int *)(&num) = 1000; //少干
printf("num = %d\n",num); //结果:num = 1000
}
const * int p
const在*的左边表示const修饰的是
*而不是p用户不能借助*p更改空间的内容,但是p可以指向其他空间(*p只读,p可读可写)
void test1(void)
{
int num1=10;
int num2 = 20;
//const在*的左边 *p只读 p可读可写
const int *p = &num1;
printf("*p = %d\n",*p); //10
//*p = 1000; //err *p只读
p = &num2; //ok p可读可写
printf("*p = %d\n",*p); //20
}
int * const p
const在*的右边const修饰的是
p而不是*用户可以通过*p修改p所指向空间的内容,但是不能再更改p的指向(*p可读可写,p只读)
void test1(void)
{
int num1 = 10;
int num2 = 20;
//const在*的右边 *p可读可写 p只读
int * const p = &num1; //p一旦初始化 就不能更改指向
printf("*p = %d\n",*p); //10
*p = 1000; //ok *p可读可写
printf("*p = %d\n",*p); // 1000
//p=&num2; //err p只读
}
const int * const p (*p只读,p只读)
void test1(void)
{
int num1 = 10;
int num2 = 20;
const int * const p = &num1; //*p和p都是只读
//*p = 1000; //err *p只读
//p = &num2; //err p只读
}