“我花了两天时间,解决了一个中文字符在MQL下的解码问题”
众所周知中文字符需要用UTF8编码。
如果是用高级语言开发,那么基本不会遇到编解码问题,语言本身就帮你处理了这些细节。
但如果你用C语言,而且不允许用第三方库呢?
UT8和中文编码
以前的计算机只支持英文字符的时候,全部字符加符号也不过一两百个,ascii解决不了的,扩展一下表就可以了。
后来遇到了中文等其他语言,ascii就没辙了。动不动几万个字符,这咋整?
于是就有了UTF8编码。
比如"帅小伙",用UTF8编码是
帅小伙
这是三个双字节的编码。
后台想把“帅小伙”通过json传给我,我在MQL里拿到的就是下面这串字符,
\u5E05\u5C0F\u4F19
这里面的\u表示转义字符是utf编码。
现在问题来了,只有基本的C语言类型和API,没有第三方库的情况下,怎么正确显示中文?
char转short,再位移一下
拿 \u5E05
来说,
在MQL里,拿到是是一个 char[],
char[0] == '\';
char[1] == 'u';
char[2] == '5';
char[3] == 'E';
char[4] == '0';
char[5] == '5';
简化处理流程,我们把转义字符忽略掉,只考虑后面四个char。
于是我们的问题变成要解决
5E05 -> 帅
众所周知,UTF8编码是1-4字节长度,对于常见中文占两字节。所以我们需要一个short类型来存最终结果。
最后我们想要拿到的是一个short变量ch,
ushort ch = '帅';
从二进制角度把ch输出的话,会得到
0101 1110 0000 0101
刚好对应 5E05 !
于是问题就进一步简化了,我们只需要把 char[] 按位移,然后按半字节做或处理就行。
最后的障碍
实际上 char[] 的字符本身还是编码,比如 ‘5’,它是一个ascii编码,int值是53.
但这个问题不是很难,
只要把ascii编码按偏移量取值,就可以得到int值了。
因为’0’-‘9’,在ascii表里是连续的,从 48 到 57,只要把 char 减去48,就可以得到对应的int值。
到这里问题就解决了,
ushort ch = 0101 1110 0000 0101;
char[0] 是 ‘5’,转到ch的高位是 0101,取高位的代码
(char[0] << 12) & 0xF000
剩下的12bit按同样的方式取就行。
有什么用?
现在的高级语言基本都会帮开发者处理掉这些编码细节问题,开发中基本不需要手动去解决编码转换的操作。
这种虽然方便了开发者,但也导致了很多开发者到现在都不知道基本类型占几个字节。
有个故事讲的是一个流水线遇到机器运行问题,请了一个老工程师。
老工程师收了五万块,去到流水线,用粉笔在机器上画了一条线,说,把这里拆开,里面的线圈减掉5匝。
工人不服,划一条线为什么要给这么多。
老工程师讲,划一条线,值五毛钱,但知道在哪里划线,值5万块。