-
strcpy是进行字符串拷贝的函数 - %s - 以字符串的形式打印
- 需要引用的头文件<string.h>
main主函数内的准备代码:
int main()
{
char arr1[20] = "xxxxxxxxxxxx";
char arr2[] = "hello";
strcpy(arr1,arr2);
printf("%s\n", arr1);
return 0;
}
注:strcpy函数内的参数arr1为目标空间的起始地址,arr2为源空间的起始地址.
运行结果:
简要分析:
arr1向arr2进行拷贝时,实际上拷贝的是"hello\0",'\0'是字符串的结束标志,不会打印'\0'后面的内容.
模拟实现strcpy库函数:my_strcpy
- arr1是数组名,也是数组首元素的地址.传递参数时,第一个参数应当写成char* dest.
- arr2也是数组首元素的地址,第二个参数应当写成char* src.
- 数组传参时,为了减少空间资源的浪费,往往不是把整个数组传递过去,而是数组首元素的地址.
- 对变量名进行命名时,应做到"见名知意".
- my_strcpy只进行拷贝,不需要返回值,返回值类型为void.
画图分析:
void my_strcpy(char* dest, char* src)
{
*dest = *src;
dest++;
src++;
}
*dest = *src的作用是把当前解引用操作找到的字符赋值给目标空间数组对应的元素.
赋值完毕后,为使dest/src指向的元素地址更新,应当及时++.
注意:这里不能对*dest/*src++,只有变量才能做运算,*dest为解引用操作找的元素,是常量.
可以发现上面的三条语句应在一定范围内循环执行,循环条件为*src !='\0';
void my_strcpy(char* dest, char* src)
{
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
}
当*src == '\0'时,循环停止,但“hello\0"的最后一个字符'\0'还没有拷贝.
void my_strcpy(char* dest, char* src)
{
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
*dest = *src;
}
运行结果:
解法二:
//void my_strcpy(char* dest, char* src)
//{
// while (*src != '\0')
// {
// *dest++ = *src++;
// }
// *dest = *src;
//}
*dest++ = *src++;这条语句的++为后置++,先使用,再自增.等效于:
①*dest = *src;
②dest++;
③src++;
dest和src谁先自增,谁后自增,不影响程序的运行结果.
解法三:
void my_strcpy(char* dest, char* src)
{
while (*dest++ = *src++)
{
;
}
}
*dest++ = *src++;这条语句放在循环条件中,比较的是字符的ASCII码值,'\0'的ASCII码值为0
①当*src为'\0'时,赋值给*dest,此时*dest == ‘\0’,0为假,循环停止.
②空语句的作用:既拷贝了'\0',又使得循环停止.
接下来让我们一起看看C语言标准库里面怎么实现strcpy函数的吧!!!
char * strcpy ( char * destination, const char * source );
- 从函数声明中可以发现标准库函数实现多了返回值类型char*,以及修饰符const.
- strcpy函数实现把src指向的内容拷贝放进dest指向的空间中.
- 从本质上讲,只希望dest指向的内容被修改,src指向的内容不被修改.
- strcpy这个库函数其实返回的是目标空间的起始地址.
下面进行标准strcpy库函数的模拟实现(主函数部分省略):
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;
assert(src != NULL);
//assert(dest != NULL);
while (*dest++ = *src++)
{
;
}
return ret;
//return dest;//error
}
代码分析:
- assert()函数用来断言.
- 如果不满足某一条件时,断言就会报错.
- 上面的两个断言函数只能执行一个.
- 第一个断言执行,第二个断言就没有机会执行;第二个断言执行,第一个断言就没有机会执行.
- return ret;返回的是目标空间的起始地址.
- 而直接return dest;返回的是目标空间中'0'的地址.
- 代码改进:assert(src != NULL);也可写成assert(src); 0为假,报错.
C语言模拟实现标准strlen库函数
需求分析:
- strlen()函数用来求字符串长度.
- 模拟函数名为my_strlen(); / 需要加返回值类型int和修饰符const.
代码演示:
int main()
{
char arr1[20] = "xxxxxxxxxxx";
char arr2[] = "hello";
printf("%d\n", my_strlen(arr2));
return 0;
}
int my_strlen(const char* str)
{
int count = 0;
assert(str != NULL);
while (*str++ != '\0')
{
count++;
}
return count;
}
- str是一个指针变量,存放的是"hello"中首元素'h'的地址.
- 通过(*)解引用操作,找到对应的元素.
- 这个元素和'\0'进行比较,如果不是'\0',则进入循环.
- *str++为后置++,上述两步执行完毕后,str再自增1,指向该空间中下一个元素的地址.
代码改进:
- 字符串长度不能为负数,故返回值类型不能用int.
- 无符号整型:unsigned--->int signed_t.
size_t my_strlen(const char* str)
{
//assert(str != NULL);
assert(str);
size_t count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}