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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C - 使用特殊字符格式化字符串大小相关的知识,希望对你有一定的参考价值。

所以,我试图从字符串格式良好的比赛中打印灯具,但我发现只要有'é'或'í'或'á'这样的特殊字符,即使我指定了最大值,它也会打印+1大小长度。

代码在哪里:

printf("=> %-25s (%d) vs (%d) 	%-25s
", 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   

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

答案

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

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

mbstowcs函数描述为:

将多字节字符串从src指向其第一个元素的数组转换为其宽字符表示形式。转换后的字符存储在dst指向的数组的连续元素中。只有len宽字符写入目标数组。

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

C11标准的相关引用载于7.19 / 2通用定义<stddef.h>

wchar_t

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

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

这是一个概念证明:

#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
", setlocale(LC_CTYPE, NULL));
    printf("Maximum number of bytes in a multibyte character: %zu
", MB_CUR_MAX);
    printf("Does current encoding support shift states? : %s

", 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) 	%-*s
",
            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;
}

结果:

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  

以上是关于C - 使用特殊字符格式化字符串大小的主要内容,如果未能解决你的问题,请参考以下文章

json格式如何读取有特殊字符的数据!内详!

如何从我的 DatePicker 片段中传输格式化的日期字符串?

如何让在Html中特殊字符不被转义

json特殊字符都有哪些

C语言字符串打印出现特殊字符是怎么回事?请问如何解决这个问题?

如何用java读取文件并统计文件的大小写字母,数字,特殊字符的个数