当我编译并运行我的程序时,似乎一切正常,除了我得到“运行时检查失败#2”错误之外的任务。顺便说一句,这是我的hw任务,这是我第一次尝试使用任何cstring函数,所以我确定这是我出错的地方。基本上我将2个字符串附加在一起,我几乎100%确定它与我的结果参数溢出有关。只是不知道如何解决它。
#include <iostream>
#include <cstring>
using namespace std;
void concat(const char a[ ], const char b[ ], char result[ ], int result_maxlength);
int main()
{
char a[] = "Woozle";
char b[] = "Heffalump";
char c[5];
char d[10];
char e[20];
concat(a, b, c, 5);
concat(a, b, d, 10);
concat(a, b, e, 20);
cout << c << "\n";
cout << d << "\n";
cout << e << "\n";
return 0;
}
void concat(const char a[ ], const char b[ ], char result[ ], int result_maxlength)
{
strncpy (result,a, result_maxlength);
strncat (result, b, result_maxlength);
result[result_maxlength-1] = '\0';
}
答案 0 :(得分:1)
strncat
非常没用,因为num
参数不是目标的总大小,而是要复制的字节数。
答案 1 :(得分:1)
到目前为止,有几个问题指出了这个代码。一个非常微妙的,似乎很少谈论的是:根据POSIX规范,如果移动的非空字符数达到指定的限制,strncpy
的行为将不会在字符串上设置空终止符(然后')。但是,它会尾部填充空值以达到'n'。因此:
char ar[3];
strncpy(ar, "food", sizeof(ar)/sizeof(ar[0]));
这将以(0)='f',a(1)='o'和ar(2)='o'结束。 不会附加空终止符。忽略最后一个字符由于这个原因,人们对于调用这个运行时库函数是如此负面。考虑到这一点很重要。因此,您经常会看到这样的代码。
char ar[3];
strncpy(ar, "food", sizeof(ar)/sizeof(ar[0])-1);
ar[sizeof(ar)/sizeof(ar[0])-1] = 0;
这可能会得到你真正想要的东西,即ar =“fo”。充足的空间情况扭转了这一局面。如果你有一个有足够空间的缓冲区,'n'将使用空值进行尾部填充,直到达到'n',如果副本的源字符串在到达'n'之前到达它自己的终结符。因此:
char ar[30];
strncpy(ar, "food", sizeof(ar)/sizeof(ar[0])-1);
ar[sizeof(ar)/sizeof(ar[0])-1] = 0;
在'd'之后将导致ar =“food”,其中有26个零字符。保持人们的脚趾,不那么明显的memset-to-zero调用:
char ar[30];
strncpy(ar, "", sizeof(ar)/sizeof(ar[0]));
是的,这是错的,我知道。
所有这一切都说明了strncat()的行为与您的代码似乎反映出来的情况不同也就不足为奇了。例如,最后一个参数未指定要在目标中限制的字符数。相反,它描述了从源复制限制的字符数。换句话说,当你继续使用新的字符串时,尾部空间限制器应该不断变短。当然,要知道多少涉及跟踪每个步骤复制的字符,并且正如有人指出的那样,这使得strncat在许多情况下无边界无用,提供了比实用程序更多的混乱。
作为参考,可以在此处strncpy和strncat查看具有已定义行为的精确定义。在继续做作业之前,我强烈建议您仔细阅读这两本书。