c - 当读取 C 中的字符串时,while 循环何时停止?
问题描述
我正在尝试自己实现该strcpy
功能。原件strcpy
是string.h
图书馆的一部分。
char *strcpy(char *dest, const char *src)
{
assert(dest != NULL && src != NULL);
char *temp = dest;
while (*src)
{
*dest = *src;
src++;
dest++;
}
return temp;
}
void strcpyTest()
{
char source[20] = "aaaaaa";
char dest1[20] = "bbbbbbbbb";
char desta[10]="abcd";
puts(dest1); // bbbbbbbbb
strcpy(dest1, source);
puts(dest1); // aaaaaa
strcpy(desta, source);
puts(desta); // aaaaaa
strcpy(desta, dest1);
puts(desta); // aaaaaa
strcpy(dest1, desta);
puts(dest1); // aaaaaa
strcpy(source, desta);
puts(source); // aaaaaa
}
dest
正如你所看到的,即使是第一次调用比函数更长的函数也会src
给出正确的结果,尽管从逻辑上讲,它应该给出
aaaaaabb
而不是aaaaaa
:
char source[20] = "aaaaaa";
char dest1[20] = "bbbbbbbbb";
strcpy(dest1, source);
puts(dest1);
/** aaaaaa **/
为什么我的功能有效?我猜我必须在(*src)` 退出后手动添加/0
字符。*dest*
while
我的意思while (*src)
是,当它到达*src*
字符串的最后一个字符的末尾时退出/0
。因此,我想我必须自己添加这个字符,*dest*
但是代码会以某种方式工作并复制字符串,而无需手动添加/0
.
所以我的问题是它为什么以及如何仍然有效?
当我创建一个新数组时,假设是 10 的
int *arr
orchar *arr
,即char arr[10]
orint arr[10]
并且我只初始化 2 个第一个索引,其余索引内的值会发生什么变化?它们是否会填充零或垃圾值或什么?
也许我的代码有效,因为它充满了零,这就是while
循环停止的原因?
解决方案
对于初学者,您应该选择另一个名称而不是 strcpy。
让我们逐步考虑您的函数的所有调用。
变量source
声明为
char source[20] = "aaaa";
这个声明等价于下面的声明
char source[20] =
{
'a', 'a', 'a', 'a', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
};
因为根据 C 标准,未显式初始化的数组元素被隐式初始化为零。
变量desta
声明为
char desta[10]="abcd";
这个声明等价于下面的声明
char desta[10]= { 'a', 'b', 'c', 'd', '\0', '\0', '\0', '\0', '\0', '\0' };
所以第一次打电话
strcpy(desta, source);
只需将四个字符替换"abcd"
为四个字符"aaaa"
。结果数组desta
将包含一个字符串,因为下界终止零被覆盖。
在这个电话之后
strcpy(desta, dest1);
数组desta
将包含字符串,因为此调用不会覆盖"bbbbbbbbb"
数组的最后一个零字符。desta
这个电话
strcpy(dest1, desta);
实际上并不是被改变的数组dest1
。
在这次通话中
strcpy(source, desta);
由于数组的所有零字符source
都没有被覆盖,因此数组将包含一个字符串。
如果你一开始打电话,你可能会得到一个不可预知的结果
strcpy(desta, dest1);
接着
strcpy(desta, source);
因为您的函数不会将终止零附加到目标数组。
这是一个演示程序。
#include <stdio.h>
#include <assert.h>
char * my_strcpy(char *dest, const char *src)
{
assert(dest != NULL && src != NULL);
char *temp = dest;
while (*src)
{
*dest = *src;
src++;
dest++;
}
return temp;
}
int main(void)
{
char source[20] = "aaaaaa";
char dest1[20] = "bbbbbbbbb";
char desta[10]="abcd";
my_strcpy(desta, dest1);
my_strcpy(desta, source);
puts( desta );
return 0;
}
程序输出为
aaaaaabbb
那就是desta
包含字符串"aaaaaabbb"
而不是字符串aaaaaa
。
更新后的功能可能如下所示
char * strcpy(char *dest, const char *src)
{
assert(dest != NULL && src != NULL);
char *temp = dest;
while ( ( *dest++ = *src++ ) );
return temp;
}
推荐阅读
- javascript - 用对象内部的项目替换javascript数组
- reactjs - Express cors 不允许凭据
- python - 如何在选择图像中的轮廓时避免对图像(条形)进行分组?
- node.js - 仅使用 DynamoDB 中的分区键进行查询
- sql - 将数据从一个表复制到另一个表 - 忽略重复 Postgresql
- batch-file - 如何替换父批处理文件?
- html - 如何为响应式网页设计设置最小宽度,然后让设备缩放以适应该点以下?
- postgresql - postresql group by 查询耗时太长
- angular - “块”参数必须是字符串或缓冲区类型之一。接收到的类型对象
- c# - 获取从社交登录提供商返回的流量,以在我的 .net core 2.2 Web 应用程序上创建本地帐户