首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何修复现场?

如何修复现场?
EN

Stack Overflow用户
提问于 2016-10-28 05:47:43
回答 3查看 797关注 0票数 1

添加ru_RU.CP1251语言环境(在debian上,在/etc/locale.gen中取消注释ru_RU.CP1251并运行sudo locale-gen),并使用gcc -fexec-charset=cp1251 test.c编译以下程序(输入文件在UTF-8中)。结果是空的。只要字母'я‘是错误的。其他字母可以是小写字母,也可以是大写字母。

代码语言:javascript
复制
#include <locale.h>
#include <ctype.h>
#include <stdio.h>
int main (void)
{
  setlocale(LC_ALL, "ru_RU.CP1251");
  char c = 'я';
  int i;
  char z;
  for (i = 7; i >= 0; i--) {
    z = 1 << i;
    if ((z & c) == z) printf("1"); else printf("0");
  }
  printf("\n");

  if (islower(c))
    printf("lowercase\n");
  if (isupper(c))
    printf("uppercase\n");
  return 0;
}

为什么islower()isupper()都不工作在字母я

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-11-11 08:14:17

答案是CP 1251中该字符小写版本的编码是十进制255,您的实现的islower()isupper()不接受或返回该值(通常被解释为EOF)。

您需要跟踪运行时库的源代码,以了解它的功能和原因。

解决方案是编写自己的实现,或者包装已有的实现。就我个人而言,我从来没有直接使用这些函数,因为有很多问题。

票数 1
EN

Stack Overflow用户

发布于 2016-11-03 06:43:23

Igor,如果您的文件是UTF-8,那么尝试使用代码页1251是没有意义的,因为它与utf-8编码没有任何共同之处。只需使用地区ru_RU.UTF-8,您就可以显示您的文件没有任何问题。或者,如果坚持使用ru_RU.CP1251,那么首先需要将文件从utf-8编码转换为cp1251 (可以使用iconv(1)实用程序)

代码语言:javascript
复制
iconv --from-code=utf-8 --to-code=cp1251 your_file.txt > your_converted_file.txt

另一方面,--fexec-charset=cp1251只影响在可执行文件上使用的字符,但是您还没有在源代码中指定要在字符串文本中使用的输入字符集。可能,编译器正在从环境(在LANG或LC_CHARSET环境变量中设置的环境)确定这一点。

只有在您精确地控制了每个阶段使用的区域设置之后,您才会得到一致的结果。

正努力将所有国家转换为一个共同字符集(UTF)的主要原因是,不需要在每个阶段处理所有这些地区设置。

如果您总是处理以CP1251编码的文档,您将需要对计算机上的所有内容使用这种编码,但是当您收到一些以utf-8编码的文档时,您必须转换它才能正确地看到它。

我建议您切换到utf-8,因为它是一种支持所有国家字符集的编码,但是现在,这个决定只是你的决定。

备注

在debian linux上:

代码语言:javascript
复制
$ sed 's/^/    /' pru-$$.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>

#define P(f,v) printf(#f"(%d /* '%c' */) => %d\n", (v), (v), f(v))
#define Q(v) do{P(isupper,(v));P(islower,(v));}while(0)

int main()
{
    setlocale(LC_ALL, "");
    Q(0xff);
}

代码语言:javascript
复制
$ make pru-$$
cc    pru-1342.c   -o pru-1342

ru_RU.CP1251语言环境执行

代码语言:javascript
复制
$ locale | sed 's/^/    /'
LANG=ru_RU.CP1251
LANGUAGE=
LC_CTYPE="ru_RU.CP1251"
LC_NUMERIC="ru_RU.CP1251"
LC_TIME="ru_RU.CP1251"
LC_COLLATE="ru_RU.CP1251"
LC_MONETARY="ru_RU.CP1251"
LC_MESSAGES="ru_RU.CP1251"
LC_PAPER="ru_RU.CP1251"
LC_NAME="ru_RU.CP1251"
LC_ADDRESS="ru_RU.CP1251"
LC_TELEPHONE="ru_RU.CP1251"
LC_MEASUREMENT="ru_RU.CP1251"
LC_IDENTIFICATION="ru_RU.CP1251"
LC_ALL=

$ pru-$$
isupper(255 /* 'я' */) => 0
islower(255 /* 'я' */) => 512

因此,glibc不是错误,而是代码中的错误。

票数 1
EN

Stack Overflow用户

发布于 2016-11-11 07:23:47

乔纳森·莱弗勒对OP的第一个评论是正确的。isxxx() (和iswxxx())函数需要处理EOF (WEOF)参数(可能是为了防止傻瓜)。这就是为什么选择int作为参数类型的原因。当我们传递char或字符文字类型的参数时,它被提升为int (保留符号)。由于默认情况下,char类型和字符文字都是用gcc签名的,所以0xFF变成了-1,这与EOF的值是不愉快的巧合。

因此,在将char类型的参数(以及带有代码0xFF的字符文本)传递给函数时,始终要使用int参数类型(不要依赖char的未签名性,因为它是实现定义的)。类型转换既可以通过(unsigned char)完成,也可以通过(uint8_t)完成,后者不太适合键入(您必须包括stdint.h)。

另见bug.cgi?id=20792Why passing char as parameter to islower() does not work correctly?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40298801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档