栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

10天学会C语言——字符串

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

10天学会C语言——字符串

定义方式 字符数组

char str[]={'h','e','l','l','o'};或者char str[]="hello";

数组方式定义且初始化,开的空间是合法空间,访问的时候,可通过下标法访问。因为访问的都是字符变量,所以可以修改字符数组的内容。

strlen(str)值是5,而sizeof(str)值是6,说明字符串初始化时候,系统会自动在输入的字符串最后添加表示字符串的结尾。由此要注意:为字符串开空间时记得多开一个空间用于存放,不然越界可能会发生一些奇怪的错误

strlen和sizeof区别

strlen求字符串长度,传参传字符串名字,会从首地址数起,直到找到,记录大小时不计入。sizeof求空间大小,传参类型所占的空间有多大,值就有多大。

字符数组strlen求有效字符串长度,sizeof求整个数组大小,指针字符串strlen求有效字符串长度,sizeof求的是这个字符串首字符地址的大小

字符串指针

char *str="hello";

指针方式定义且初始化,是将常量区这片字符串的地址直接赋值给指针,访问的时候,通过指针偏移取内容访问。因为是该指针指向的是常量区的地址,这片地址的值是不允许修改的。所以如果想直接通过指针取内容修改字符串内容,会segmentation fault段错误。

注意字符数组和字符串指针两者定义方式区别就在于空间的类型不同,前者是字符串变量,后者是字符串常量。数组方式是开一片合法地址空间,然后往空间里面赋值,这些空间里面的值可以自定义。指针方式并非另外开了一片空间,而是直接指向常量区的地址,该地址里面本来就有一些常量字符串,这些字符串只能使用,不能修改。

如果想通过指针方式定义字符串,而且允许修改,定义时候可以:

第一种:

char p[size]; char *str=p;scanf("%s",str);

第一种方式是开一片合法空间在栈区,size值为常量,该空间大小固定,然后用str指向该空间,再把str直接当字符串使用。

第二种:

char *str=(char *)malloc(size);scanf("%s",str); 

第二种方式是动态开辟一片空间在堆区,size值可以是变量,空间大小还可以通过realloc来扩大之前malloc开辟的空间,str指向该空间,再把str当字符串使用。

指针方式定义字符串,指针名本质上是字符串首字符的地址,但是该指针名可以当做字符串的名字使用,所以访问的时候,可以直接通过字符串名字输出,也可以通过指针取内容方式依次取出每个字符输出。

#include

int main(){
	
	char *str="123abc";	
	for(int i=0;i<6;i++){
		printf("%c",*(str+i));//str本质是地址
	}
	puts("");
	printf("%sn",str); //str可以当字符串名使用
	printf("%pn",str); //str本质是地址
	puts(str);      //str当字符串名使用
	
}

相关API malloc

malloc传参直接传开辟空间大小,开辟空间不赋初值,开辟不成功return NULL;

calloc

calloc传参第一个参数是空间个数,第二个参数是没一个空间大小,开辟空间自动赋初值0,开辟不成功return NULL;

realloc

realloc额外扩大malloc或者calloc开辟的空间,第一个参数传空间首地址,第二个参数传扩容的大小,扩容成功且原地址后额外空间足够大则返回原地址,若原地址后额外空间小于需要扩容的空间,则会新找合适大小的空间,将原数据拷贝到新空间,再返回新空间的地址,原空间会自动释放。若内存已无足够大小空间,则扩容失败return NULL。

memset

memset会为一段连续的空间统一赋值,第一个参数是目标地址,第二个参数是赋值内容,第三个参数是赋值的空间数量。

gets

gets函数可以完全取代scanf("%s",str),可以直接输入带空格的字符串,而且使用gets函数系统会将最后敲的换行符从缓冲区丢弃,以致于多次gets函数之间不需要吸收回车清空缓存区

但是需要注意gets可以读取任意多少字符,需要让赋值地址的空间足够大,不然很容易造成内容泄露,发生一些奇怪的错误。

strcpy和strncpy

strcpy可以拷贝整个字符串到新的地址,并且末尾追加,第一个参数的目标字符串,第二个参数是源字符串,要保证目标字符串的空间大于源字符串的空间。strncpy多第三个参数n,拷贝的字符串是前n个字符,不会追加需要手动添加,如果n大于整个字符串的长度,多余的部分会以填充

memcpy

memcpy可以拷贝任意内容,不只是字符串,而且有第三个参数n规定拷贝空间的大小。

strcmp和strncmp

strcmp按字典序通过字符ascii码大小比较两个字符串,第一个参数是第一个字符串,第二个参数是第二个字符串,若第一个字符串大于第二个字符串return 1

相等return 0,小于return -1。strncmp多第三个参数n,比较两字符串的前n个字符。

strcat和strncat

strcat用于将源字符串拼接到目标字符串尾部,第一个参数是目标字符串,第二个参数是源字符串,调用后原目标字符串尾部的会被源字符串的首字符替代,调用完成后目标字符串的尾部会追加。strncat多第三个参数n,将源字符串的前n个字符拼接到目标字符串尾部。

strstr

strstr用于判断源字符串是否是目标字符串的子串,第一个参数是目标字符串,第二个参数是源字符串,如果是return目标字符串第一次出现源字符串的指针,如果不是return NULL;

strchr

strstr用于判断源字符是否是目标字符串的子字符,第一个参数是目标字符串,第二个参数是源字符,如果是return目标字符串第一次出现源字符的指针,如果不是return NULL;

strtok

strtok用于分割目标字符串,第一个参数是目标字符串,第二个参数是分割字符串,分割字符串中的每一个字符都可以作为目标字符串的分隔符。第一次调用传入目标字符串,分割成功return 分割出来的字符串的首地址,如果不可分割则return NULL。而后多次调用传入第一个参数为NULL,可以继续分割目标字符串,注意分割操作会修改目标字符串的内容,如果不想修改目标字符串,可以拷贝一份。

一些注意事项

对于自加,i++,先用再加,先运算完整个表达式再自加,一个语句分号前都是运算表达式。

对于断言assert(expresstion),括号中写程序正常运行的条件,只要程序运行到assert时,expression表达式的值为false,即不满足条件了,assert函数想stderr打印一条错误信息,再调用abort终止程序运行。可以在合适的地方设置断言,防止程序运行过程中,遇到一些隐患可以及时停止。比如规定输入小于40个字节大小的字符串,可以在获取输入后,设置断言,检查字符串的空间大小,超过40字节则程序停止运行。

作业案例:自己实现常用字符串API

#include
#include
#include
#include
char* Mystrcpy(char *des,char *srs){
	 assert(des!=NULL&&srs!=NULL); 
	char *backup=des;
	while(*backup++=*srs++); //就算while循环{}没有内容;不能少
	//src最后的先赋值给backup,backup再判断,为假,不执行{}的代码。但是++运算符已经运行了,最后backup仍然会自加。
	return des;
	
}
char* Mystrncpy(char *des,char *srs,int count){
	assert(des!=NULL&&srs!=NULL); 
	char *backup=des;
	while((*backup++=*srs++)&&count>0){   //i++,i的值会在自加所在的语句运行完之后再自加
	    count--;
	}
	if(count>0){
		while(count>0){
			count--;
			*backup++='';
		}
	}
    *(backup-1)='';
	return des;
	
}
int Mystrcmp(char *des,char* srs){
	assert(des!=NULL&&srs!=NULL);
    int res=0;	
	while(!(res=(*des++)-(*srs++))&&*des&&*srs);
	if(res>0)res=1;
	if(res<0)res=-1;
	return res;
	
}
int Mystrncmp(char *des,char* srs,int size){
	assert(des!=NULL&&srs!=NULL);
    int res=0;	
	while(!(res=(*des++)-(*srs++))&&*des&&*srs&&size>1)size--;
	if(res>0)res=1;
	if(res<0)res=-1;
	return res;
}
char* Mystrcat(char *des,char* srs){
	assert(des!=NULL&&srs!=NULL);
	char *backup=des;
	while(*backup){  //backup为时,就不自加了,如果++写在()里面,backup=''之后仍会自加;
		backup++;
	}
	while((*backup++)=(*srs++));
	*backup='';
	return des;
	
}
char* Mystrncat(char *des,char* srs,int count){
    assert(des!=NULL&&srs!=NULL);
	char *backup=des;
	Mystrncpy(backup+strlen(des),srs,count);
	return des;
}

int Mystrstr(char* des,char* srs){
	assert(des!=NULL&&srs!=NULL);
	int srslen=strlen(srs);
	int res=0;
	int cnt=1;
	if(!srslen){
		return -999;
	}
	while(*des!=''){
		if(*des==*srs){
		res=Mystrncmp(des,srs,srslen);
		if(res==0){
		 return cnt;
		}
	  }
		des++; 	
		cnt++;
	}
	return -1;
}

char* Mystrchr(char *des, char c){
	assert(des!=NULL);
	while(*des!=''&&*des!=c)des++;
	if(!(*des))return NULL;
	return des;
}

char* Mystrtok(char *srs,char *delim){
	assert(delim!=NULL);
	char*p =(char *)malloc(3);
	Mystrcpy(p,"nexit");
	static char *remain;
	int len=strlen(delim);
	char de[100];
	for(int i=0;i 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1034039.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号