printf字段宽度:字节还是字符?
printf / fprintf / sprintf系列支持
格式说明符中的宽度字段.我有个疑问 对于(非宽)char数组参数的情况: 宽度字段应该是字节还是字符? 如果char数组是什么(正确 – 事实上)行为 例如,在 char s[] = "nixc3xb1o"; // utf8 encoded "ni?o" fprintf(f,"%5s",s); 这个函数应该只尝试输出5个字节 或者是否应该尝试计算“文本字符”的长度 更新:我同意答案,printf家族没有合情合理 例证: #include<stdio.h> #include<locale.h> main () { char * locale = setlocale(LC_ALL,""); /* I have LC_CTYPE="en_US.UTF-8" */ char s[] = {'n','i',0xc3,0xb1,'o',0}; /* "ni?o" in utf8: 5 bytes,4 unicode chars */ printf("|%*s|n",6,s); /* this should pad a blank - works ok*/ printf("|%.*s|n",4,s); /* this should eat a char - works ok */ char s3[] = {'A','B',0}; /* this is not valid UTF8 */ printf("|%s|n",s3); /* print raw chars - ok */ printf("|%.*s|n",15,s3); /* panics (why???) */ } 因此,即使设置了非POSIX-C语言环境,仍然printf似乎有正确的概念来计算width:bytes(c plain chars)而不是unicode chars.没关系.但是,当给定一个在其语言环境中无法解码的char数组时,它会无声地发生恐慌(它会中止 – 在第一个’|’之后没有任何内容打印 – 没有错误消息)…只有当它需要计算一些宽度时才会出现.我不明白为什么它甚至会尝试从utf-8解码字符串,当它不需要/必须时.这是glibc中的错误吗? 用glibc 2.11.1(Fedora 12)测试(也是glibc 2.3.6) 注意:它与终端显示问题无关 – 您可以通过管道检查输出到od:$./a.out | od -t cx1这是我的输出: 0000000 | n i 303 261 o | n | n i 303 261 | n 7c 20 6e 69 c3 b1 6f 7c 0a 7c 6e 69 c3 b1 7c 0a 0000020 | A 261 B | n | 7c 41 b1 42 7c 0a 7c 更新2(2015年5月):这个有问题的行为has been fixed在较新版本的glibc中(从2.17开始,似乎).使用glibc-2.17-21.fc19它对我来说还可以. 解决方法
它将导致输出五个字节.和五个字符.在ISO C中,字符和字节之间没有区别.字节不一定是8位,而是定义为char的宽度.
8位值的ISO术语是八位字节. 你的“ni?o”字符串在C环境方面实际上是五个字符宽(当然没有空终结符).如果终端上只显示四个符号,那几乎可以肯定是终端的功能,而不是C的输出功能. 我不是说C实现无法处理Unicode.如果CHAR_BITS被定义为32,它可以很容易地做到UTF-32.由于UTF-8是一个可变长度编码会更难,但几乎所有问题都有办法:-) 根据您的更新,您可能会遇到问题.但是,我没有在我的设置中看到您描述的行为具有相同的区域设置.在我的情况下,我在最后两个printf语句中得到相同的输出. 如果您的设置只是在第一个|之后停止输出(我假设你的意思是中止但是,如果你的意思是整个程序中止,那就更严重了),我会提出GNU的问题(首先尝试你的特定发行版程序).你已经完成了所有重要的工作,例如生成一个最小的测试用例,所以如果你的发行版没有完全达到目的,大多数人都不应该对最新版本进行操作. 顺便说一句,我不确定你的意思是检查od输出.在我的系统上,我得到: pax> ./qq | od -t cx1 0000000 | n i 303 261 o | n | n i 303 261 | n 7c 20 6e 69 c3 b1 6f 7c 0a 7c 6e 69 c3 b1 7c 0a 0000020 | A 261 B | n | A 261 B | n 7c 41 b1 42 7c 0a 7c 41 b1 42 7c 0a 0000034 所以你可以看到输出流包含UTF-8,这意味着它是必须解释它的终端程序. C / glibc根本没有修改输出,所以也许我只是误解了你想说的内容. 虽然我刚刚意识到你可能会说你的od输出也只有那条线上的起始条(不像我看起来没有问题),这意味着它在C / glibc中是错的,不是错的终端默默地丢弃角色(说实话,我希望终端能够丢弃整行或者只是违规的字符(即输出| A) – 你刚刚得到的事实似乎排除了一个终端问题).请澄清一下. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |