我需要创建一个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"
}
答案 0 :(得分:3)
在C中,即使您的代码是C ++,这也是您所要求的,但您不能这样做。
没有办法从裸void *
中找出如何将其转换为字符串。
您必须使用以下方式添加某些表单的类型信息,例如printf()
的字符串%d
表示十进制整数等等。
我认为这是一个可行的原型:
char * concat_any(const char *format1, const void *data1,
const char *format2, const void *data2);
我不是说“最佳”甚至“合适”,但至少可以实现该原型。 format
字符串可以是printf()
- 样式,或其他任何内容。
请注意,对于C,这也是非常不切实际,因为取void *
意味着您需要一个指向数据的指针。如果你想要,例如连接两个数字,你不能这样做:
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);
这显然不太方便。
所以,使用varargs会更好,但是你会遇到无法将不同的varargs与不同的非变量参数关联的问题,如下所示:
char * concat_anyv(const char *format1, ...,
const char *format2, ...); /* BROKEN CODE */
那么,如何首先拥有两个格式化字符串,然后信任调用者将这两个参数作为varargs传递?这会给:
char * concat_anyv2(const char *format1, const char *format2, ...);
现在我们正在谈论。这可以简单地实现,甚至:在内部连接两个格式化字符串,并调用vsnprintf()
两次:一次计算缓冲区大小,然后分配,并再次调用它。
用法就是这样:
char *fortytwo = concat_anyv2("%d", "%d", 4, 2);
完成。
答案 1 :(得分:1)
如果我理解正确,您要做的是将varA
和varB
指向的数据一个接一个地复制到新的内存缓冲区中,并返回一个char指针这个缓冲区。您可以使用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;
}
请注意,无论数据varA
和varB
是否保留它都会按原样使用,而不会转换为人类可读的表示形式。
答案 2 :(得分: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);
我有这个的原因是语法糖,所以我可以传递动态分配的字符串,获得一个新的动态分配的字符串,但不必担心清理输入字符串。