2011-09-03 112 views
1

我有这个PHP代码,因为性能的原因,希望在C中的等价物。 我已完成R & D Google;我没有得到任何解决方案。C中的PHP vsprintf()等价于什么?

的代码是:

<?php 
    $array = array('tom','jerry','cat'); //variable 
    $tmpl = 'test %s for %s with %s'; //args taken from $array 
    print vsprintf($tmpl,$array)."\n"; 
?> 
+0

C已经有vsprintf在 0xAli

+0

向我们显示您的环境C代码。 –

回答

0

所以,你要一些的printf变体需要从一个阵列打印的参数呢?你可以这样做,在C.

+0

没有预构建(标准)功能,但它绝对可以完成。 –

1

如果你提前知道该字符串,你可以只手动展开数组:

char *array[] = {"tom", "jerry", "cat"}; 
char *tmpl = "test %s for %s with %s"; 
sprintf(out, tmpl, array[0], array[1], array[2]) 

要动态地做到这一点在C:

int my_sprintf(char * restrict out, const char * restrict format, int len, char **args){ 
    switch(len) { 
     case 0: return sprintf(out, format);    
     case 1: return sprintf(out, format, args[0]); 
     case 2: return sprintf(out, format, args[0], args[1]); 
     case 3: return sprintf(out, format, args[0], args[1], args[2]); 
     /* ... add more cases as necessary ... */ 
    } 
    return -1; 
} 

你可能会深入GCC内部,但它不会是便携式的。

PHP脚本生成的相关代码(编译在此之前应运行):

int my_sprintf(char * restrict out, const char * restrict format, int len, char **args){ 
    switch(len) { 
     <?php 
      for($i=0, $out="";$i<=100;++$i) { 
     ?> 
     case <?= $i ?>: return sprintf(out, format <?= $out ?>); 
     <?php 
      $out .= ", args[$i]"; 
      } 
     ?> 
    } 
} 
+0

数组长度实际上随着tmpl的变化而变化,我可以使用va_list函数与上面的数组 – moorthi

+0

@moorthi你可以通过为每个长度创建一组函数(或宏)来破解一些东西在一起。我将编辑我的回复,告诉你如何去做 –

+0

我的论点大约在30-70,所以有动态的我可以生成c代码的sprintf,并在运行时将它包含在主代码中 – moorthi

0

没有直接类似物的vsprintf() C中的PHP变种有一个功能vsprintf() - 这通常不应该使用;代替使用vsnprintf()更安全。但是这并不需要一组字符指针,printf()也没有其他任何变体。

您有几个选项。 @Foo Bah概述的是这样做的一种方式;复杂的因素是你必须写出30-70个变体,如果没有其他的话,这很丑陋。

我想在这种情况下,我会写一个变体来分析格式字符串并处理数组。它会将格式的文字组件复制到结果中,然后在请求时调用snprintf()来从数组格式化(复制)元素。我注意到像%*.*s这样的格式不是上下文中的选项;没有办法获得通过的整数值(或者,没有清除的方式这样做)。并且没有简单的方法来支持交错格式说明符,如%f%d。在界面设计中有一个有趣的问题是'你是否会传递数组的长度并验证长度和格式,还是让格式决定数组的长度?

int vsnprintfas(char *buffer, size_t buflen, const char *format, 
       size_t arrlen, char * const * const array); 

或者:

int vsnprintfas(char *buffer, size_t buflen, const char *format, 
       char * const * const array); 

由于有犯错的余地,我会使用双界面检查 - 列出的第一个。当然,建议的as后缀是字符串数组。我很乐意在array上就const限定符的数量和位置进行协商,但从概念上讲,它是一组功能根本不会改变的指针。

1

如果您知道您传递了多少个参数,则只需拨打snprintf(3)即可。如果您不知道,唯一的其他选择是使用可变参数功能并致电vsnprintf。这通常用于将代码记录为围绕snprintf的薄包装。例如:

void my_log_function(int level, const char *format, ...) 
{ 
    if(level >= MIN_LOGGING_LEVEL) 
    { 
     va_list ap; 
     va_start(ap, format); 

     char buffer[4096]; 
     vsnprintf(buffer, sizeof(buffer), format, ap); 
     // Now write buffer to a file/stdout/the debugger/etc. 

     va_end(ap); 
    } 
} 
... 
my_log_function(LOG_LEVEL_DEBUG, "foo %d bar %s baz", 42, "quux"); 

如果你真的只有参数数组中,有没有办法做你想要使用标准下可以使用库如ffcall什么,但它不能移植到所有系统。例如,这里是你如何能与ffcall做到这一点:

int array_vsnprintf(char *str, size_t size, const char *format, int *args, 
        int numargs) 
{ 
    av_alist alist; // will hold the argument list 
    int retval; // will hold the return value from vsnprintf 
    av_start_int(alist, &vsnprintf, &retval); 

    // Add the arguments to the argument list. This assumes all of the 
    // arguments are ints -- if you have heterogeneous types, you need to keep 
    // track of the type information somewhere and use the appropriate macro 
    // for each argument. 
    av_ptr(str); 
    av_int(size); 
    av_ptr(format); 

    int i; 
    for(i = 0; i < numargs; i++) 
     av_int(alist, args[i]); 

    // Now call vsnprintf 
    av_call(alist); 

    return retval; 
} 
0

我已经试过这种替代做工精细,喜欢拿到ATTRS为“|”分开的字符串和补丁 我可以进一步优化,如果可能的话,任何瓶颈与此。

char *tmpl = "test %s for %s with %s" , buffer[10000], *attrs="Tom|Jerry|Cat"; 

tmplpatch(buffer,tmpl,attrs); 
printf("%s\n",buffer); 

void tmplpatch(char *str, const char *fmt, const char *attrs) { 
    for(;*str=*fmt, *fmt;++fmt,++str) { 
    if(*fmt == '\\') { 
    fmt++;*str=*fmt;continue; 
    } 
    if(!(*fmt == '%' && *(fmt+1)=='s')) continue; // ! %s 
    for(;*attrs!='\0' && *attrs != '|';*str++=*attrs++); 
    ++fmt;++attrs;str--; // skip s, |, junk not '\0' 
    } 
} 
相关问题