C字符串:使用strcpy和strcat后出现在内存中的随机字符

C字符串:使用strcpy和strcat后出现在内存中的随机字符,c,string,strcpy,strcat,C,String,Strcpy,Strcat,我正在尝试从文件中删除文件扩展名,以便使用子字符串“opt.s”重命名该文件。我使用以下简单的示例程序执行此操作: char in[5] = "hel.s"; char test[40]; strncpy(test,in,strlen(in)-2); char result[50]; strcpy(result,strcat(test,"opt.s")); printf(" %s ",result); 我得到的输出不同,但通常如下所示: helþ(opt.s 所以基本上随机数

我正在尝试从文件中删除文件扩展名,以便使用子字符串“opt.s”重命名该文件。我使用以下简单的示例程序执行此操作:

 char in[5] = "hel.s";
 char test[40];
 strncpy(test,in,strlen(in)-2);
 char result[50];
 strcpy(result,strcat(test,"opt.s"));
 printf(" %s ",result);
我得到的输出不同,但通常如下所示:

 helþ(opt.s 
所以基本上随机数出现在“hel”和“opt.s”之间。这是什么原因?我是否使用strcpy错误,或者是strcat导致了问题

char in[5] = "hel.s";
中的
不是字符串:它没有终止的
'\0'
字符。不能将中与字符串函数一起使用

strncpy(test, in, strlen(in) - 2); // invalid use of strlen
strcpy(result, strcat(test, "opt.s")); // invalid use of strcat
但是,
strncpy()
不是字符串函数(它不需要src数组中的终止NUL;它不一定在dst数组中写入终止NUL)。
如果它按照我认为您期望的那样工作,那么生成的
test
数组也是而不是字符串。。。并且不能将其与字符串函数一起使用

strncpy(test, in, strlen(in) - 2); // invalid use of strlen
strcpy(result, strcat(test, "opt.s")); // invalid use of strcat
中的
不是字符串:它没有终止的
'\0'
字符。不能将中与字符串函数一起使用

strncpy(test, in, strlen(in) - 2); // invalid use of strlen
strcpy(result, strcat(test, "opt.s")); // invalid use of strcat
但是,
strncpy()
不是字符串函数(它不需要src数组中的终止NUL;它不一定在dst数组中写入终止NUL)。
如果它按照我认为您期望的那样工作,那么生成的
test
数组也是而不是字符串。。。并且不能将其与字符串函数一起使用

strncpy(test, in, strlen(in) - 2); // invalid use of strlen
strcpy(result, strcat(test, "opt.s")); // invalid use of strcat
这是不正确的:

char in[5] = "hel.s";
字符串包含六个字符,而不是五个字符(第六个字符表示空终止符)。如果没有它,字符串将无法终止,从而导致
strlen
strcat
,以及其他在终止字符串上工作的函数以未定义的行为失败

要修复此问题,请从声明中删除5,并让编译器为您决定长度:

char in[] = "hel.s";
此外,您使用的
strncpy
是无效的:它不会隐式附加空终止符

如果源长度大于num,则不会在目标的末尾隐式追加空字符。因此,在这种情况下,目标不应被视为以空结尾的C字符串(这样读取它会溢出)

这条线

strncpy(test,in,strlen(in)-2);
始终生成未终止的字符串,导致后续调用strcat失败。要解决此问题,您需要自己添加终止符:

size_t len = strlen(in)-2;
memcpy(test, in, len); // Do not use strncpy
test[len] = '\0';
这是不正确的:

char in[5] = "hel.s";
字符串包含六个字符,而不是五个字符(第六个字符表示空终止符)。如果没有它,字符串将无法终止,从而导致
strlen
strcat
,以及其他在终止字符串上工作的函数以未定义的行为失败

要修复此问题,请从声明中删除5,并让编译器为您决定长度:

char in[] = "hel.s";
此外,您使用的
strncpy
是无效的:它不会隐式附加空终止符

如果源长度大于num,则不会在目标的末尾隐式追加空字符。因此,在这种情况下,目标不应被视为以空结尾的C字符串(这样读取它会溢出)

这条线

strncpy(test,in,strlen(in)-2);
始终生成未终止的字符串,导致后续调用strcat失败。要解决此问题,您需要自己添加终止符:

size_t len = strlen(in)-2;
memcpy(test, in, len); // Do not use strncpy
test[len] = '\0';

5
不应该只是一个简单的例子吗?当然可以。在这种特殊情况下,您可以方便地使用
sizeof(In)
来获取数组的大小。不应该只使用
5
吗?当然可以。在这种情况下,您可以方便地使用
sizeof(In)
来获得数组的大小。谢谢,这正是我要找的。在多个级别上提供帮助当您需要获取字符串的一部分而不是最后/第一部分时会发生什么情况?如果您想从char 4提取子字符串直到char 9,那么您需要使用strncpy(test,input+4,5),我想。@John
strncpy
是用于固定长度的字符串的,它不再常见了(并且已经有一段时间不常见了)。由于您确信您要使用的部件位于字符串主体内(即,不穿过字符串的末端),因此最好使用plain
memcpy
。谢谢,这正是我想要的。在多个级别上提供帮助当您需要获取字符串的一部分而不是最后/第一部分时会发生什么情况?如果您想从char 4提取子字符串直到char 9,那么您需要使用strncpy(test,input+4,5),我想。@John
strncpy
是用于固定长度的字符串的,它不再常见了(并且已经有一段时间不常见了)。由于您确信所取的部分位于字符串主体内(即不穿过字符串末端),因此最好使用纯
memcpy