-1

我需要创建一个 C 函数来连接两个任何类型的数据并返回作为连接结果的字符串。我在下面完成了这个功能,但它不起作用。有人可以帮我吗?

// void pointer does not store value, is just the address of a memory location
char* concatenate(void* varA, int tamA, void* varB, int tamB)
{
    // char is 1 byte
    char* result;
    char* a,b; // helpers
    result = malloc((tamA+tamB)*sizeof(char)); 

    a = varA; // "a" receives the address pointed to by the pointer varA
    b = varB; // "b" receives the address pointed to by the pointer varB
    *result = *result << tamA + *a;
    *result = *result << tamB + *b;
    result = a;    // let the results point to "a"
    return result; // the result is the pointer "a"
}
4

3 回答 3

3

在 C 中,即使您的代码是 C++,这也是您要问的问题,但您不能那样做。

没有办法从裸露的void *如何将其转换为字符串中弄清楚。

您必须添加某种形式的类型信息,例如使用十进制整数等printf()的字符串。%d

我认为这将是一个可行的原型:

char * concat_any(const char *format1, const void *data1,
                  const char *format2, const void *data2);

我不是说“最佳”甚至“合适”,但至少可以实现该原型。format字符串可以是-styleprintf()或其他。

请注意,对于 C,这也是非常不切实际的,因为采用 avoid *意味着您总是需要一个指向数据的指针。如果你想例如连接两个数字,你不能这样做:

char *fortytwo = concat_any("%d", 4, "%d", 2);  /* BROKEN CODE */

因为它传递整数而不是void *,这非常难看。你必须这样做:

const int four = 4, two = 2;
const char *fortytwo = concat_any("%d", &four, "%d", &two);

这显然不是很方便。

因此,使用可变参数会更好,但是您会遇到无法将不同可变参数与不同的非可变参数相关联的问题,如下所示:

char * concat_anyv(const char *format1, ...,
                   const char *format2, ...);   /* BROKEN CODE */

那么,首先有两个格式化字符串,然后信任调用者将两个参数作为可变参数传递怎么样?那将给出:

char * concat_anyv2(const char *format1, const char *format2, ...);

现在我们正在谈论。这可以很简单地实现,甚至:在内部连接两个格式化字符串,并调用vsnprintf()两次:一次计算缓冲区大小,然后分配,然后再次调用。

用法是这样的:

char *fortytwo = concat_anyv2("%d", "%d", 4, 2);

完毕。

于 2013-08-30T13:00:36.527 回答
1

如果我理解正确,您要做的是将数据varAvarB指向的数据一个接一个地复制到一个新的内存缓冲区中,然后将一个字符指针返回到该缓冲区。您可以使用该功能轻松实现此目的memcpy

char *concatenate(void *varA, int tamA, void *varB, int tamB)
{
    char* result = malloc(tamA + tamB); 

    // copy varA to "result"
    memcpy(result, varA, tamA);
    // copy varB to "result" after varA
    memcpy(result+tamA, varB, tamB);

    return result;
}

请注意,任何数据varAvarB保存它都按原样使用,而不是转换为人类可读的表示。

于 2013-08-30T13:58:12.870 回答
0

我在 C 中使用了两个小字符串函数。第一个是其他人使用printf模型进行的改编,正如其他人提到的那样,您必须知道数据类型是什么:

char* str(const char *fmt, ...)
{
  int size;
  char *buff;
  va_list argp1;
  va_list argp2;

  va_start(argp1, fmt);
  va_copy(argp2, argp1);

  //calling vsnprintf with a NULL buffer simply returns what would
  //be the size of the resulting string but does not include space for nul byte
  size = vsnprintf(NULL, 0, fmt, argp1) + 1;  
  va_end(argp1);

  //now actually allocate a buffer of the correct size and then fill it
  buff = calloc(1,size);
  assert(buff != NULL);
  vsnprintf(buff, size, fmt, argp2);
  va_end(argp2);

  return buff;
}

有了这个,我可以concat做一个简单的

char *d = str("%s%s%d", s1, s2, 25);

我只需要记住释放返回的字符串,因为它分配了内存。

我有第二个例程,用于简单的字符串连接,我可以嵌套在其他调用中,因为它为我做内部清理:

typedef enum {FREE_NONE, FREE_ONE, FREE_TWO, FREE_BOTH} CONCAT_FREE_FLAG;
char *concat(char *one, char *two, CONCAT_FREE_FLAG f)
{
  int size = strlen(one) + strlen(two) + 1;
  char *buff = calloc(1,size);
  assert(buff != NULL);
  strcpy(buff, one);
  strcat(buff, two);

  if( f == FREE_ONE || f == FREE_BOTH)
    free(one);
  if( f == FREE_TWO || f == FREE_BOTH)
    free(two);
  return buff;
}

这使我可以执行以下操作:

 char *s = concat(
              concat("Static ",str("%dx%d", x, y), FREE_TWO),
              "Other Static", FREE_ONE);

我有这个的原因实际上是语法糖,所以我可以传递动态分配的字符串,获取一个新的动态分配的字符串,但不必担心清理输入字符串。

于 2013-08-30T16:03:10.523 回答