连接没有缓冲区的字符串

时间:2018-03-08 08:05:07

标签: c string strcat

有没有一种方法可以在不预先分配缓冲区的情况下连接字符串?

请考虑以下事项:

int main()
{
    char buf1[] = "world!";
    char buf2[100] = "hello ";
    char * p = "hello ";
    // printf("%s", strcat(p, buf1)); // UB
    printf("%s", strcat(buf2, buf1)); // correct way to use strcat
    return 0;
}

如果我有一个我想要作为字符串前缀的指针,我必须首先将其复制到缓冲区然后strcat()吗?是否有任何功能隐含地这样做?

我想到的唯一选项是strcat()sprintf(),两者都需要缓冲区。

  • 我需要一个需要一个字符串的函数,我希望有一些接近Python str1 + str2语法的东西

3 个答案:

答案 0 :(得分:6)

嗯,它不是标准的C,所以不太便携,但在GNU libc系统上你可以使用asprintf()

int main(void)
{
    const char buf1[] = "world!";
    const char * const p = "hello ";
    char *s;
    if (asprintf(&s, "%s%s", p, buf1) > 0 && s != NULL)
    {
      puts(s);
      free(s);
    }
    return 0;
}

在兼容系统上编译和运行时,会打印

hello world!

答案 1 :(得分:4)

我真的想要使用C,那么你需要使用缓冲区。在C ++或Python中,您可以使用构造函数和运算符来隐藏工作,但在C语言中,您必须自己做事。如果你想让你的代码更容易,你可以创建一个小帮助函数,但要注意内存泄漏和线程:

const char *

只要结果字符串不超过2048个字符,此示例就会起作用;否则结果字符串将被截断。

这当然只是您可以创建的辅助函数的一个示例。

请注意,上面的示例返回了您无法编辑的SetCurrentValue(DistanceTextProperty, Math.Round((To - From).Length, 1).ToString(CultureInfo.InvariantCulture)); 。如果你想进一步编辑字符串,你需要创建一个辅助函数来分配一个缓冲区,但是你需要管理你的内存!

答案 2 :(得分:3)

在运行时执行此操作的最有效方法是调用malloc并为新字符串分配空间,然后将所有内容复制到那里。这很可能是Python在行后面所做的 - 虽然它将有一个字符串类型。

在ADT /类之外执行此操作的缺点是您必须手动进行清理。

然而,使用malloc + copy远比任何* printf快,它是线程安全的,并且可以再次重复使用相同的函数。例如:

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

char* strdog (const char* s1, const char* s2)
{
  size_t size1 = strlen(s1);
  size_t size2 = strlen(s2);
  char* result = malloc(size1 + size2 + 1);
  if(result == NULL) 
  {
    exit(EXIT_FAILURE);
  }

  memcpy(result, s1, size1);
  memcpy(result+size1, s2, size2);
  result[size1 + size2] = '\0';
  return result;
}

inline void cleandog (char* s)
{
  free(s);
}

int main (void)
{
  char s1[] = "hello ";
  char s2[] = "world";

  char* str = strdog(s1, s2);
  puts(str);
  cleandog(str);
}

但请注意,C支持编译时连接。因此,如果您只使用字符串文字,则应该执行以下操作:

#define HELLO "hello "
#define WORLD "world"

...

const char* str = HELLO WORLD;
puts(str);

这当然是它们的优越版本,但仅适用于编译时字符串文字。