C - 使用特殊字符格式化字符串大小

时间:2018-01-02 16:41:31

标签: c string format special-characters

所以,我试图用格式良好的字符串来打印灯具,但我发现每当有一个特殊字符,如'é''í''á'即使我指定了最大长度,它也会打印+1大小。

代码在哪里:

printf("=> %-25s (%d) vs (%d) \t%-25s\n", f->home_team_name, f->goals_home_team, f->goals_away_team, f->away_team_name);

对于具有这些角色的团队,输出如下:

=> Palmeiras               (2) vs (0)   Botafogo               
=> Atlético Mineiro       (4) vs (3)    Grémio                
=> Atlético PR            (3) vs (0)    Palmeiras              
=> Botafogo                (2) vs (2)   Cruzeiro   

但我希望输出看起来像,即使是特殊字符:

=> Tottenham Hotspur FC    (0) vs (0)   Leicester City FC      
=> West Ham United FC      (0) vs (0)   Everton FC             
=> Burnley FC              (0) vs (0)   AFC Bournemouth   

我试图寻找格式化标记,但无法找到解决方案。

1 个答案:

答案 0 :(得分:3)

printf中的格式字符串不考虑多字节字符。

一种可能的解决方案是通过mbstowcs函数计算字符串的宽字符。然后从检查的字符串的长度(即以字节为单位)中减去所获得的计数。这会产生(非负)"补偿值",可以添加到mbstowcs的格式字段宽度。

src函数描述为:

  

从第一个数组中转换多字节字符串   dst将元素指向其广泛的字符表示。   转换后的字符存储在连续的元素中   len指向的数组。写入的宽度不超过char个字符   到目的地阵列。

在您的情况下,这意味着UTF-8编码的八位字节(在wchar_t数组中表示)将转换为某些宽表示,这保证了任何多字节字符(最多为语言环境)特定的MB_CUR_MAX个字节)可以由不超过一个<stddef.h>对象编码。

C11标准的相关引用载于7.19 / 2 通用定义wchar_t

  

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> static inline size_t widestrlen(const char *str) { return mbstowcs(NULL, str, strlen(str)); } static inline size_t compensation(const char *str) { return strlen(str) - widestrlen(str); } int main(void) { setlocale(LC_CTYPE, ""); // Print some debugging information regarding selected locale printf("Current locale for LC_TYPE category: %s\n", setlocale(LC_CTYPE, NULL)); printf("Maximum number of bytes in a multibyte character: %zu\n", MB_CUR_MAX); printf("Does current encoding support shift states? : %s\n\n", mblen(NULL, 0) ? "Yes" : "No"); int goals_home_teams[] = { 4, 0 }; int goals_away_teams[] = { 3, 0 }; const char *home_team_names[] = { "Atlético Mineiro", "West Ham United FC" }; const char *away_team_names[] = { "Grémio", "Everton FC" }; for (int i = 0; i < 2; i++) { printf("=> %-*s (%d) vs (%d) \t%-*s\n", 25 + (int) compensation(home_team_names[i]), home_team_names[i], goals_home_teams[i], goals_away_teams[i], 25 + (int) compensation(away_team_names[i]), away_team_names[i]); } return 0; }

     

是一个整数类型,其值范围可以表示不同   指定的最大扩展字符集的所有成员的代码   在支持的语言环境中;

例如,在Linux平台上,宽字符最有可能在UCS-4中表示(称为UTF-32)。

以下是概念证明:

Current locale for LC_TYPE category: en_US.UTF-8
Maximum number of bytes in a multibyte character: 6
Does current encoding support shift states? : No

=> Atlético Mineiro          (4) vs (3)     Grémio                   
=> West Ham United FC        (0) vs (0)     Everton FC  

结果:

=SELECT(Sheet'Master Database'!A:K, WHERE 'Master Database'!C CONTAINS ‘”,'List'!B5,”‘”)