【问题标题】:C printf function does not align strings correctly for strings that contain Turkish characters对于包含土耳其语字符的字符串,C printf 函数无法正确对齐字符串
【发布时间】:2019-07-23 12:33:49
【问题描述】:

我有以下代码以左对齐格式在控制台上打印一些字符串:

#include <stdio.h>
#include <locale.h>
#include <stdlib.h>

int main()
{
    printf("%s:\n", "Türkçe karakterler ile");
    printf("%-14s: \n", "Onaltılık");
    printf("%-14s: \n", "Onluk");
    printf("%-14s: \n", "İkilik");

    printf("\n%s:\n", "Türkçe karakterler olmadan");
    printf("%-14s: \n", "Onaltilik");
    printf("%-14s: \n", "Onluk");
    printf("%-14s: \n", "Ikilik");
}

我在 Ubuntu 18.04 系统上使用 gcc(7.3.0) 和 clang(6.0.0) 编译了这段代码。

输出如下:

Türkçe karakterler ile:
Onaltılık  : 
Onluk        : 
İkilik      : 

Türkçe karakterler olmadan:
Onaltilik     : 
Onluk         : 
Ikilik        :

从第一组字符串中的代码可以看出,有一些土耳其字符,例如“ı”和“İ”。第二组字符串中没有土耳其字符。

printf 函数的输出未正确对齐包含土耳其字符的字符串。预期的输出是:

Türkçe karakterler ile:
Onaltılık     : 
Onluk         : 
İkilik        : 

Türkçe karakterler olmadan:
Onaltilik     : 
Onluk         : 
Ikilik        :

如果我使用 gcc(CodeBlocks 17.2 中的 MinGW v5.1.1)在 Windows 系统(Windows 7)上编译相同的代码,则输出正确,如下所示:

Türkçe karakterler ile:
Onaltılık     :
Onluk         :
İkilik        :

Türkçe karakterler olmadan:
Onaltilik     :
Onluk         :
Ikilik        :

谁能帮我找出问题所在?

【问题讨论】:

  • 您是否尝试过设置setlocale(LC_ALL,""); 并使用puts() 打印字符串?
  • strlen("Onaltılık)"strlen("Onaltilik)" 在两个平台上的回报是什么?
  • 也许尝试在你的字符串前加上L?像这样:L"Turkish characters"
  • @Jabberwocky 从下面的答案中我了解到,当存在包含非 ASCII 字符的字符串时,如“Onaltılık”strlen 或 printf 不会返回正确的结果。 strlen("Onaltılık") 的预期结果是 9,但它返回 11。我认为这是因为字符串中有两个 'ı' 字符,它是一个非 ASCII(多字节)字符。

标签: c text printf alignment


【解决方案1】:

我的猜测是因为您的编辑器使用 UTF-8 保存了源代码,这是一种 多字节 编码。 printf 系列函数只处理 byte 字符串。这意味着每个非 ASCII 字符都将被 printf 计为多个字符。

如果是这样,您可以通过打印字符串来解决此问题,然后在打印空字符串时使用* 修饰符后手动添加填充。 * 修饰符允许您将宽度作为参数传递给printf

类似这样的:

printf("%s%*s: \n", "Onaltılık", 5, "");  // 5 = 14 - 9, where 9 is the number of "characters" in Onaltılık
printf("%s%*s: \n", "Onluk"    , 9, "");  // Dito for Onluk
printf("%s%*s: \n", "İkilik"   , 8, "");  // Dito for İkilik

输出:

Onaltılık: 安乐: 伊基利克:

【讨论】:

  • 感谢您的回答。虽然这不是我想要做的,但这些信息非常有用。这解释了为什么我得到这个结果。 strlen 函数不返回字符串“Onaltılık”的正确长度。我想这也是出于同样的原因。我认为应该有一些解决方案。其他语言(Java、Python、...)只能使用 Unicode 字符。 C 也应该适用于 Unicode。我认为应该重新实现标准库中的函数以使用 Unicode 字符。还是谢谢...
  • @Karşıbalı “其他语言”实际上是其他语言。你不能指望两种不同的语言能同样工作。编程语言有点像书面和口头语言,没有两种书面和口头语言具有完全相同的规则和语法,即使它们密切相关。编程语言也是如此。在 C 的情况下,除了字节大小的字符(或 wchar_t,它在任何特定方式上仍然不是 Unicode)之外,它没有对任何内容的原生内置支持。
  • @Karşıbalı 有一些库可以让您在 C 中使用 Unicode 更轻松,例如 libiconv。设置正确的语言环境可以帮助解决一些问题,但远非一切。
  • 为什么你认为相同的代码在 Windows 7 上可以正常工作?
猜你喜欢
  • 2016-10-09
  • 1970-01-01
  • 2016-06-06
  • 2023-03-25
  • 1970-01-01
  • 2017-09-29
  • 1970-01-01
  • 2012-04-23
  • 2015-01-07
相关资源
最近更新 更多