微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Visual Studio 2019 C++ 项目中的特殊字符并使用它们执行 CMD 命令

如何解决Visual Studio 2019 C++ 项目中的特殊字符并使用它们执行 CMD 命令

首先,我只想在控制台中使用波罗的海字符并使用它们执行 CMD 命令,但问题始于认/标准控制台 C++ 应用程序。

#include <iostream>
int main() {
    string output = "āāāčččēēēē";

    cout << output << endl;
}

早些时候,我在堆栈上提出了这个问题 - How to use UTF8 characters in DEFAULT c++ project OR when using mysql connector for c++ in visual studio 2019 (Latin7_general_ci to UTF-8)?

我在测试中发现:如果我将 UTF8 字符串转换latin1 字符串,然后输出或打印十六进制值,我会在控制台中输出一些特殊字符。例如 -

**char s2[256] = "\xc3\xa9";**  printed is outputted as "ķ" THAT MEANS I need to convert strings into correct HEX values when it is needed,and some people might kNow how it might be one.

但是我的代码逻辑需要一个功能来使用这个字符串在 CMD 中使用 cp。所以稍后转换为字符串,我的 CMD 无法工作,尽管 CMD 必须执行的 cp 命令的输出似乎在控制台中正确显示

// Example program
#include <iostream>
#include <string>
#include <fstream>
#include <sstream> 
#include <stdexcept>
#include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 
#include <cstring> 
#include <cstdint>
#include <locale> 
#include <cstdlib>





int GetUtf8CharacterLength(unsigned char utf8Char)
{
    if (utf8Char < 0x80) return 1;
    else if ((utf8Char & 0x20) == 0) return 2;
    else if ((utf8Char & 0x10) == 0) return 3;
    else if ((utf8Char & 0x08) == 0) return 4;
    else if ((utf8Char & 0x04) == 0) return 5;

    return 6;
}

char Utf8Tolatin1Character(char* s,int* readindex)
{
    int len = GetUtf8CharacterLength(static_cast<unsigned char>(s[*readindex]));
    if (len == 1)
    {
        char c = s[*readindex];
        (*readindex)++;

        return c;
    }

    unsigned int v = (s[*readindex] & (0xff >> (len + 1))) << ((len - 1) * 6);
    (*readindex)++;
    for (len--; len > 0; len--)
    {
        v |= (static_cast<unsigned char>(s[*readindex]) - 0x80) << ((len - 1) * 6);
        (*readindex)++;
    }

    return (v > 0xff) ? 0 : (char)v;
}

// overwrites s in place
char* Utf8Tolatin1String(char* s)
{
    for (int readindex = 0,writeIndex = 0; ; writeIndex++)
    {
        if (s[readindex] == 0)
        {
            s[writeIndex] = 0;
            break;
        }

        char c = Utf8Tolatin1Character(s,&readindex);
        if (c == 0)
        {
            c = '_';
        }

        s[writeIndex] = c;
    }

    return s;
}


int main()
{
    char s2[256] = "\xc3\xa9";
    Utf8Tolatin1String(s2);

    std::cout << s2 << std::endl;

    std::string locations2 = ("C:\\Users\\Janis\\Desktop\\TEST2\\");
    std::string txtt = (".txt");
    std::string copy2 = ("copy /-y ");

    std::string space = " ";
    std::string PACIENTI2 = "C:\\PACIENTI\\";




    std::string element = copy2 + locations2 + s2 + txtt;

    std::string cmd = element + space + PACIENTI2 + s2 + txtt;

    std::cout << cmd << std::endl;

    FILE* pipe = _popen(cmd.c_str(),"r");
}

所以我们需要真正解决两个问题,从已经给定的创建十六进制字符串,并确保它在 CMD 中工作。

解决方法

我在您的另一个问题中为您提供了很好的答案。这里有类似的东西。

您的程序可以使用 UTF-8 编码,控制台可以使用不同的编码,但是您必须向标准库提示每个数据源的编码方式。
当然,如果目标编码不包括不支持特定字符,则必须进行一些后备(参见底部示例)。

必须明确定义编码才能使一切正常工作的 4 个方面:

  • 您的源代码。 VS 使用系统区域设置来使用编码,这很糟糕。强制 VS 和所有编辑器使用通用编码,最好选择 UTF-8。最好通知编译器源是如何编码的:cl /source-charset:utf-8 .....
  • 您的可执行文件。您必须定义应该在最终可执行文件中编码哪种编码字符串文字。这里的 UTF-8 也是最好的:cl .... /execution-charset:utf-8 .....
  • 当您运行应用程序时,您必须通知标准库您的字符串文字定义为何种编码或使用了程序逻辑中的何种编码。因此,在执行开始时您的代码中的某处需要这样的东西:
std::locale::global(std::locale{".utf-8"});
  • 最后你必须指示流它应该使用什么样的编码。因此,对于 std::coutstd::cin,您应该设置系统默认的语言环境:
    auto streamLocale = std::locale{""}; 
    // this impacts date/time/floating point formats,so you may want tweak it just to use sepecyfic encoding and use C-loclae for formating
    std::cout.imbue(streamLocale);
    std::cin.imbue(streamLocale);

在此之后,一切都应该可以正常工作,而无需明确进行转换的代码。
由于有 4 个地方会出错,这就是人们遇到问题的原因,而且互联网上到处都是“黑客”解决方案。

这里有一些测试程序来证明我的观点:

#include <iostream>
#include <locale>
#include <exception>
#include <string>

void setupLocale(int argc,const char *argv[])
{
    std::locale def{""};
    std::locale::global(argc > 1 ? std::locale{argv[1]} : def);
    auto streamLocale = argc > 2 ? std::locale{argv[2]} : def;
    std::cout.imbue(streamLocale);
    std::cin.imbue(streamLocale);
}

void printSeparator()
{
    std::cout << "---------\n";
}

void printTestStuff()
{
    std::cout << "Wester Europe: āāāčččēēēēßÞÖöñÅÃ\n";
    std::cout << "Central Europe: ąĄÓóŁłĘężćźŰűÝýĂă\n";
    std::cout << "China: 字集碼是把字符集中的字符编码为指定集合中某一对象\n";
    std::cout << "Korean: 줄여서 인코딩은 사용자가 입력한\n";
}

int main(int argc,const char *argv[]) {
    try{
        setupLocale(argc,argv);
        printSeparator();
        printTestStuff();
        printSeparator();
    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
    }
}

以及它是如何构建和运行以证明其有效的(注意这也涵盖了使用无效编码的情况):

C:\Users\User\Downloads>cl /source-charset:utf-8 /execution-charset:utf-8 /EHsc encodings.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

encodings.cpp
Microsoft (R) Incremental Linker Version 14.28.29336.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:encodings.exe
encodings.obj

C:\Users\User\Downloads>chcp
Active code page: 437

C:\Users\User\Downloads>encodings.exe
---------
Wester Europe: Ä?Ä?Ä?Ä?Ä?Ä?Ä"Ä"Ä"Ä"AYAzA-AA±A.Aƒ
Central Europe: Ä.Ä,A"A3Å?Å,Ä~ÄTżÄ╪źŰűA?A½Ä,ă
China: å--é>+碼æ~_æSSå--ç¬▌é>+ä,-çs,å--ç¬▌ç¼-ç ?ä,ºæO╪årsé>+å?^ä,-æY?ä,?å_1象
Korean: ì,ì-¬ì,o ì?,ì½"ë"cì?? ì,¬ìscìz?ê°? ìz.ë ¥ío
---------

C:\Users\User\Downloads>encodings.exe .65001
---------
Wester Europe: aaaccceeeeß_ÖöñÅA
Central Europe: aAOóLlEezczUuYyAa
China: ????????????????????????
Korean: ??? ???? ???? ???
---------

C:\Users\User\Downloads>encodings.exe .65001 .437
---------
Wester Europe: aaaccceeeeß_ÖöñÅA
Central Europe: aAOóLlEezczUuYyAa
China: ????????????????????????
Korean: ??? ???? ???? ???
---------

C:\Users\User\Downloads>encodings.exe .65001 .1250
---------
Wester Europe: aaaccceeeeß_ÖöñÅA
Central Europe: aAOóLlEezczUuYyAa
China: ????????????????????????
Korean: ??? ???? ???? ???
---------

C:\Users\User\Downloads>chcp 1250
Active code page: 1250

C:\Users\User\Downloads>encodings.exe .65001 .1250
---------
Wester Europe: aaačččeeeeß?ÖönAA
Central Europe: ąĄÓóŁłĘężćźŰűÝýĂă
China: ????????????????????????
Korean: ??? ???? ???? ???
---------

C:\Users\User\Downloads>chcp 65001
Active code page: 65001

C:\Users\User\Downloads>encodings.exe
---------
Wester Europe: ÄÄÄÄÄÄēēēēßÞÖöñÅÃ
Central Europe: ąĄÓóÅłĘężćźŰűÃýĂă
China: 字集碼是把字符集中的字符编ç ä¸ºæŒ‡å®šé›†åˆä¸­æŸä¸€å¯¹è±¡
Korean: 줄여서 ì¸ì½”ë”©ì€ ì‚¬ìš©ìžê°€ 입력한
---------

C:\Users\User\Downloads>encodings.exe .65001
---------
Wester Europe: āāāčččēēēēßÞÖöñÅÃ
Central Europe: ąĄÓóŁłĘężćźŰűÝýĂă
China: 字集碼是把字符集中的字符编码为指定集合中某一对象
Korean: 줄여서 인코딩은 사용자가 입력한
---------

C:\Users\User\Downloads>encodings.exe .65001 .65001
---------
Wester Europe: āāāčččēēēēßÞÖöñÅÃ
Central Europe: ąĄÓóŁłĘężćźŰűÝýĂă
China: 字集碼是把字符集中的字符编码为指定集合中某一对象
Korean: 줄여서 인코딩은 사용자가 입력한
---------

C:\Users\User\Downloads>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?