字符串
字符串的定义和使用
字符串输出的占位符是%s
字符传递结尾都是有个’\0’的字符。
字符串变量的定义
字符串可以理解为是一个字符数组,C语言中没有字符串类型的变量,连续的字符是保存在字符数组中的,
例子:char arry[]={'h','e','l','l','o','w'};
==上面的例子就是一个字符串,==可以换成另一种简便写法:char arry[]="hellow";
使用双引号括起来是一种简单写法,以上都是字符串变量
字符串常量的定义
使用字符类型的指针指向字符串,例子:
char *p="hellow";
这个就是字符串常量,字符串常量是不可以被修改的,字符串变量是可以被修改的这个就是两者之间的区别
验证代码:使用字符串
#include<stdio.h>
int main()
{
//字符串常量的定义和使用
char arry[]="hellow"; //定义一个字符串变量
char *a="hellow";//定义一个字符串的常量
//通过puts()来打印
puts(a);
puts(arry);
//通过printf函数以%s方式进行解析
printf("arry里面存放是字符串是%s\n",arry);
printf("指针变量a指向了一个字符串的地址,地址里面是%s\n",a);
//可以修改字符串变量arry里面的值
arry[0]='r';//字符串arry的第一个值进行修改
printf("arry里面存放是字符串是%s\n",arry);
//字符串的常量不可以被修改,但是可以指向别的地址
a="world";
printf("指针变量a指向了一个字符串的地址,地址里面是%s\n",a);
return 0;
}
运行结果:
验证:字符数组和字符串之间的区别
#include<stdio.h>
int main()
{
//字符串和字符数组的区别
char arry[6]={'h','e','l','l','o','w'};
int len;//计算长度的变量
char arry2[]="hellow" ;
len=sizeof(arry)/sizeof(arry[0]);
printf("字符数组arry的长度是%d\n",len);
len=sizeof(arry2)/sizeof(arry2[0]);
printf("字符串arry2的长度是%d\n",len);
puts(arry);
return 0;
}
运行结果:字符串后面是自动加入了一个’\0’的字符,所以字符串和字符数组内容是一样长度不一样的原因,
strlen函数的使用
strlen函数是计算出字符串中有效字符的长度,有效字符不包括’\0’的字符
代码:
#include<stdio.h>
#include<string.h>//使用strlen函数需要包含的头文件
void test()
{
}
int main()
{
char arry[]="hellow,world";
void (*p)();
p=test;
//使用strlen函数和sizeof关键字计算字符串长度的区别
printf("arry通过sizeof关键字计算出的长度是%d\n",sizeof(arry));
printf("arry通过strlen函数计算出的长度是%d\n",strlen(arry));
// sizeof关键字还可以这样使用,计算出不同类型变量占用的字节数
printf("sizeof int 的长度是%d\n",sizeof(int)) ;
printf("sizeof char*的长度是%d\n",sizeof(char*));
printf("sizeof int*的长度是%d\n",sizeof(int*));
printf("sizeof char 的长度是%d\n",sizeof(char));
printf("sizeof test 的长度是%d\n",sizeof(p));
return 0;
}
运行结果:
sizeof是计算出字符串中一共是有多少字符,其中包含了’\0’,hellow,world一共是12个字符,加上’\0’正好是13个
strlen是计算出字符串当中有效字符,不包括’\0’的字符所以得出结果是12
malloc动态开辟空间
malloc是可以申请空间的函数,
(类型*)malloc(字节数);
例子:(char *)malloc(1);//这个就是开辟了一个字节数大小内存,
返回一个char *的地址
realloc是可以对内存进行扩容的函数,
realloc(地址,扩容大小)
p=realloc(p,12);//这个就是对地址p扩容12个字节数的大小,返回地址
free是悬挂指针,野指针的一种,当开辟空间不用时可以进行悬挂
free( p );//这个就是把指针p进行悬挂
strcpy函数时可以把字符串复制一份给到一个地址
strcpy(p,arry);//把arry里面的字符串复制一份给到p所处的地址里
代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main() {
//malloc,free,strcpy,realloc的使用
char *p = NULL; //一个空指针
p = (char*)malloc(1); //开辟一个字节数的空间
*p = 'c'; //把字符c放入新开辟的空间里面
printf("%c", *p);
free(p);//悬挂指针p
p = NULL; //重新指向空
p = (char*)malloc(12); //重新开辟一个12个字节的内存
if (p == NULL) {
printf("开辟空间失败\n");
exit(-1);
}
memset(p, '\0', 12); //把新开辟的空间进行初始化
char arry[30];
int len;
int newlen;//扩容大小
printf("请输入字符串\n");
scanf("%s", arry);
len = strlen(arry); //计算出输入字符串的有效字符的数量
if (len > 12) {
printf("内存进行扩容\n");
newlen = len - 12 + 1; //算出扩容大小
p = realloc(p, newlen); //让指针重新指向扩容后的地址
strcpy(p, arry); //把arry里面的字符串给到扩容后的内存
puts(p);
} else {
printf("内存不需要扩容\n");
strcpy(p, arry);
puts(p);
}
return 0;
}
运行结果:
strcpy和strncpy函数
参考文章:4.strcpy和5.strncpy
自己定义函数实现复制字符串的写法:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void printarry(char*arry) {
puts("请输入字符串");
scanf("%s", arry);
}
char* mystrncpy(char*arry, char*arry2) {
//判断arry和arry2的地址是否为空
if (arry == NULL && arry2 == NULL) {
return NULL;//直接返回一个空地址
}
char *des;
des = arry; //保留一个首地址
while (*arry2 != '\0') { //建立循环来判断arry2的字符是否为'\0'
*arry = *arry2; //进行赋值
arry++;//偏移指针arry
arry2++;//偏移指针arry2
}
*arry = '\0'; //当上面循环结束后给arry的尾巴补上一个'\0'
return des;//返回首地址
}
char* mystrncpy2(char*arry, char*arry2) {
//判断地址是否为空
if (arry == NULL && arry2 == NULL) {
return NULL;//返回空指针
}
char* des;
des = arry; //保留一个首地址
//建立循环赋值,直到退出循环
while (*arry2 != '\0') {
*arry++ = *arry2++; //和第一种写法差不多
}
*arry = '\0';
return des;//返回首地址
}
char* mystrncpy3(char*arry, char*arry2) {
//判断地址是否为空
if (arry == NULL && arry2 == NULL) {
return NULL;//返回空地址
}
char* des;
des = arry; //保留arry的首地址
while ((*arry++ = *arry2++) != '\0');
*arry = '\0'; //末尾添加一个'\0'
return des;
}
char *mystrncpy4(char*arry, char*arry2, int a) {
//判断地址是否为空
if (arry == NULL && arry == NULL) {
return NULL;//返回空地址
}
char *des;
des = arry; //保留一个首地址
while (*arry2 != '\0' && a > 0) {
*arry++ = *arry2++;
a--;
}
if (a > 0) { //防止越界
while (a > 0) {
*arry++ = '\0';
a--;
}
return des;//返回首地址
}
*arry = '\0';
return des;
}
int main() {
//strcpy函数和自己定义函数实现其功能的写法
char arry[100] = {'\0'};
char arry2[100] = {'\0'}; //定义两个字符数组并且初始化为'\0'
//1.建立一个可以输入字符串的函数
printarry(arry2);
//2三种写法
strncpy(arry, arry2,7); //把arry2里面的7个字符复制给到arry
puts(arry);
//2.1模仿strncpy函数的写法
mystrncpy(arry, arry2);
puts("写法1");
puts(arry);//打印arry
//2.2第二种写法,和第一种写法差不多
puts("写法2");
mystrncpy2(arry, arry2);
puts(arry);
//2.3第三种写法,有些不适应
puts("写法3");
mystrncpy3(arry, arry2);
puts(arry);
//3.指定复制字符串个数的函数,基于2.2函数的改写
int a;//控制字符串个数的变量
puts("指定个数的写法");
printf("请输入复制arry2字符串字符的个数\n");
scanf("%d", &a);
mystrncpy4(arry, arry2, a);
puts(arry);
return 0;
}
运行结果:
字符串的拼接函数strcat
参考文章:6.strcat和7.strncat
代码:自己手写实现字符串拼接函数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
void printarry(char*arry, char*arry2) {
puts("请对数组arry进行输入字符串");
scanf("%s", arry);
puts("请对数组arry2进行输入字符串");
scanf("%s", arry2);
}
char* mystrcat(char*arry, char*arry2) {
//保留数组的首地址
char*des = arry;
while (*arry != '\0') {
arry++;//指针偏移直到退出循环
}
//偏移到了arry尾巴,把arry2里面的字符从arry的尾巴部分开始赋值
while ((*arry++ = *arry2++) != '\0'); //指针偏移直到*arry2='\0'
*arry = '\0'; //补充一个'\0'
return des;//返回首地址
}
char *mystrcat2(char* arry, char*arry2) {
char*des = arry; //保留一个地址
//直接使用strcpy的方式,先让arry指针偏移到尾部,把arry2里面字符赋值到尾巴部分
strcpy(arry + strlen(arry), arry2);
return des;//返回首地址
}
char* mystrcat3(char*arry, char*arry2) {
char*des = arry; //保留一个地址
//和方法1的函数类似,只不过是用for循环来实现你
for (; *arry != '\0'; arry++);
while ((*arry++ = *arry2++) != '\0');
*arry = '\0';
return des;
}
int main() {
//字符串拼接函数strcat和手写函数strncat
char arry[100];
char arry2[100];
char*p = NULL; //一个空指针
//1.建立一个对数组arry和数组arry2进行输入字符串的函数
printarry(arry, arry2);
//2.使用strcat函数对字符串进行拼接
puts("第一次拼接");
p = strcat(arry, arry2);
puts(p);
//3三种自己定义函数实现字符串拼接
//3.1方法1
puts("第二次拼接");
p = mystrcat(arry, arry2);
puts(p);
//3.2方法2
puts("第三次拼接");
p = mystrcat2(arry, arry2);
puts(p);
//3.3方法3
puts("第四次拼接");
p = mystrcat3(arry, arry2);
puts(p);
return 0;
}
运行结果:
字符串之间的比较函数:strcmp
根据上面文章里面代码进行验证
代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void printarry(char*arry,char*arry2)
{
puts("请输入arry里面的字符串");
scanf("%s",arry);
puts("请输入arry2里面的字符串");
scanf("%s",arry2);
}
int main()
{
//字符串比较函数,strcmp
char arry[100];
char arry2[100];
int ret=0;//定义一个变量初始化为0
int a=3;//控制循环的变量是循环进行3次
//1.建立一个字符串输入的函数
while(a>0){
printarry(arry,arry2);
ret=strcmp(arry,arry2);
printf("ret=%d\n",ret);
a--;
}
return 0;
}
运行结果:仔细看
自己定义函数实现字符串比较
代码:注意看注释
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void printarry(char*arry, char*arry2) {
puts("请输入arry里面的字符串");
scanf("%s", arry);
puts("请输入arry2里面的字符串");
scanf("%s", arry2);
}
int mystrcmp(char*arry, char*arry2) {
int ret = 0; //最终返回值
//保留两个指针的首地址
char* str1 = arry;
char* str2 = arry2;
//定义两个变量存放字符串arry和arry2里面字符相加的值
int arryadd = 0;
int arry2add = 0; //值初始化为0
//1.判断两个字符串是否相等
while (*arry && *arry2 && (*arry == *arry2)) { //对arry和arry2进行取值然后判断是否相等
arry++;
arry2++;//指针偏移
}
//循环正常退出,说明两个字符串相等直接返回0,下面的if不会执行
//如果上面循环提前退出,说明两个字符串不相等,再加一层判断
if (*arry || *arry2) { //*arry不等于'\0'或者*arry2不等于'\0',满足一个条件就进行判断
//arry指针和arry2回到首个地址
arry = str1;
arry2 = str2;
while (*arry) { //条件满足*arry='\0'就会退出循环
arryadd += *arry; //计算出字符串arry里面的值
arry++; //指针偏移
}
while (*arry2) { //条件满足*arry2='\0'就会退出循环
arry2add += *arry2; //计算出arry2字符串里面字符相加的值
arry2++;//指针偏移
}
}
ret = arryadd - arry2add;
//判断arry字符串字符相加的值减去arry2里面字符串相加值,是正数还是负数
if (ret > 0) {
ret = 1; //整数大于0,返回值就是1
}
if (ret < 0) {
ret = -1; //负数小于0,返回值就是-1
}
return ret;
}
int main() {
//字符串比较函数,strcmp
char arry[100];
char arry2[100];
int ret = 0; //定义一个变量初始化为0
int a = 3; //控制循环的变量是循环进行3次
//1.建立一个字符串输入的函数
while (a > 0) {
printarry(arry, arry2);//字符串输入函数
ret = mystrcmp(arry, arry2);
printf("ret=%d\n", ret);
if (ret == 1) {
puts("arry字符串比较大");
} else if (ret == 0) {
puts("两个字符串相等");
} else {
puts("返回值是负数,arry2里面字符串比较大");
}
a--;
}
return 0;
}
运行结果: