原始海报在这里。我没有提到我有一个可行的解决方案来解决这个问题,它并不像我希望的那样强大。请不要难过,我感谢参与此征求意见和回答的每个人。“程序”本质in question
上是variadic
不超过 63 个匿名char *
参数。
它是什么:一个多字符串连接器。它可以处理许多参数,但我建议开发人员不要传递超过 20 个左右的参数。开发人员从不直接调用该过程。相反,一个称为“过程名称”的宏将参数和一个尾随的空指针一起传递,所以我知道什么时候我已经遇到了统计数据收集的结束。
如果函数只接收两个参数,我创建第一个参数的副本并返回该指针。这是字符串文字大小写。但实际上它所做的只是掩盖strdup
如果单个有效参数测试失败,我们继续使用来自包含每个指针realloc
和memcpy
它的 64 条记录的静态数据库中的记录信息strlen
,每次将 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_ */
不要在演职员表中提及我。她很好,花花公子。