简体   繁体   English

在C中连接字符串的安全方法是什么?

[英]What is a safe way to join strings in C?

I need to construct a path to a file from two strings. 我需要从两个字符串构造一个文件的路径。 I could use this (not tested, though): 我可以使用它(虽然没有经过测试):

/* DON'T USE THIS CODE! */
/* cmp means component */
char *path_cmp1 = "/Users/john/";
char *path_cmp2 = "foo/bar.txt";
unsigned len = strlen(path_cmp1);
char *path = path_cmp1;
for (int i = 0; i < strlen(path_cmp2); i++) {
  path[len + i] = path_cmp2[i];
}

but this could lead to memory corruption I guess. 但这可能会导致内存损坏。 Is there a better way to do this, or is there a function for this in the standard library? 有没有更好的方法来做到这一点,或者标准库中是否有这样的功能?

#include <stdlib.h>
#include <string.h>

char *join(const char* s1, const char* s2)
{
    char* result = malloc(strlen(s1) + strlen(s2) + 1);

    if (result) // thanks @pmg
    {
        strcpy(result, s1);
        strcat(result, s2);
    }

    return result;
}

This is simple enough to be written in place, especially when you have multiple strings to concatenate. 这很简单,可以编写到位,特别是当你有多个字符串连接时。

Note that these functions return their destination argument, so you can write 请注意,这些函数返回其目标参数,因此您可以编写

char* result = malloc(strlen(s1) + strlen(s2) + 1);
assert(result);
strcat(strcpy(result, s1), s2);

but this is less readable. 但这不太可读。

#include <stdio.h> 

char *a = "hello ";
char *b = "goodbye";
char *joined;

asprintf(&joined, "%s%s", a, b)

There are several problems in this code: 1 - calling strlen on the for loop is a bad idea, it will calculate the string length every iteration, so it is better to call it once before the loop and keep the result in a variable. 这段代码有几个问题:1 - 在for循环上调用strlen是个坏主意,它会在每次迭代时计算字符串长度,所以最好在循环之前调用它一次并将结果保存在变量中。

2 - The same strlen problem applies to strlen(path_cmp1) inside the loop, call it before the loop and increments its size. 2 - 相同的strlen问题适用于循环内的strlen(path_cmp1),在循环之前调用它并递增其大小。

In the end, it is better to simple copy both strings and store those on a dynamic allocated string, like: 最后,最好简单地复制两个字符串并将它们存储在动态分配的字符串上,例如:

char *join_strings(const char* s1, const char* s2)
{
    size_t lens1 = strlen(s1);
    size_t lens2 = strlen(s2);

    //plus 1 for \0
    char *result = malloc(lens1 + lens2 + 1);

    if(result)
    {
        memcpy(result, s1, lens1);
        memcpy(result+lens1, s2, lens2+1);
    }

    //do not forget to call free when do not need it anymore
    return result;
}

strcatstrncat

char *path_cmp1 = "/Users/john/";
char *path_cmp2 = "foo/bar.txt";

int firstLength = strlen(path_cmp1);
int secondLength = strlen(path_cmp2);
char *both = malloc(firstLength+secondLength+1);
memcpy(both, path_cmp1, firstLength);
memcpy(both+firstLength, path_cmp2, secondLength+1);
       // this +1 copyes the second string's null-terminator too.

创建一个具有两个输入长度和strcpy / strcat输入的新字符串,并且不要忘记空终止符。

Use strcat . 使用strcat (You are right that your code will lead to memory corruption.) (你的代码会导致内存损坏,你说得对。)

string.h中的strcat怎么样?

path is just a pointer to path_cmp1 and you are trying to access beyond the end of the array. path只是指向path_cmp1的指针,并且您尝试访问超出数组末尾的内容。 Very occasionally this will work, but in the vast majority of cases you will cause memory corruption. 偶尔这会起作用,但在绝大多数情况下,你会导致内存损坏。

As others have pointed out use strcat to concatenate strings. 正如其他人指出的那样,使用strcat来连接字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM