strcat()用于格式化字符串

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

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

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

您的解决方案将有效。 调用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()以这种方式使用时效率更高。

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

不,这是不可能的,但你可以在这些简单的字符串上使用sprintf() ,并避免每次调用strlen()

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

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

 #include  #include  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的答案和mux的答案 。 用于保存单个字段的各个数组不是必需的,至少在这种情况下不是这样。

由于此代码不会跟踪字符串的结尾,因此性能可能很差。 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()附加格式化的字符串。 这不太可能是一个好主意。

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

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

对此的调用如下: –

 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 *  #FOR-ANSI * or  #FOR-UNIX */ 

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

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