概念&定义
字符串 -- 就是字符数组
两种定义方式:
char str[]="hello"; //字符串变量,能修改
char *str1="hello"; //字符串常量,不允许被修改
printf -- %s -- 控制字符串输入
//野指针 -- 没有明确的内存指向
#include<stdio.h>int main()
{
char str[]={'h','e','l','l','o'};
char str2[]="hello";
char *str3="hello";
// for(int i=0;i<5;++i)
// {
// printf("%c",*(str3+i));
// }str2[3]='m';
printf("%s\n",str2);
// str3[0]='m'; // 不可以
printf("%s\n",str3);
return 0;
}
================================================
字符串和字符数组的区别: -- ‘/0’
char str[]={'h','e','l','l','o'};
char str2[]="hello"; //在调用的"" 修饰字符串的时候,会在最后一个字符后面加入字符串结束标准-- '/0'
str2[] ={'h','e','l','l','o','/0'};
验证程序:
#include<stdio.h>int main()
{
char str[]={'h','e','l','l','o'};
char str2[]="hello";
char *str3="hello";
int len1=sizeof(str)/sizeof(str[0]);
int len2=sizeof(str2)/sizeof(str2[0]);
int len3=sizeof(str3)/sizeof(str3[0]);printf("len1: %d\n",len1); // 5
printf("len2: %d\n",len2); // 6
printf("len3: %d\n",len3); // 8 -- 他是一个指针
return 0;
}
================================================
sizeof 和 strlen ---的区别
计算字符串大小一般使用 strlen -- 只计算有效字符的长度 ,不算'/0'
sizeof -- 计算整个数组的大小
strlen -- 计算有效字符的大小
#include<stdio.h>
#include<string.h>int main()
{
char str[]={'h','e','l','l','o'};
char str2[100]="hello";printf("sizeof() -- %d\n",sizeof(str2)); // 100 后面多个,未初始化的空间用'/0'填充
printf("strlen() --%d\n ",strlen(str2)); // 5 个有效字符
char *str3="hello";printf("sizeof(str3):%d\n",sizeof(str3)); //8 -- 指针
printf("sizeof(char*):%d\n",sizeof(char*));//8
printf("sizeof(int*):%d\n",sizeof(int*));//8printf("strlen(str3):%d\n",strlen(str3)); //5
return 0;
}
================================================
动态内存管理
malloc -- 动态开辟字符串:
原型:void* malloc(size); -- 分配所需的内存空间,并且返回指向这段空间的指针
注: malloc 在堆上面开辟空间,要到程序结束的时候才释放,需要手动free 释放
而 局部变量 是在栈 上面开辟的空间,出了函数就释放了
realloc -- 扩容
原型: void *realloc(void *ptr,size);
尝试重新调整 之前使用malloc 或者 calloc 所分配的内存块大小
free
原型: void free(void *ptr); -- 释放之前malloc,clloc,realloc 所分配的内存空间
-- 防止内存泄漏
memset(); -- 内存初始化
原型:void *memset(void *str,int c,size_t n); ,作用是将某一块内存中的全部设置为指定的值
- str指向要填充的内存块。
- c是要被设置的值。
- n是要被设置该值的字符数。
- 返回类型是一个指向存储区s的指针。
char *str;
str=(char*)malloc(5);
memset(str,'\0',5);
悬挂指针 -- 野指针的一种
当指针指向的内存空间已经被释放,但是该指针没有任何的改变,以至于仍然指向已经被回收的内存地址,这种情况下该指针就被称为悬挂指针。
int *p;
p=(int*)malloc(5);
free(p); //这个时候是悬挂指针
p=NULL; // 赋值后不再悬挂
p=(char*)malloc(20);
野指针
野指针是指尚未初始化的指针,它指向的地址是未知的、不确定的、随机的。
产生的原因:
释放内存后指针没有及时置空,依然指向该内存,有可能会出现非法访问的错误。
避免方法:
初始化置NULL
申请内存后判空
指针释放后NULL
使用智能指针
================================================
常见字符串操作API
输出字符串:put printf
char *str;
puts(str);
printf("%s\n",str);
获取字符串:gets scanf
scanf("%s",str):
原型: char *strcpy(char *dest,const char *src);
gets()
原型: char *gets(char* str);
注: 因为改函数可以无限读取,容易发送溢出,溢出的字符覆盖到堆栈中的内容中,破坏其他变量的值
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *str="wasaiwnh";
puts(str);
printf("%s\n",str);
char *str2;
puts("请输入一个字符串:");
//scanf("%s",str2);
gets(str2);
puts(str2);
return 0;
}
strcpy(); -- 字符串拷贝
strcpy()-是将一个字符串复制到另一块空间地址中 的函数,‘\0’是停止拷贝的终止条件
原型: char* strcpy(char* destination,const char* source);
1. 函数的参数:
char* destination---------目标字符串的首地址
const char* source------源地址:被复制的字符串的首地址,用const修饰,避免修改掉被拷贝的字符串
2.函数的返回值类型:char*:返回的是目标字符串的首地址
strncpy(); -- 字符串拷贝
char* strncpy(char* str,const char *scr,int count); -- 指定复制长度count 的 拷贝
test
重写上面两个拷贝
#include<stdio.h>
#include<string.h>
#include<stdlib.h>char *myStrcpy(char *des,char *src )
{
if(des==NULL && src==NULL)
{
return NULL;
}
//先把des 一开始的地址记录起来
char *start=des;
// while(*src!='\0')
// {
// //写法1:
// // *des=*src;
// // des++;
// // src++;
// //写法2:
// *des++=*src++;
// }while((*des++=*src++)!='\0'); //先复制在判断
*des='\0'; //拷贝完记得,加上结束标识符
return start;
}
char *myStrncpy(char *des,char *src,int count)
{
if(des==NULL && src==NULL)
{
return NULL;
}
//先把des 一开始的地址记录起来
char *start=des;while(*src!='\0' && count >0)
{
*des++=*src++;
count--;
}if(count){
while(count)
{
*des++='\0';
count--;
}
return des;
}*des='\0'; //拷贝完记得,加上结束标识符
return start;
}int main()
{
//char str[100]={'\0'};
char *str;
str = (char*)malloc(100);
char *p="megniDXASDFA";
//myStrcpy(str,p);
myStrncpy(str,p,20);
puts(str);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
// int *p;
// p=(int *)malloc(1); // 给指针p 分配内存空间,防止野指针
// *p=11;
// printf("1 %d\n",*p);
// free(p);
// printf("2 %d\n",*p);
char *str;
str=(char*)malloc(5);
int len1=strlen("mxmxdhljkdadsadadadsada");
printf("扩容前地址 -- %p\n",str);
int moreLen=len1-5+1; // +1 -- '/0'
realloc(str,moreLen);
printf("扩容后地址 -- %p\n",str);
strcpy(str,"mxmxdhljkdadsadadadsada"); //越界了
puts(str);
return 0;
}
assert(断言)
-- if else 的替代品:
用法:
include<assert.h>
assert(expression);
作用: 计算表达式experrsion的值,if为假,他的stderr打印一条错误信息,通过aboor来终止程序运行
//报错信息
Assertion failed!
Program: D:\All_for_code\code_of_c\a.exe
File: stringT2.c, Line 7
Expression: des!=NULL && src!=NULL
===================================================
strcat -- 字符串拼接
原型: char *strcat(char *dest,const chatr *src);
将src所指向的字符串复制到 dest所指向的字符串后面,(删除dest末尾的‘\0’),请确保dest足够长,返回指向dest的指针
#include<stdio.h>
#include<string.h>
#include<assert.h>
char *myStrcat(char *des,char *src)
{
assert(des!=NULL && src!=NULL);
char* start=des;
while(*des != '\0')
{
des++;
}
while((*des++ = *src++)!='\0');
*des='\0';
return start;
}
char *myStrcat2(char *des,char *src)
{
char *start=des;
strcpy(des+strlen(des),src);
return start;
}
int main()
{
char str[50]="merngxoiangege";
char *p;
char *p2=" hamesome";
p=myStrcat2(str,p2);
puts(p);
puts(str);
return 0;
}
===================================================
strcmp --字符串比较 -- 主要判断是否相等
原型: int strcmp(const int*s1,const int* s2) --
返回值: // 字符比较大小遵循字典数 -- 比较完前面的,才比较后面的
s1 = s2 返回0
s1 > s2 返回正数 -- 1
s1<s2 返回负数 -- -1
strncmp -- 只比较前n个字节
#include<stdio.h>
#include<string.h>int myStrcmp(char *str1,char *str2)
{
int res=0;
int n1,n2;
char *sta1=str1;
char *sta2=str2;
while(*str1&&*str2&&(*str1==*str2))
{
str1++;
str2++;
}
if( *str1|| *str2)
{
str1=sta1;
str2=sta2;
while(*str1)
{
n1+=*str1;
str1++;
}
while(*str2)
{
n2+=*str2;
str2++;
}
}
res=n1-n2;
if(res>0)res=1;
else if(res<0) res=-1;
else res=0;
return res;
}
int main()
{
char *p1="mengxiangjunb";
char *p2="mengxiangjunb";
int res = myStrcmp(p1,p2);
printf("%d\n",res);
return 0;
}
===================================================