我在 C 中有以下程序:
该程序的主要问题是我执行复制操作后,在复制的字母后显示了许多垃圾字符。我知道这是因为目标变量没有正确以空值结尾。但是,如果您仔细检查代码,我正在执行空终止。为什么问题仍然存在?
我在 C 中有以下程序:
该程序的主要问题是我执行复制操作后,在复制的字母后显示了许多垃圾字符。我知道这是因为目标变量没有正确以空值结尾。但是,如果您仔细检查代码,我正在执行空终止。为什么问题仍然存在?
那么,呃,你认为如何strlen()
计算字符串的长度?你认为它需要终止吗?
提示:确实如此。字符数组不是 C 中的字符串,除非它以 0 字符结尾。所做strlen()
的只是计算字符数,直到找到终止符,因此在逻辑中使用它来终止缓冲区以使其成为字符串是一种鸡蛋的情况。
您的问题是您误用了strncpy()
. 这是一件很容易出错的事情,因为从典型(初学者)C 程序员的角度来看,该函数有点疯狂。从名称上看,它根本不会像您期望的那样做。
您可能应该手动执行此操作,只要您确定nob < sizeof destination - 1
:
memcpy(destination, source, nob);
destination[nob] = '\0';
代替:
destination[strlen(destination)] = '\0';
有:
destination[nob] = '\0';
strlen
继续阅读,直到找到'\0'
字符。
马修,当您已经知道要复制的字符串的长度时,您不需要strcpy
or strncpy
(检查每个字符以查找末尾的 \0 )。相反,您应该使用memcpy
然后终止新字符串:
memcpy(destination, source, nob);
destination[nob] = '\0';
memcpy
不检查'\0',所以速度更快。
strncpy
不保证您的destination
字符串在复制后将以空值结尾。我的方法是:
destination[ nob ] = '\0';
经过一些非常小的修改后,这将非常有用:
char destination[18] = {'\0'};
不要使用 strncpy,这很危险。正如我们从您的示例中看到的那样,程序员总是忘记输入正确的参数,结果他们得到了损坏的字符串。这是一个非常常见的错误。
strcpy() 更安全,但也不理想,因为它没有边界检查。如果使用不当,可能会导致缓冲区溢出,这是一个安全问题。这也是一个常见的错误。
复制字符串最快和最安全的方法是通过 memcpy:
memcpy(destination, source, nob);
desitnation[nob] = '\0';
这是失败的,因为strncpy仅复制第一个nob字符并且不附加尾随0。您尝试在目标字符串上添加带有strlen()的尾随 0并没有帮助,因为它会计算字符直到第一个 0,并在该位置放置一个零(这将无效)。
“破解”修复的一种方法是清除目标字符串:
memset( destination, 0, sizeof(destination));
可能有更好的解决方案,包括使您的测试> 17成为> 18。