【问题标题】:sprintf() handling of %s extended ASCII (ISO 8859-1) on some runtimes?sprintf() 在某些运行时处理 %s 扩展 ASCII (ISO 8859-1)?
【发布时间】:2016-05-06 01:23:45
【问题描述】:

我在我的 C 应用程序中使用 ISO 8859-1(拉丁扩展 ASCII 字符集)。当我strcpy/strcat 将字符串的各个部分放在一起时,它可以正常工作。但是当我使用sprintf("%s %s") 时,在某些运行时(尤其是某些Android 版本)上,当扩展的ASCII 字符(特别是é,虽然我没有尝试过其他的)被命中时,字符串会被截断。

我认为%s 只是应该复制字节直到'\0' 被命中。我怀疑strcpy/strcat 有效,因为它确实做到了这一点,没有任何格式。这里可能发生了什么?

我应该注意,我不是使用printf() 查看文本,而是我自己的文本渲染引擎,它可以很好地处理 ISO-8859-1。

更新: 澄清一下,我有一个 NDK 应用程序,它将字符串保存在 C 中,并将其传递给我的基于 OpenGL 的文本渲染引擎。如果我将完整的字符串作为 char* 文字传递,它会显示得很好。如果我 sprintf() 将这些部分放在一起,它会在 é 字符处被截断。 例如:

char buffer[1024];
strcpy(buffer, "This is ");
strcat(buffer, "the string I want to diésplay.");

这显示得很好。但是这个:

sprintf(buffer, "%s%s", "This is ", "the string I want to diésplay.");

打印为:

This is the string I want to di

【问题讨论】:

  • 你确定这是 sprintf() 的错吗? strlen() 说什么?
  • 我不知道,因为我没有遇到此错误的用户的特定 android 设备(众所周知的三星型号)。在我自己的测试设备上运行良好,在 iOS 和 Win32 上也运行良好。所以我想知道某些 Android 运行时上的 sprintf() 是否将 char* 视为 UTF-8 或其他东西。
  • 让我澄清一下:你有 NDK 应用程序,它正在将字符串传递给 Java 应用程序?
  • 没有。我有一个 NDK 应用程序,它将字符串保存在 C 中,并将其传递给我的基于 OpenGL 的文本渲染引擎。如果我将完整的字符串作为 char* 文字传递,它会显示得很好。如果我 sprintf() 将这些部分放在一起,它会在 é 字符处被截断。例如:字符缓冲区[1024]; strcpy(buffer, "这是"); strcat(buffer, "我想显示的字符串。");这显示得很好。但是这个: sprintf(buffer, "%s%s", "This is ", "the string I want to diésplay.");打印为:This is the string I want to di
  • 完全有可能将 UTF-8 编码的字节转换为 C 字符串,但这并不能解释您的用户的观察,因为值 0 不会出现在 UTF-8 编码中'\0' 以外的任何字符。可能存在编码问题,但我不能说哪种编码会产生您所描述的行为。

标签: android c ansi-c


【解决方案1】:

s[n]printf() 的行为与 strcpy()strcat() 等字符串操作函数的行为不同。当呈现相同的格式和打印项目时,printf-family 函数都需要生成相同的字节序列。唯一的区别在于这些字节的发送位置。因此,如果您的 C 库的构建使得它在通过printf() 打印到标准流时对字符串数据执行转换(可能是转码),那么它在通过sprintf() 打印到字符串时将执行相同的转换。

“printf”中的“f”表示“格式化”。该标准既没有说也没有暗示格式化字符串必须意味着将其字节逐字转储到输出中,因此我上面假设的转码或其他转换并不是不可能的。事实上,the docs for some versions of these functions 表示依赖于语言环境(“请注意,生成的字符串的长度取决于语言环境,难以预测”),因此特别是转码是一种可能。

您描述的第三方观察结果的任何具体解释都必然是推测性的,因为您没有提供几乎足够的代码或数据来做出自信的诊断。我倾向于怀疑围绕在使用与程序内部使用的字符编码不同的字符编码的语言环境中运行程序的问题。如果是这样,那么您可以通过更改运行的语言环境在本地重现该问题,并且您可以通过确保您的程序始终在合适的语言环境中运行的一种或另一种方式来解决该问题。除其他外,您可以使用 getlocale()setlocale() 函数来提供帮助,特别是如果您想限制您行使区域设置控制的范围。

由于最终您仅将 printf 系列函数用于字符串操作,但是,我认为最好使用问题中提出的解决方法:尽可能使用 C 的专用字符串操作函数,例如strcpy()strncat(),执行您的字符串构建。由于您的实际输出不依赖于 stdio 函数,因此应该没问题。

【讨论】:

  • 绝妙的答案!正是我想要的。我会尝试弄乱语言环境,看看我是否可以复制它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-25
  • 2015-10-11
  • 2011-06-10
  • 2013-01-19
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多