Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 将std::string从一个区域设置转换为另一个区域设置_C++_String_Character Encoding_Localization_Locale - Fatal编程技术网

C++ 将std::string从一个区域设置转换为另一个区域设置

C++ 将std::string从一个区域设置转换为另一个区域设置,c++,string,character-encoding,localization,locale,C++,String,Character Encoding,Localization,Locale,如何将一种语言环境的std::string转换为另一种语言环境? 例如,我在std::localeru_RU.koi8r中有std::string,在std::localeru_RU.CP1251或std::localezh_CN.gb18030中创建std::string是的,codevt是解决此类问题的正确答案 codecvt简介: codecvt方面的目标是在内存中的内部表示变量和文件中的流表示数据之间提供流上字符编码转换: 要用于流的codecvt(如果有)在其区域设置中使用imbue定

如何将一种语言环境的std::string转换为另一种语言环境? 例如,我在std::localeru_RU.koi8r中有std::string,在std::localeru_RU.CP1251或std::localezh_CN.gb18030中创建std::string是的,codevt是解决此类问题的正确答案

codecvt简介: codecvt方面的目标是在内存中的内部表示变量和文件中的流表示数据之间提供流上字符编码转换:

要用于流的codecvt(如果有)在其区域设置中使用imbue定义。 从流中读取数据时,通过facet中的do_in函数将外部文件缓冲区转换为内部编码。 将数据写入流时,通过函数do_out将内部数据转换为存储在文件中的外部数据。 如果其中一种编码具有可变长度,则可以在单字节或多字节编码之间进行转换,无论是否需要状态。 我有一个非常简单的示例,可以在文件中的代码页850格式和内存中的iso8859-1之间进行转换。当然,您可以对其进行调整,以便对koi8r和CP1251执行相同的操作

原则如下:

由于我的示例中的字符集都是为char类型定义的,因此我创建了自己的字符集,如下所示:

class codecvt_cp850_iso8859 : public codecvt < char, char, mbstate_t > {
public:
    explicit codecvt_cp850_iso8859(size_t r=0) : codecvt(r) {}
protected:
    result do_in(mbstate_t &s, const char *from, const char *from_end, 
        const char*&from_next, 
        char *to, char*to_end, char*&to_next) const  // from cp850 to iso8859-1
    {
        result res=partial; 
        const char*p;
        for (p = from; p != from_end && to != to_end; p++)
            *to++ = ... /*  your stuff here, for example a conversion table */
        from_next = p;  // what's the next char to convert
        to_next = to;   // what's the next place to convert to
        if (p == from_end)
            res = p == from ? noconv : ok;
        return res; 
    }

    result do_out(mbstate_t &s, const char *from, const char *from_end, const char*&from_next,
        char *to, char*to_end, char*&to_next) const  // from iso8859-1 to cp850
    {
        result res = partial;
        const char*p;
        for (p = from; p != from_end && to != to_end; p++)
            *to++ = ... /* conversion in the other direction */ 
        from_next = p;  to_next = to;
        if (p == from_end)
                res = p == from ? noconv : ok;
        return res;
    }
    result do_unshift(mbstate_t &s, char*to, char*to_end, char*& to_next) const {
        to_next = to;    // Attention MSVC segfaults if this is missing ! 
        return ok;
    }
    int encoding() const {  return 1; } // fixed length for external representation
    bool do_always_noconv() const { return false; }
然后,您可以使用以下代码:

// read with conversion from cp850 in stream to iso in memory 
ifstream is850("test-cp850.txt");
is850.imbue(locale(is850.getloc(), new codecvt_cp850_iso8859 ())); // use our conversion
getline(is850, isotext); 
... 
// writing an iso string to a CP850 file: 
ofstream os850("test-cp850fromiso.txt");
os850.imbue(locale(os850.getloc(), new codecvt_cp850_iso8859()));
os850 << myisotext << endl;
...
请注意,标准库拥有所提供的codect的所有权,并在不再需要时对其进行中继

应用于字符串 最后,还可以使用codecvt在内存中的两种格式之间转换字符串

正如下面的注释所示,字符串本身没有区域设置

所以一种方法是使用stringstreams。另一种方法是直接使用mycodecvt::in、mycodecvt::out和mycodecvt::length


最后一种方法是使用。但是这一个不方便要求使用宽字符进行转换。

应该是您的朋友。请演示如何使用std::codecvt实现我的示例。很抱歉,我对它非常不熟悉。我只知道你可以用它进行字符集转换。如果您正在构建的标准库版本能够很好地支持codevt,那么codevt中的示例可能会对您有所帮助。到撰写本文时为止,GCC不支持Clang,我认为MSVC可能至少部分支持。您可能会发现使用重量级unicode库(如ICU或libiconv)更可靠、更便于移植。问题是在字符串上嵌入区域设置,这毫无意义,而不是流。@LightningRacisinObrit您当然是对的。所以我已经完成了答案。然而,我保留了后面的codecvt的介绍,因为我认为在不了解其初始设计目的的情况下应用它更困难。