
格式说明符中的宽度字段.我有个疑问
对于(非宽)char数组参数的情况:
宽度字段应该是字节还是字符?
如果char数组是什么(正确 – 事实上)行为
对应(比方说)一个原始的UTF-8字符串?
(我知道通常我应该使用一些宽的char类型,
那不是重点)
例如,在
char s[] = "ni\xc3\xb1o"; // utf8 encoded "niño"fprintf(f,"%5s",s);
这个函数应该只尝试输出5个字节
(普通C chars)(并且你承担了错位的责任
或两个字节导致文本字符的其他问题)?
或者是否应该尝试计算“文本字符”的长度
阵列? (根据当前的语言环境对其进行解码?)
(在这个例子中,这相当于发现字符串有
4个unicode字符,所以它会为填充添加一个空间).
更新:我同意答案,printf家族没有合情合理
将普通C字符与字节区分开来.问题是我的glibc doest似乎没有
完全尊重这个概念,如果先前已经设置了区域设置,并且如果
一个有(今天最常用)LANG / LC_CTYPE = en_US.UTF-8
例证:
#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 0a0000020 | 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 cx10000000 | 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 0a0000020 | A 261 B | \n | A 261 B | \n 7c 41 b1 42 7c 0a 7c 41 b1 42 7c 0a0000034
所以你可以看到输出流包含UTF-8,这意味着它是必须解释它的终端程序. C / glibc根本没有修改输出,所以也许我只是误解了你想说的内容.
虽然我刚刚意识到你可能会说你的od输出也只有那条线上的起始条(不像我看起来没有问题),这意味着它在C / glibc中是错的,不是错的终端默默地丢弃角色(说实话,我希望终端能够丢弃整行或者只是违规的字符(即输出| A) – 你刚刚得到的事实似乎排除了一个终端问题).请澄清一下.
总结以上是内存溢出为你收集整理的printf字段宽度:字节还是字符?全部内容,希望文章能够帮你解决printf字段宽度:字节还是字符?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)