Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何在格式化字符串上使用strlen()?_C_String_Ncurses_Strlen_Formatted - Fatal编程技术网

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

C 如何在格式化字符串上使用strlen()?,c,string,ncurses,strlen,formatted,C,String,Ncurses,Strlen,Formatted,我想为mvwprint/mvwchgat ncurses函数编写一个包装函数,它在指定的窗口中打印消息,然后更改其属性 然而,mvwchgat需要知道它应该更改多少个字符——我不知道如何告诉mvwchgat格式化字符串的长度,因为例如,“abc%d”上的strlen()显然返回5,因为strlen不知道%d代表什么…在C99或C11中,您可以使用这样一行: length = snprintf(NULL, 0, format_string, args); FILE *throw_away = f

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


然而,mvwchgat需要知道它应该更改多少个字符——我不知道如何告诉mvwchgat格式化字符串的长度,因为例如,
“abc%d”
上的strlen()显然返回5,因为strlen不知道
%d
代表什么…

在C99或C11中,您可以使用这样一行:

length = snprintf(NULL, 0, format_string, args);
FILE *throw_away = fopen("/dev/null", "w"); /* On windows should be "NUL" but I haven't tested */
if (throw_away)
{
    fprintf(throw_away, "<format goes here>%n", <args go here>, &length);
    fclose(throw_away);
} /* else, try opening a temporary file */
从(我的)重点:

函数snprintf()和vsnprintf()的写入长度不超过大小字节(包括终止的空字节('\0'))如果输出由于此限制而被截断,则返回值为字符数(不包括终止的空字节),如果有足够的可用空间,该字符数将写入最终字符串。因此,返回值大于等于size意味着输出被截断

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

在C89中,您没有
snprintf
。解决方法是创建一个临时文件,或者在*nix open
/dev/null
中编写如下内容:

length = snprintf(NULL, 0, format_string, args);
FILE *throw_away = fopen("/dev/null", "w"); /* On windows should be "NUL" but I haven't tested */
if (throw_away)
{
    fprintf(throw_away, "<format goes here>%n", <args go here>, &length);
    fclose(throw_away);
} /* else, try opening a temporary file */
FILE*throw_away=fopen(“/dev/null”,“w”);/*在windows上应该是“NUL”,但我还没有测试*/
如果(扔掉)
{
fprintf(丢弃“%n”和长度);
fclose(扔掉);
}/*否则,请尝试打开临时文件*/

您无法提前知道字符串的长度:

printf("abc%d", 0); //4 chars
printf("abc%d", 111111111);//12 chars
都使用相同的格式字符串

唯一可靠的方法是
sprintf
将相关文本放入缓冲区,
strlen(buffer)
结果和
printf(“%s”,buffer)将结果显示在屏幕上


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

难道您不能获取格式化字符串,然后计算它的长度吗?sprintf打印和strlen测量。您如何知道缓冲区的长度足够长?除非您有最终的大小,否则无法创建足够大的缓冲区。听起来不错:)现在,请澄清:在C89中无法做到这一点?@UncleDolan,请参阅我的编辑。我承认这不是最优雅的,但我必须想更多的更好的选择。@Shahbaz Nevermind,我只是出于兴趣才这么问的,因为有人告诉我,作为初学者,我应该坚持C89标准,因为它会改进我的编码风格,尽管我真的不知道这是不是真的…@UncleDolan,我不这么认为。C99是对C89的改进,它实际上已经有13年的历史了!这不是不好/不成熟的事情。我鼓励你使用它。(顺便说一句,我甚至不知道
snprintf
不在C89中!)@shabaz:你甚至可以不用先写/dev/null。考虑到文件系统对于任何字符串都足够大,您只需执行以下操作:
len=fprintf(tmpfile,fmt,…)然后:malloc(len+1);倒带,fread()一次扫描整个字符串。当然还有fclose(tmpfile)。