今天主要讲了两点,一是字符数组的定义,二是字符数组的拷贝,也是重点。
一、字符数组的定义
char arr[5] = {'a','b','c','d','e'};char brr[5] = {'a','b','c'}; //聚合类型,只初始化部分,剩余部分为0('\0')
char crr[] = {'a','b','c','d','e'};
char drr[5];
以上等同整型数组
char frr[5] = "abc";
char grr[5] = "abcde";//error, 这个定义是错误的,是因为如果字符串后面还有一个'\0',长度一共为6,而定义的数组长度是5。字符串一定以'\0'结尾,这个字符是看不见的。
'\0'是字符串结尾标记,只要是字符串一定有'\0', 只要遇到'\0'就认为字符串结束。
二、如何进行字符串拷贝
首先定义三个字符数组str1,str2,str3。
char str1[100]="abcd";
char str2[100]="xyz";
char str3[100];
现在想把str1数组里面元素复制到str3里面。如何实现呢?
1.str3=str1;这样可以吗?很明显是不行的,因为数组不能整体复制。
2.建立一个函数Mystrcpy1(),如下:
void Mystrcpy1(char *str1,char *str2) //str1=str2
{
int i;
for(i=0;str[i]!='\0';i++) //从首元素开始复制,直到元素为'\0'时停止。
{
str1[i]=str2[i];
}
str1[i]='\0'; //最后再加一个'\0'
}
然后在主函数中调用函数Mystrcpy1(),如下:
int main()
{
char str1[100]="abcd";
char str2[100]="xyz";
char str3[100];
Mystrcpy1(str3,str1); //调用函数
printf("%s\n",str3);//输出,成功复制
return 0;
}
3.由于上节课学过,数组和指针可以互相转化,如下:
*(arr+i)==arr[i] 等价
p[i]==*(p+i) 等价
所以对上一个函数进行换一个形式,结果如下:
void Mystrcpy2(char *str1,char *str2) //str1=str2
{
int i;
for(i=0;*(str1+i)!='\0';i++) //从首元素开始复制,直到元素为'\0'时停止。
{
*(str1+i)=*(str2+i);
}
*(str1+i)='\0'; //最后再加一个'\0'
}
主函数再调用,成功复制。因为跟上面是同理,所以此处和后面主函数省略不写。
4.现在想把函数写得更简单一点,可以这样写:
void Mystrcpy3(char *str1,char *str2)
{
while(*str2 != '\0')
{
*str1 = *str2;
str1++;
str2++;
}
*str1 = '\0';
}
这样就少定义一个变量i,由于改变指针来复制元素,需要用到解引用。
5.把函数写得更简单一点,可以这样写:
void Mystrcpy4(char *str1,char *str2)
{
while(*str2 != '\0')//2
{
*str1++ = *str2++;
}
*str1 = '\0';
}
6.史上最简单的字符数组复制函数如下:
void Mystrcpy5(char *str1,char *str2)
{
while(*str1++ = *str2++) ;
}
这个函数的优点是简单,省内存,缺点是可读性差。但是最优选择还是这个函数。
7.上面的5个函数都是无返回值的,假如需要用到返回值的话,如下:
char * Mystrcpy(char *des,char *src)//des = src
{
char *p = des;
while(*des++ = *src++) ;
return p;
}
在主函数中
Mystrcpy(str4, Mystrcpy(str3,str2));//链式表达,老师说这是一个历史遗留问题,也就是现在基本上不用了,因为看起来不容易理解。
现在这样写:
Mystrcpy(str3,str2);
Mystrcpy(str4,str2);
所以基本上用不到有返回值的函数。
bingo!