如何在格式化字符串上使用strlen()?

我想为mvwprint / mvwchgat ncurses函数编写一个包装函数,它在指定的窗口中打印消息,然后更改其属性。

但是, mvwchgat需要知道它应该改变多少个字符 – 而且我不知道如何告诉mvwchgat格式化字符串有多长,因为strlen() on,例如"abc%d"显然会返回5,因为strlen不知道%d代表什么…

在C99或C11中,您可以使用如下所示的行:

 length = snprintf(NULL, 0, format_string, args); 

snprintf手册 (强调我的):

函数snprintf()和vsnprintf()写入的字节数不超过大小(包括终止空字节(’\ 0’))。 如果输出因此限制而被截断,则返回值是字符数(不包括终止空字节),如果有足够的空间,则该字符数将被写入最终字符串 。 因此,大小或更大的返回值意味着输出被截断。

由于我们将snprintf 0作为大小,因此输出总是被截断, snprintf的输出将是已经写入的字符数,这基本上是字符串的长度。

在C89中,您没有snprintf 。 解决方法是创建一个临时文件,或者如果你在* nix open /dev/null并写下这样的东西:

 FILE *throw_away = fopen("/dev/null", "w"); /* On windows should be "NUL" but I haven't tested */ if (throw_away) { fprintf(throw_away, "%n", , &length); fclose(throw_away); } /* else, try opening a temporary file */ 

您无法预先知道字符串的长度:

 printf("abc%d", 0); //4 chars printf("abc%d", 111111111);//12 chars 

全部具有相同的格式字符串。

唯一可靠的方法是将有问题的文本sprintf到缓冲区, strlen(buffer)结果和printf("%s", buffer); 筛选结果。

此解决方案避免了以分配足够长的缓冲区为代价的双重格式化。