原始海报在这里。我没有提到我有一个可行的解决方案来解决这个问题,它并不像我希望的那样强大。请不要难过,我感谢参与此征求意见和回答的每个人。 '过程'in question本质上是variadic,并且期望不超过63个匿名char *参数。
它是什么:一个多字符串连接器。它可以处理许多参数,但我建议开发人员不要传递超过 20 个左右的参数。开发人员从不直接调用该过程。相反,一个称为“过程名称”的宏将参数和一个尾随的空指针一起传递,所以我知道什么时候统计数据收集结束了。
如果函数只接收两个参数,我会创建第一个参数的副本并返回该指针。这是字符串文字大小写。但实际上它所做的只是掩盖strdup
如果单个有效参数测试失败,我们继续进行realloc 和memcpy,使用来自包含每个指针及其strlen 的64 条记录的静态数据库中的记录信息,每次将memcopy 的大小添加到二级指针 (memcpy destination) 以 realloc 返回值的副本开始。
我编写了第二个宏,附加了 'd' 表示第一个参数不是动态的,因此需要动态参数,并且该宏使用以下代码将动态参数注入到实际过程中作为第一个参数调用:
strdup("")
这是一个可以重新分配的有效内存块。它的strlen 返回 0,所以当循环将它的大小添加到记录中时,它不会产生任何影响。空终止符将被memcpy 覆盖。我应该说它工作得非常好。但是,仅在过去几周内才刚接触 C,我不明白您不能“傻瓜证明”这些东西。我想人们会按照指示或在 DLL 地狱中结束。
代码在没有所有这些额外的恶作剧和口哨声的情况下运行良好,但没有办法回报单个内存块,由于所有动态指针 mgmt,该过程在循环处理中丢失。涉及。因此,第一个参数必须始终是动态的。我读到有人建议在函数中使用保存指针的 c-static 变量,但是您不能使用该过程在其他函数中执行其他操作,例如在决定编译的递归下降解析器中需要字符串。
如果您想查看代码,请询问!
编码愉快!
mkstr.cpp
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
struct mkstr_record {
size_t size;
void *location;
};
// use the mkstr macro (in mkstr.h) to call this procedure.
// The first argument to mkstr MUST BE dynamically allocated. i.e.: by malloc(),
// or strdup(), unless that argument is the sole argument to mkstr. Calling mkstr()
// with a single argument is functionally equivalent to calling strdup() on the same
// address.
char *mkstr_(char *source, ...) {
va_list args;
size_t length = 0, item = 0;
mkstr_record list[64]; /*
maximum of 64 input vectors. this goes beyond reason!
the result of this procedure is a string that CAN be
concatenated by THIS procedure, or further more reallocated!
We could probably count the arguments and initialize properly,
but this function shouldn't be used to concatenate more than 20
vectors per call. Unless you are just "asking for it".
In any case, develop a workaround. Thank yourself later.
*/// Argument Range Will Not Be Validated. Caller Beware!!!
va_start(args, source);
char *thisArg = source;
while (thisArg) {
// don't validate list bounds here.
// an if statement here is too costly for
// for the meager benefit it can provide.
length += list[item].size = strlen(thisArg);
list[item].location = thisArg;
thisArg = va_arg(args, char *);
item++;
}
va_end(args);
if (item == 1) return strdup(source); // single argument: fail-safe
length++; // final zero terminator index.
char *str = (char *) realloc(source, length);
if (!str) return str; // don't care. memory error. check your work.
thisArg = (str + list[0].size);
size_t count = item;
for (item = 1; item < count; item++) {
memcpy(thisArg, list[item].location, list[item].size);
thisArg += list[item].size;
}
*(thisArg) = '\0'; // terminate the string.
return str;
}
mkstr.h
#ifndef MKSTR_H_
#define MKSTR_H_
extern char *mkstr_(char *string, ...);
// This macro ensures that the final argument to "mkstr" is null.
// arguments: const char *, ...
// limitation: 63 variable arguments max.
// stipulation: caller must free returned pointer.
#define mkstr(str, args...) mkstr_(str, ##args, NULL)
#define mkstrd(str, args...) mkstr_(strdup(str), ##args, NULL)
/* calling mkstr with more than 64 arguments should produce a segmentation fault
* this is not a bug. it is intentional operation. The price of saving an in loop
* error check comes at the cost of writing code that looks good and works great.
*
* If you need a babysitter, find a new function [period]
*/
#endif /* MKSTR_H_ */
不要在演职员表中提及我。她很好,花花公子。