function(char *a, char *b)
{
char newStr[100];
strncpy(newStr, a, sizeof(newStr)); //Line 1 - copy no more than 100 bytes
strncat(newStr, b, (sizeof(newStr) - strlen(newStr))); //Line 2 - ?
newStr[99] = NULL; //Line 3 - null terminate string
}
字符串
第2行:正确指定100bytes减去strlen的a从复制的内容,以确保我不会复制超过100个字节?
谢谢
2条答案
按热度按时间m4pnthwp1#
这几乎是正确的。首先,NULL终止行:
字符串
是错的
strncat
始终以NULL结束,第三个参数是要写入的最大字节数 NOT(不包括NUL)。假设,如果
strncat
不是以NULL结尾,那么该行的问题是它总是写到数组的最后一个元素,即使实际的字符串可能要短得多。如果a和b分别是“Hello“和“world!,”则最终的数组将是:H| e| L| L| O|、||W| O| R| L| D|!|G|我|B| B| e| R|我|S| H
其中
gibberish
表示数组中这些位置上的先前内容。只有在99处,在大多数这些未初始化的剩余部分之后,才会有NUL。编辑:另外,基思关于
strncpy
的判断是正确的,他的函数部分是正确的,但是第二个函数可能会溢出缓冲区,因为它没有考虑已经存在的字符串,两行加起来可以写199个字符(包括NUL)。另外,我对第三个参数(包括NUL)的理解也是错误的,这给我们留下了(从基思的修改而来):
型
s2j5cfk02#
strncpy()
并不像您所想的那样。strncat()
是strcat()
的“更安全”版本,它允许您指定源数组的大小。strncpy()
* 不是 *strcpy()
对应的“更安全”版本。如果目标数组太大,strncpy()
将用空字符填充它; 99%的情况下这是不必要的,因为您只需要一个'\0'
来标记字符串的结尾。更糟糕的是,如果目标数组太小,strncpy()
将复制尽可能多的字符 *,并使目标保持未终止 。strncpy()
是为早期Unix系统用来储存文件名的一种晦涩的数据结构而设计的。文件名储存在固定长度的14字节缓冲区中,并以空字节填充。如果文件名正好是14个字符长,就不会有空终止符。 这不是一个字符串 *。如果你想要的是这种数据结构,那么
strncpy()
就是你想要的,否则就不要使用它,只要在确认目标足够大之后使用strcpy()
就可以了。下面是如何编写此函数:
字符串
备注:
1.声明函数的返回类型。如果不显式声明,编译器可能会默认为
int
,但这是一种糟糕的风格和过时的语言特性。1.避免使用
strncat()
。1.我使用了
'\0'
,而不是NULL
,来以空值结束字符串。NULL
是一个空 * 指针 * 常量;不要用它来表示空 * 字符 *。这里有一个实质性的低效率:第二个
strncat()
必须从newStr
的开头重新扫描。对于少量的短字符串,这不是什么大问题,但是对于连接到大型目标数组中的大量字符串,这可能会导致严重的速度下降。有一些方法可以解决这个问题,但是它们要么是非标准的(strlcpy()
,strlcat()
)或不方便。编辑:感谢Matthew指出了我的代码中的错误。我 * 认为 * 我已经修复了它们;如果我用新的错误替换了旧的错误,我相信我可以指望有人来敲我的头。
另一种方法是:
型