11-12 统计文件字符个数(部分待定)

1. 统计中文文本的字符个数

        使用宽字符相关函数 wcslen() 以及宽字符文件读取相关函数 fgetws() 统计中文文本的字符个数。

        需要注意的是,设定 GBK 编码的代码在不同系统下不同。windows 系统下 设定 GBK 编码的代码为 setlocale(LC_ALL, "chs"),其他系统(Linux,Mac)下设定 GBK 编码的代码为 setlocale(LC_ALL, "zh_CN.gbk")。设定 GBK 编码后,读取文件的代码是一致的,均为 file = fopen(filename, "r")。

        UTF-8 正好与之相反。不同系统下设定 UTF-8 的代码相同,均为 setlocale(LC_ALL, "zh_CN.utf-8"),而读取 UTF-8 编码文件的代码不一致。windows 系统下读取 utf-8 编码的文件代码为 file = fopen(filename, "r, ccs=utf-8"),其他系统均为 file = fopen(filename, "r")。

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


// 设定错误类型
#define ERROR_ILLEGAL_FILENAME -1
#define ERROR_CANNOT_OPEN_FILE -2
#define ERROR_READ_FILE -3
#define ERROR_UNSUPPORTED_CHARSET -99

#define CHARSET_UTF8 0
#define CHARSET_GBK 1

#define BUFFER_SIZE 512

int CountCharactersInFile(char const *filename, int charset) {

  if (filename == NULL) return ERROR_ILLEGAL_FILENAME;

  FILE *file;

  // 不同编码格式,执行不同操作
  switch (charset) {

    case CHARSET_GBK:

#ifdef _WIN32  // 设定不同系统对应的 GBK 编码
      setlocale(LC_ALL, "chs");
#else
      setlocale(LC_ALL, "zh_CN.gbk");
#endif

      file = fopen(filename, "r");
      break;

    case CHARSET_UTF8:
      setlocale(LC_ALL, "zh_CN.utf-8");  // 不同系统下设定 utf-8 方法相同

#ifdef _WIN32 // 不同系统使用 utf-8 格式,读取的方法有差别
      file = fopen(filename, "r, ccs=utf-8");
#else
      file = fopen(filename, "r");
#endif
      break;

    default: return ERROR_UNSUPPORTED_CHARSET;
  }

  // 文件打开失败
  if(file == NULL) return ERROR_CANNOT_OPEN_FILE;

  // 文件打开成功
  wchar_t wcs[BUFFER_SIZE];
  int count = 0;
  while(fgetws(wcs, BUFFER_SIZE, file) != NULL){ // 文件没读完
    count += wcslen(wcs);  // 读取的字符个数加和
  }
  // 文件读完,判断读完的原因
  if(ferror(file)){
    perror("method error!");
    fclose(file);  // 文件打开就要关闭,注意!!
    return ERROR_READ_FILE;
  }

  fclose(file);
  return count;
}

int main() {

  TestWchar();

  printf("data/sanguo_gbk.txt: %d\n", CountCharactersInFile("data/sanguo_gbk.txt", CHARSET_GBK));
  printf("data/sanguo_utf8.txt: %d\n", CountCharactersInFile("data/sanguo_utf8.txt", CHARSET_UTF8));

  printf("data/CMakeLists_gbk.txt: %d\n", CountCharactersInFile("data/CMakeLists_gbk.txt", CHARSET_GBK));
  printf("data/CMakeLists_utf8.txt: %d\n", CountCharactersInFile("data/CMakeLists_utf8.txt", CHARSET_UTF8));

  return 0;
}

2. 统计英文字符个数

        统计英文个数可以使用窄字符相关函数 strlen() 和 fgets(),也可使用上述统计中文字符个数的代码(原因?)

        mingw 编译器下(未修改编译器编码格式),GBK 和 UTF-8 编码的程序文件,其执行结果相同。msvc 编译器 + 程序文件 GBK 编码(编译器默认编码格式为 GBK)也可得到下图的结果,而当 msvc 编译器 + 文件 UTF-8 编码时,若不修改编译器编码格式为 UTF-8 时,则会报程序错误。

         故一定要注意三个地方的编码需要保持一致。一,文件本身的编码;二,编译器编译时使用的编码;三,程序代码读取相关字符时使用的编码。三者编码保持一致,才可以正确获取宽字符的个数。三个地方的编码调整方式见:https://blog.csdn.net/gltzlike/article/details/119479343

        此外,使用 wcslen() 函数时,如果三个地方编码格式不一致,不能获取到正确的宽字符个数。

void TestWchar(){

  wchar_t str1[] = L"你好,中国!";
  int count = wcslen(str1);
  printf("%d", count);  // 6

}

3. 疑惑

        1)为什么统计中文字符个数的代码,可以准确无误的统计英文字符个数?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值