我正在为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的初学者,你可能已经注意到了,所以到目前为止我还没有想出任何更清洁的解决方案。
答案 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。)