zoukankan      html  css  js  c++  java
  • mingw控制台中文乱码

    乱码原因

    直接先用一段话讲乱码原因,看不懂老老实实就往下看吧

    其实我用Sublime或者VSCode等编辑器写代码出现的控制台中文乱码问题是编译器mingw输出的数据使用的是UTF-8编码,而控制台用了GBK编码来解析它

    其实编码只要统一,用UTF8或者GBK都行,但用了错误的编码去解析文件就会出错。

    问题来源

    如果我们写轻量代码(比如写算法题)也用VS之类的IDE,就太不划算了;虽然也有Codeblocks、Dev C++这样的小一点的IDE,但用起来还是可以发现让人很不爽的缺点。

    之前尝试用VS Code写C++代码,挺不错的,好看方便。但问题就是难配置,最大的问题是控制台中文乱码,我搞了好久都没搞好,今天终于解决了。

    在网上找到一段话是这么讲的:

    Windows(中文)默认的字符集是Windows-936(GBK),mingw的内部是GCC,而GCC编译器默认编译的时候是按照UTF-8解析和输出的,当未指定字符集时一律当作UTF-8进行处理,于是造成乱码。

    根据上边这段话,我有点灵感,但还是有疑问,见下。

    问题分析

    我电脑的CMD编码设置的是UTF-8,代码文件的编码也是UTF-8,如果mingw默认按UTF-8处理的话,可以看到这里用的编码全都是UTF-8,那应该不会出现乱码的。

    但我们确实看到了乱码啊!?

    当我去看我的注册表(见下图),发现代码链接、编译后生成的可执行文件有一个单独的注册表,这似乎说明我们运行的可执行文件并不是我们口中的那个CMD(按Win+R、cmd打开的那个CMD)。所以@roadwide整理的网上的改CMD编码啊什么的,可能搞错了问题的方向,不过也算一个方法吧,但似乎对我不适用。我之前也是搞错了方向。
    Console注册表.png

    如下图所示,我们运行的可执行文件,也就是那个弹出来的控制台,它的编码是GBK。现在我们应该知道乱码的原因了。

    可执行文件编码.png

    整个过程是这样的:

    1. 我们代码的编码是UTF-8
    2. 把UTF-8编码的代码交给mingw,它也默认当做UTF-8处理(目前为止这是正确的)
    3. mingw处理后生成的数据还是UTF-8编码(目前为止还是正确的)
    4. 把mingw处理后的数据(UTF-8编码)给cmd(目前为止也是正确的)
    5. cmd按GBK编码处理它(UTF-8),这时出现错误,所以出现乱码

    解决方案

    我们可以修改mingw的输出,让它在编译时使用GBK编码输出,然后再让CMD去显示。


    处理中文乱码只需要设置两个(核心只有一个)编译参数,即在tasks.jsontasks中的args中添加-fexec-charset=GBK-finput-charset=UTF-8,下边tasks.json中的第14、15行。


    这个解决方案中代码文件的编码是UTF-8,控制台编码是GBK,令mingw实现编码转换。

    下面的.vscode配置是我在网上找到的比较新的VS Code配置,可以作为参考,具体不做解释,想了解可以去看文章末的参考网址。

    tasks.json

    // 用来编译
    {
        // See https://go.microsoft.com/fwlink/?LinkId=733558
        // for the documentation about the tasks.json format
        "version": "2.0.0",
        "tasks": [{
            "label": "Build",   // 任务的名字叫Build(编译),注意是大小写区分的,等会在launch中调用这个名字
            "type": "shell",    // 任务执行的是shell命令
            "command": "g++",   // 命令是g++
            "args": [           //参数
                "-g",           // 调试
                
                //
                "-fexec-charset=GBK",   // 处理mingw中文编码问题
                "-finput-charset=UTF-8",// 处理mingw中文编码问题
                //
                
                "${file}", //当前文件路径,包括所在目录绝对路径和文件名
                "-o",      //对象名,不进行编译优化
                "${fileDirname}/exes/${fileBasenameNoExtension}.exe", //当前目录下exes文件夹下的exe文件,exe文件名为 当前文件名(去掉扩展名).exe
            ],
            // 所以以上部分,就是在shell中执行下面这行语句(以我E盘中一个main.cpp为例)
            // g++ -g  -fexec-charset=GBK -finput-charset=UTF-8 e:StudyProgrammingCodeAlgoPTABasicLevelCPPmain.cpp -o e:StudyProgrammingCodeAlgoPTABasicLevelCPP/exes/main.exe
            "group": {
                "kind": "build",
                "isDefault": true
                // 任务分组,tasks是个数组,意味着可以执行多个task
                // 在build组的任务们,可以通过在Command Palette(F1) 输入run build task来运行
                // 当然,如果任务分组是test,你就可以用run test task来运行 
            },
            "problemMatcher": [
                "$gcc" // 使用gcc捕获错误
            ],
        }]
    }
    

    -fexec-charset=GBK是令mingw按GBK编码生成exe文件。

    -finput-charset=UTF-8是令mingw按UTF-8编码处理。(经测试这个参数可以不设置)

    launch.json

    {
        "version": "0.2.0",
        "configurations": [
    
            {
            "name": "C++ Launch (GDB)", // 调试时程序员看到的名字
            "preLaunchTask": "Build",   // launch之前会运行的任务,这个名字一定要跟tasks.json中的任务名一致
            "type": "cppdbg",           // 经测试,不可删除
            "request": "launch",        // 经测试,不可删除
            "program": "${fileDirname}/exes/${fileBasenameNoExtension}.exe", //运行当前打开文件的目录下exes文件夹中名字和当前文件相同,但扩展名为exe的程序
            "args": [],                 // 运行程序是默认是没有参数的
            "stopAtEntry": false,       // 选为true则会在打开控制台后停滞,暂时不执行程序
            "cwd": "${workspaceFolder}",// 当前工作路径:当前文件所在的工作空间
            "environment": [],
            "externalConsole": true,    // 是否使用外部控制台,
            "MIMode": "gdb",
            "miDebuggerPath": "D:\WorkingSoftware\MinGW\bin\gdb.exe",   //调试器路径
            "setupCommands": [{
                "description": "Enable pretty-printing for gdb",
                "text": "-enable-pretty-printing",
                "ignoreFailures": true
            }]
        }]
    }
    // https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations
    // author: huihut
    // Available variables which can be used inside of strings.
    // ${workspaceRoot}: the root folder of the team        
    // ${file}: the current opened file                     
    // ${fileBasename}: the current opened file's basename 
    // ${fileDirname}: the current opened file's dirname    
    // ${fileExtname}: the current opened file's extension  
    // ${cwd}: the current working directory of the spawned process
    

    参考链接

    中文乱码参考1

    中文乱码参考2

    VS Code配置参考


    作者:@臭咸鱼

    转载请注明出处:https://www.cnblogs.com/chouxianyu/

    欢迎讨论和交流!


  • 相关阅读:
    将CSV格式的文件导入到数据中
    查询及删除数据重复记录的方法
    创建job
    存储过程动态创建表,以时间给表命名
    索引表空间
    sequence 作为序列插入值不是第一个
    2.类(对象)之间的关系
    1.类和对象
    angularJS1笔记-(1)-多控制器
    angularJS中$apply()方法详解
  • 原文地址:https://www.cnblogs.com/chouxianyu/p/11249810.html
Copyright © 2011-2022 走看看