конкатенация строк - как вы делаете это чисто? - PullRequest
3 голосов
/ 10 сентября 2011

Я пишу расширение C для PHP, и там мне нужно создать строку на основе некоторых подстрок.В настоящее время это выглядит так:

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 ]

3 голосов
/ 10 сентября 2011

Если вы используете среду выполнения 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), но вам нужно угадать длину буфера.Если вы ошиблись, вам нужно выделить больший буфер и попробовать еще раз.

0 голосов
/ 10 сентября 2011

Вот небольшой фрагмент, который я написал некоторое время назад. Возможно, это немного глупо, но, возможно, это то, что вы ищете. Примечание: это не самый эффективный, потому что он делает два vsnprintf с. Во-первых, определить длину буфера.


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;
}


Это, вероятно, похоже на asprintf glibc, (но не требует glibc.)

0 голосов
/ 10 сентября 2011

Я думаю, что вы собираетесь использовать snprintf:

char bucket_list_url[1024];

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

Второй параметр snprintf - это длина первого параметра в байтах, а не длина строки, которую вы ожидаете получить после вызова функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...