当我们使用MinGW-w64作为编译器在windows系统环境下进行C语言编程时,如果源代码文件(.c)保存格式为Ansi格式,则在打印汉字时不会出现乱码;反之,如果我们使用UTF-8格式保存,则会出现乱码,需要在编译时加上“-fexec-charset=gbk”来解决乱码问题。
#include <stdio.h> int main() { printf("%s ", "你好,世界!"); return 0; }
那么,当我们使用C语言处理文件时,如果文件格式是UTF-8,如何转换成Ansi格式呢?注意:在windows下,txt的保存格式中有UTF-8和带有BOM的UTF-8两个选项。如果选择带有BOM的UTF-8选项,则在读取文件时会首先读到三个标志着这个文件是由UTF-8格式编码的字符,分别为EF BB BF。如果选择UTF-8,则不会有这三个字符,而是直接一开始就读到文件本身内容。详情请看:https://blog.csdn.net/wang544831183/article/details/82349668
1 // char.h 2 // 头文件 3 // 定义结构体File,存储文件信息 4 // 定义结构体初始化函数以及其他函数 5 6 #ifndef _H_CHAR_ 7 #define _H_CHAR_ 8 9 #include <stdio.h> 10 #include <stdbool.h> 11 #include <stdlib.h> 12 #include <windows.h> 13 14 unsigned char BOM[] = {0xEF, 0xBB, 0xBF}; // 带有BOM的UTF-8编码格式的文件会以这三个字符开头 15 16 // File结构体定义 17 typedef struct file { 18 char *filename; 19 char *filemode; 20 char *encoding; 21 bool readable; 22 } File; 23 24 // 函数定义 25 File *initializeFile(char *, char *); // 初始化结构体 26 bool isUTF8(char *); // 判断文件是否为UTF-8编码格式 27 bool isReadable(char *); // 判断filemode是否支持可读选项 28 bool charInString(char, char *); // 判断字符是否在字符串中 29 void fprint(File *); // 打印结构体内容 30 void fprintInfo(File *); // 打印结构体信息 31 void deconstructFile(File *); // 析构化结构体 32 void fprintAnsi(File *); // 以Ansi格式打印 33 // 转换函数定义 34 void Convert(const char* strIn, char* strOut, int sourceCodepage, int targetCodepage); 35 void UTF82Ansi(PCHAR Src, PCHAR Dst); 36 void Ansi2UTF8(PCHAR Src, PCHAR Dst); 37 38 // 函数实现 39 File *initializeFile(char *filename, char *filemode) 40 { 41 File *file = (File *)malloc(sizeof(File)); 42 file->filename = filename; 43 file->filemode = filemode; 44 file->encoding = "Ansi"; 45 file->readable = false; 46 47 if (isUTF8(filename)) 48 { 49 file->encoding = "UTF-8"; 50 } 51 52 if (isReadable(filemode)) 53 { 54 file->readable = true; 55 } 56 57 return file; 58 } 59 60 bool isUTF8(char *filename) 61 { 62 FILE *fp = fopen(filename, "r"); 63 64 if (fp == NULL) 65 { 66 printf("Unable to open file %s ", filename); 67 return false; 68 } 69 70 unsigned char *buffer = (unsigned char *)malloc(sizeof(unsigned char) * 3); 71 fread(buffer, 3, 3, fp); 72 fclose(fp); 73 74 for (int i = 0; i < 3; i++) 75 { 76 if (buffer[i] != BOM[i]) 77 { 78 return false; 79 } 80 } 81 82 return true; 83 } 84 85 bool isReadable(char *filemode) 86 { 87 if (charInString('r', filemode) || charInString('+', filemode)) 88 { 89 return true; 90 } 91 return false; 92 } 93 94 bool charInString(char ch, char *str) 95 { 96 while (*str != '