连接字符串 - 你如何以干净的方式做到这一点?

时间:2011-09-09 20:53:49

标签: c string

我正在为PHP编写C扩展,我必须根据一些子字符串构建一个字符串。目前它看起来像这样:

spprintf(
    &bucket_list_url, 
    strlen(host) + 1 + sizeof(port) + 1 + strlen(prefix) +strlen("?buckets=true"),
    "%s:%d/%s?buckets=true",
    host, 
    port,
    prefix
);

它有效,但看起来很可怕,可能难以维持。是否有更清晰的方法将这些字符串安全地连接在一起?

我是C的初学者,你可能已经注意到了,所以到目前为止我还没有想出任何更清洁的解决方案。

3 个答案:

答案 0 :(得分:3)

如果您正在使用GNU C运行时(glibc),则可以使用asprintf(3)函数将字符串格式化为动态分配的缓冲区。这样,您就不必担心有足够大的缓冲区了。例如:

// Error checking omitted for expository purposes
char *bucket_list_url;
asprintf(&bucket_list_url, "%s:%d/%s?buckets=true", host, port, prefix);
...  // do stuff
free(bucket_list_url);

如果你没有使用glibc,你仍然可以使用snprintf(3),但你必须猜测缓冲区的长度。如果您猜错了,则必须分配更大的缓冲区并重试。

答案 1 :(得分:0)

我认为你的意思是使用snprintf:

char bucket_list_url[1024];

snprintf(bucket_list_url, sizeof(bucket_list_url), "%s:%d/%s?buckets=true", host, port, prefix);

snprintf的第二个参数是第一个参数的长度,以字节为单位,而不是函数调用后期望得到的字符串的长度。

答案 2 :(得分:0)

这是我写的一段时间的小片段。这可能有点傻,但也许这就是你要找的东西。注意:它不是最有效的,因为它有两个vsnprintf s。第一个是确定缓冲区的长度。


char * new_string_from_format(const char * fmt, ...) {
  int size;
  char * string_buffer;

  assert(fmt != NULL);
  assert(strlen(fmt) > 0);

  //  first determine the length the buffer should be
  va_list args;
  va_start(args, fmt);
  size = vsnprintf(NULL, 0, fmt, args) + 1;
  va_end(args);
  assert(size > 0);


  string_buffer = new char[size];
  va_start(args, fmt);
  vsnprintf(string_buffer, size, fmt, args);
  va_end(args);

  return string_buffer;
}


它可能类似于glibc的asprintf,(但不需要glibc。)