strcat()用于格式化字符串

时间:2012-12-24 15:19:05

标签: c string concatenation printf

我正在我的程序中逐个构建一个字符串,当我在末尾添加一个简单的字符串时,我正在混合使用strcat(),但是当我添加一个格式化的字符串时,我正在使用sprintf( )例如:

int one = 1;
sprintf(instruction + strlen(instruction), " number %d", one);

是否可以使用strcat()连接格式化字符串或者首选方法是什么?

6 个答案:

答案 0 :(得分:15)

您的解决方案将有效。调用strlen有点尴尬(特别是如果字符串变得很长)。 sprintf()将返回你使用的长度[strcat不会],所以你能做的一件事是这样的:

 char str[MAX_SIZE];
 char *target = str;

 target += sprintf(target, "%s", str_value);
 target += sprintf(target, "somestuff %d", number);
 if (something)
 {
    target += sprintf(target, "%s", str_value2);
 }
 else
 {
    target += sprintf(target, "%08x", num2);
 }

我不确定strcat是否比sprintf()以这种方式使用时效率更高。

编辑:应该写更小的例子......

答案 1 :(得分:9)

不可以,但你可以对这些简单字符串使用sprintf(),并且每次都避免调用strlen()

len = 0;
len += sprintf(buf+len, "%s", str);    
len += sprintf(buf+len, " number %d", one);

答案 2 :(得分:2)

要回答直接问题,请确保可能使用strcat附加格式化字符串。您只需要首先构建格式化的字符串,然后您可以使用strcat附加它:

#include <stdio.h>
#include <string.h>
int main(void) {
    char s[100];
    char s1[20];
    char s2[30];
    int n = 42;
    double x = 22.0/7.0;

    strcpy(s, "n = ");
    sprintf(s1, "%d", n);
    strcat(s, s1);

    strcat(s, ", x = ");
    sprintf(s2, "%.6f", x);
    strcat(s, s2);

    puts(s);
    return 0;
}

输出:

n = 42, x = 3.142857

但这不是一个特别好的方法。

sprintf也可以写到现有字符串的末尾。有关示例,请参阅Mats's answermux's answer。用于保存单个字段的各个数组不是必需的,至少在这种情况下不是。

由于此代码不会跟踪字符串的结尾,因此性能可能很差。 strcat(s1, s2)首先必须扫描s1以查找终止'\0',然后然后s2的内容复制到其中。其他答案通过推进索引或指针来跟踪字符串的结尾而不必重新计算它来避免这种情况。

此外,代码不会努力避免缓冲区溢出。 strncat()可以做到这一点,但它只是截断字符串;它没有告诉你它被截断了。 snprintf()是个不错的选择;如果有足够的空间,它将返回 写入的字符数。如果这超出了您指定的大小,则字符串将被截断。

/* other declarations as above */
size_t count;
count = snprintf(s, sizeof s, "n = %d, x = %.6f", n, x);
if (count > sizeof s) {
    /* the string was truncated */
}

要附加多个字符串(例如,如果某些字符串有条件地或重复地附加),您可以使用其他答案中的方法来跟踪目标字符串的结尾。

是的,可以使用strcat()附加格式化字符串。这不太可能是一个好主意。

答案 3 :(得分:0)

首选方法取决于您愿意使用的内容。 I 将使用GLib或GLib的GString函数中的g_strdup_print数据结构,而不是执行所有这些手动(和潜在危险的)字符串操作。对于您的问题,GString提供了g_string_append_printf功能。

答案 4 :(得分:0)

根据需要编写自己的包装。

对此的调用如下所示: -

result = universal_concatenator(4,result,"numbers are %d %f\n",5,16.045);  
result = universal_concatenator(2,result,"tail_string");

如果需要使用sprintf()或strcat(),可以定义一个需要担心的函数。这就是函数的样子: -

/* you should pass the number of arguments
 * make sure the second argument is a pointer to the result always
 * if non formatted concatenation:
 *         call function with number_of_args = 2
 * else
 *         call function with number of args according to format
 *         that is, if five inputs to sprintf(), then 5.
 *
 * NOTE : Here you make an assumption that result has been allocated enough memory to
 *        hold your concatenated string. This assumption holds true for strcat() or
 *        sprintf() of your previous implementation 
 */

char* universal_concaternator(int number_of_args,...)
{
  va_list args_list;
  va_start(args_list,number_of_args);
  int counter = number_of_args;
  char *result = va_arg(args_list, char*);
  char *format;
  if(counter == 2) /* it is a non-formatted concatenation */
  {
      result = strcat(result,va_arg(args_list,char*));
      va_end(args_list);
      return result;
  }
  /* else part - here you perform formatted concatenation using sprintf*/
  format = va_arg(args_list,char*);
  vsprintf(result + strlen(result),format,args_list);
  va_end(args_list);
  return result; 
}

/* dont forget to include the header 
 * <stdarg.h> #FOR-ANSI 
 * or <varargs.h> #FOR-UNIX
 */ 

首先应该确定它应该调用哪两个(strcat或sprintf),然后它应该进行调用,并使您可以轻松地专注于您正在处理的任何实际逻辑! 只需按住ctrl + c代码并按ctrl + v进入你的代码库。

注意:Matt的答案是长字符串的一个很好的选择。但是对于短的字符串长度(<250),这应该是。

答案 5 :(得分:0)

一切都可以更简单

void strfcat(char *src, char *fmt, ...)
{
    char buf[2048];
    va_list args;

    va_start(args, fmt);
    vsprintf(buf, fmt, args);
    va_end(args);

    strcat(src, buf);
}

像strcat()一样使用它。

strfcat(dst, "%d:%s:%c\n", 4,"bla",'c');
strfcat(dst, "%d:%d:%c\n", 4,13,'s');