0

我有一个文本文件,其中可以包含中文、日文、韩文 (CJK) 和英文字符。我必须验证文件中的英文字符。仅当行以“$”字符开头时,该文件才可以包含 CJK 字符,该字符代表我的文本文件中的注释。通过网络搜索,我发现我可以使用fgetws()wchar_t类型来读取宽字符。

Q1)但我想知道 CJK 字符将如何存储在我的文本文件中 - 什么字节顺序等。

Q2) 如何循环遍历 CJK 字符。由于 Unicode 字符可以有 1 到 6 个字节,所以我不能使用 i++。

任何帮助,将不胜感激。

非常感谢。

4

3 回答 3

1

您需要将 UTF-8 文件作为 UTF-32 代码点序列读取。例如:

std::shared_ptr<FILE> f(fopen(filename, "r"), fclose);
uint32_t c = 0;
while (utf8_read(f.get(), c))
{
    if (is_english_char(c))
        ...
    else if (is_cjk_char(c))
        ...
    else
        ...
}

哪里utf8_read有签名:

bool utf8_read(FILE *f, uint32_t &c);

现在,utf8_read可能会读取 1-4 个字节,具体取决于第一个字节的值。请参阅http://en.wikipedia.org/wiki/UTF-8,谷歌搜索算法或使用您已经可用的库函数。

使用 UTF-32 代码点,您现在可以检查范围。对于英语,您可以检查它是 ASCII ( c < 0x7F) 还是Latin字符(包括对从例如法语导入的单词的重音字符的支持)。您可能还想排除不可打印的控制字符(例如0x01)。

对于Latin和/或CJK字符检查,您可以检查字符是否在给定的代码块中(有关代码点范围,请参见http://www.unicode.org/Public/UNIDATA/Blocks.txt )。这是最简单的方法。

如果您正在使用支持 Unicode 且具有书写脚本检测功能的库(例如 glib 库),您可以使用脚本类型来检测字符。或者,您可以从http://www.unicode.org/Public/UNIDATA/Scripts.txt获取数据:

Name     : Code      : Language(s)
=========:===========:========================================================
Common   : Zyyy      : general punctuation / symbol characters
Latin    : Latn      : Latin languages (English, German, French, Spanish, ...)
Han      : Hans/Hant : Chinese characters (Chinese, Japanese)
Hiragana : Hira      : Japanese
Katakana : Kana      : Japanese
Hangul   : Hang      : Korean

注意:脚本代码来自http://www.iana.org/assignments/language-subtag-registry ( Type == 'script')。

于 2012-10-09T12:08:44.630 回答
0

您需要了解UTF-8并使用一些 UTF8 处理库(或自己编写代码)。仅供参考, Glib(来自 GTK)具有 UTF-8 处理函数,能够处理可变长度的 UTF-8 字符和字符串。还有其他 UTF-8 库,例如iconv - 在 GNU libc 中 - 以及ICU和许多其他库。

UTF-8 确实定义了多字节UTF8 字符(例如中文字符)的字节顺序和内容。

于 2012-10-08T05:47:36.573 回答
0

我正在粘贴一个示例程序来说明 wchar_t 处理。希望它可以帮助某人。

#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#define BUFLEN 1024
int main() {
  wchar_t *wmessage=L"Lets- beginめん(下) 震災後、保存-食で-脚光-(経済ナビゲーター)-lets- end";
  wchar_t warray[BUFLEN + 1];
  wchar_t a = L'z';
  int i=0;
  FILE *fp;
  wchar_t *token = L"-";
  wchar_t *state;
  wchar_t *ptr;
  setlocale(LC_ALL, "");
  /* FIle in current dirrctory containing CJK chars */
  fp = fopen("input", "r");
  if (fp == NULL) {
      printf("%s\n", "Cannot open file!!!");
      return (-1);
  }
  fgetws(warray, BUFLEN, fp);
  wprintf(L"\n *********************START reading from file*******************************\n");
  wprintf(L"%ls\n",warray);
  wprintf(L"\n*********************END reading from file*******************************\n");
  fclose(fp);
  wprintf(L"printing character %lc = <0x%x>\n", a, a);
  wprintf(L"\n*********************START Checking string for Japanese*******************************\n");
  for(i=0;wmessage[i] != '\0';i++) {
      if (wmessage[i] > 0x7F) {
          wprintf(L"\n This is non-ASCII <0x%x> <%lc>", wmessage[i],  wmessage[i]);
      } else {
          wprintf(L"\n This is ASCII <0x%x> <%lc>", wmessage[i],  wmessage[i]);
      }
  }
  wprintf(L"\n*********************END Checking string for Japanese*******************************\n");
  wprintf(L"\n*********************START Tokenizing******************************\n");
  state = wcstok(warray, token, &ptr);
  while (state != NULL) {
      wprintf(L"\n %ls", state);
      state = wcstok(NULL, token, &ptr);
  }
  wprintf(L"\n*********************END Tokenizing******************************\n");
  return 0;
}
于 2012-10-08T09:17:05.113 回答