【问题标题】:C strings: Random characters appearing in memory after using strcpy and strcatC字符串:使用strcpy和strcat后内存中出现的随机字符
【发布时间】:2014-06-17 19:40:34
【问题描述】:

我正在尝试从文件中删除文件扩展名,以便可以使用子字符串“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 导致了问题?

【问题讨论】:

    标签: c string strcpy strcat


    【解决方案1】:

    这是不正确的:

    char in[5] = "hel.s";
    

    字符串需要六个而不是五个字符(第六个字符用于空终止符)。没有它,字符串是未终止的,导致strlenstrcat 和其他处理终止字符串的函数失败并出现未定义的行为。

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

    char in[] = "hel.s";
    

    此外,您对strncpy 的使用无效:它确实隐式附加空终止符

    如果 source 长于 num,则不会在目标末尾隐式附加空字符。因此,在这种情况下,destination 不应被视为以 null 结尾的 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';
    

    【讨论】:

    • 谢谢,这正是我想要的。在多个层面上提供帮助
    • 如果您需要获取字符串的一部分而不是最后/第一部分,会发生什么情况?然后你需要使用 strncpy(test,input+4,5),如果你想从 char 4 到 char 9 中提取子字符串,我想。
    • @John strncpy 用于固定长度的字符串 - 这不再常见(并且已经有一段时间不常见了)。既然您确定您所采取的部分在字符串的主体内(即不跨越字符串的末尾),您最好使用普通的memcpy
    【解决方案2】:
    char in[5] = "hel.s";
    

    inNOT 字符串:它没有终止 '\0' 字符。不能与字符串函数一起使用。

    strncpy(test, in, strlen(in) - 2); // invalid use of strlen
    

    但是,strncpy() 不是字符串函数(它不需要 src 数组中的终止 NUL;它不一定在 dst 数组中写入终止 NUL)。
    如果它按我的预期工作,那么生成的 test 数组也是 NOT 字符串......并且你不能将它与字符串函数一起使用。

    strcpy(result, strcat(test, "opt.s")); // invalid use of strcat
    

    【讨论】:

    • 不应该省略5 吗?
    • 当然可以。在这种特殊情况下,您可以方便地使用sizeof(in) 来获取数组的大小。
    猜你喜欢
    • 2016-03-14
    • 1970-01-01
    • 2014-08-06
    • 2014-05-28
    • 2014-10-01
    • 1970-01-01
    • 2013-08-23
    • 2018-12-18
    • 1970-01-01
    相关资源
    最近更新 更多