在运行时使用动态参数调用printf 我尝试在C++中为PrimTF编写包装器。当然我找到了va_列表,但不知道它如何适用于我,因为 不会直接调用包装器。稍后我将展示
我解析一个脚本,该脚本包含一个参数数目未知的函数,如在运行时使用动态参数调用printf 我尝试在C++中为PrimTF编写包装器。当然我找到了va_列表,但不知道它如何适用于我,因为 不会直接调用包装器。稍后我将展示,c++,C++,我解析一个脚本,该脚本包含一个参数数目未知的函数,如 ASTNode node(Token(PRINT, PRINT)); consume(PRINT); consume(LPAREN); node.make_child(variable()); // <-- formatstring (node.child[int]) while(current_token._type() != RPAREN) { consume(COMMA); node.make_child(vari
ASTNode node(Token(PRINT, PRINT));
consume(PRINT);
consume(LPAREN);
node.make_child(variable()); // <-- formatstring (node.child[int])
while(current_token._type() != RPAREN) {
consume(COMMA);
node.make_child(variable()); // <-- the values to replace in formatstring (node.child[int++])
i++;
}
consume(RPAREN);
return node;
据我所知,您有一个给定的格式字符串和读取/解析参数 您有两个问题需要处理:处理格式和使用正确的参数类型 printf系列不支持与Qt相反的部分替换,例如,Qt允许QString%1%2。argHello导致QStringHello%2允许链接 因此,您必须手动解析完整格式字符串: 打印常规字符。 遇到%时,检索标志格式,除非它是%%,在这种情况下直接显示% 从标志格式切换到适当的转换,如
// flagFormat would "simply" be %i, %010d, %4.2f or %+.0e
switch (format_type) {
case EFormatType::String: // %s
printf(flagFormat, to_string(args[i]).c_str()); break;
case EFormatType::Int: // %i, %d
printf(flagFormat, to_int(args[i])); break;
case EFormatType::String: // %f, %F, %e, %g, %
printf(flagFormat, to_double(args[i])); break;
// ...
}
++i;
“在我看来,这对你的健康更有利。”贾伯沃基现在应该清楚了。如果没有,没关系。。内森,我不能安装boost@brunoiostreams是一个讨厌的东西,重载位移位运算符是一个坏主意。可能重复的可能重复的请,添加更改的解释这不会执行替换,它只打印出一个表示函数的字符串。在屏幕上,您将看到printfHello%d world%s、param1、param2,。。。我在phpNice起点中寻找类似call_user_func_数组的东西。我想在vsprintf的配合下,我会得到我预期的结果。
// Pseudocode
out("printf(");
out($myformatstring);
int i = 1;
while(i<parameter_count) {
out(parameter[i++]);
out(",");
}
out(")");
// Pseudocode
// I would like to propose a way to solve the problem, added some stuff here
out("printf(");
// you should create format string in accordance with types of parameters
$myformatstring = "" // let suppose myformatstring is of type "string"
// and it has defined operator "+=" (concatenation of strings)
for(int j = 0;j < parametar_count; j++)
{
switch(parametar[j].type ) // suppose that you have type information of param's
{
case 'i': myformatstring += " %d "; break;
case 'f': myformatstring += " %f "; break;
case 's': myformatstring += " %s"; break;
... // you should handle all types you use ...
}
}
$myformatstring += "\\n\","; // terminate format string and write a comma before
// other arguments...
out($myformatstring);
int i = 1;
while(i<parameter_count) {
out(parameter[i++]);
if( i < parameter_count -1 ) // you don't need comma after last parameter
out(",");
}
out(");");
// flagFormat would "simply" be %i, %010d, %4.2f or %+.0e
switch (format_type) {
case EFormatType::String: // %s
printf(flagFormat, to_string(args[i]).c_str()); break;
case EFormatType::Int: // %i, %d
printf(flagFormat, to_int(args[i])); break;
case EFormatType::String: // %f, %F, %e, %g, %
printf(flagFormat, to_double(args[i])); break;
// ...
}
++i;
/*
there is example that explains how to use stdarg for a function
with variable number of parameters
*/
#include <stdio.h>
#include <stdarg.h>
void myfunc(char* fmt, ...);
/* this example folows logic of printf to specify format
%d - integer
%c - single character
%s - string
other character will be copied to output
*/
int main( int argc, char* argv[])
{
myfunc("%s %d ABCD %c", "a string", 4, 'D');
}
void myfunc(char *fmt, ...)
{
va_list ap;
int d;
char c, *s;
va_start(ap, fmt);
while (*fmt)
{
if(*fmt == '%')
{
fmt++;
switch (*fmt) // detect format characters
{
case 's': /* string format character is recognized*/
s = va_arg(ap, char *);
printf("string: %s\n", s); /* this example just print out paramater, you can do what you want */
break;
case 'd': /* integer format character */
d = va_arg(ap, int);
printf("int: %d\n", d);
break;
case 'c': /* char format character*/
c = (char) va_arg(ap, int);
printf("char: %c\n", c);
break;
default:
printf("Just copy non format characters %c\n",*fmt); // copy non format characters after %
}
}
else
printf("just copy '%c'\n", *fmt);
fmt++;
}
va_end(ap);
}