无法忽略文本文件流中的转义字符并存储在 C++ 中的 wchar_t [ ] 中

Unable to ignore the escape characters from a text file stream & store in a wchar_t [ ] in C++

我正在尝试使用 C++ 从文本文件中读取数据并将每行的字符串存储到 wchar_t [] 或 LPCWSTR 中。 (这 2 种数据类型是我正在处理的应用程序的约束。这就是为什么我必须将数据存储在这些数据类型中的原因)

.txt文件中的数据格式,例如:

abc\def\ghi 10
jkl\mnopq\rstq 20
aqq\sdsds\qc 30

我正在尝试逐行读取数据并将每一行保存为映射的键值对,其中键是LPCWSTR类型或wchar_t[]类型&值是int类型 提取 int 没有问题,但问题出在读取字符串

这是我的代码:

#include<iostream>

#include<fstream>
#include<windows.h>
#include<cstdlib>

using namespace std;

int main()
{
    wchar_t test1[260];
    const char* s = "Hello\ABC\DEF";
    mbstowcs(test1, s, strlen(s));
    wcout<<test1<<endl;


    wchar_t gr[260];
    string gr_temp;
    int percentage;

    ifstream ifs;
    ifs.open("data.txt", ifstream::in);
    if (ifs.is_open()) {
        while (ifs >> gr_temp >> percentage){

            const char* source = gr_temp.c_str();
            mbstowcs(gr, source, strlen(source));

            wcout<<gr<<L" ";
            cout<<percentage<<endl;

        }
        ifs.close();
    }

    return 0;
}

但是,它给出了以下输出:

Hello\ABC\DEFa
abc\def\ghi 10
jkl\mnopq\rstq 20
aqq\sdsds\qc 30
  1. 我不明白为什么那个小'a'突然出现在输出的第一行

  2. 我希望代码自动处理那些双斜杠,即我希望输出为:

    Hello\ABC\DEF
    abc\def\ghi 10
    jkl\mnopq\rstq 20
    aqq\sdsds\qc 30
    
  3. 如果我可以在 .txt 文件中写入不带双斜杠的条目,并且它们会在不检查任何转义序列的情况下自动处理,那就更好了。但是,由于第 1 点中的问题。 1) 上面有,所以我不确定是否可能

  4. 即使在 while 循环的第一行添加 cout<<gr_temp<<endl;,即使这样也会输出带有双反斜杠的字符串。

我错过了什么或做错了什么?

更新:

此外,当我在每个 while 循环末尾使用语句 m1[gr] = percentage; 将这些键值对添加到 std::map<LPCWSTR,int> m1 时,然后使用 print 语句,它只显示一个元素在地图上。

我的更新代码是:

#include<iostream>

#include<fstream>
#include<windows.h>
#include<cstdlib>
#include<map>

using namespace std;

std::unordered_map<LPCWSTR, int>        m1;

int main()
{
    wchar_t test1[260];
    const char* s = "Hello\ABC\DEF";
    mbstowcs(test1, s, strlen(s));
    wcout<<test1<<endl;


    wchar_t gr[260];
    string gr_temp;
    int percentage;

    ifstream ifs;
    ifs.open("data.txt", ifstream::in);
    if (ifs.is_open()) {
        while (ifs >> gr_temp >> percentage){

            const char* source = gr_temp.c_str();
            mbstowcs(gr, source, strlen(source));
            
            m1[gr] = percentage;

        }
        ifs.close();
    }

    for (auto i = m1.begin(); i != m1.end(); i++) {
        wcout<< i->first << L" ";
        cout<< i->second << endl;
    }

    return 0;
}

此代码仅在地图中添加 1 个元素,这是最近添加的元素。

我编辑了代码以使用 unordered_map,但仍然是同样的问题。

我进一步尝试打印地图的 size() 。在这两种情况下,地图 m1 的大小都显示为 1。

Miles Budnek 已经说明了您的问题。

如果您查看函数的文档 (http://www.cplusplus.com/reference/cstdlib/mbstowcs/),您会发现第三个参数并不期望转换为 wchar_t 的字节数,而是最大值您指向的缓冲区可以容纳的字符数。

它会在找到 \0 后停止(这恰好是 strlen 也在寻找的)。

因此,只需将您的第一个 mbstowcs 调用的第三个参数替换为 260(或 sizeof(test1)/sizeof(wchar_t),您就可以很好地解决这个问题 'a'。

如前所述,读取文件时没有 'escape parameters'。 这些仅存在于源代码中,表示您无法键入的 ASCII 代码。 (https://www.asciitable.com/)

\n 例如表示 'new line' 0x0A 的代码。

所以转义文件中的反斜杠是不必要的,可以跳过。

如果您知道您的输入文件将包含 'double backslashes' 并且需要 'unescape' 它们,您可以查看 std::string 函数 'find' 和 'replace'.

找到"\\"(连续两个反斜杠)并替换为"\"

针对您更新后的问题(这基本上是另一个问题)的回应: 问题是您为地图选择的键。 每张地图,无论是否无序,都需要唯一的密钥,并且在您的场景中,您一直使用相同的密钥。

LPCWSTR 扩展为 'Pointer to Wide Char String',因此虽然您可能认为您使用 'abc\def\ghi' 作为键,但实际上您使用的是 &gr[0],它在所有迭代中保持不变.

作为一个额外的结果,一旦程序离开 gr 的范围,它的内容就变得无效并且访问映射(它维护指针但不维护内容),将访问容易崩溃的释放内存你的程序。

虽然这样的解决方案很简单:您需要使用内容作为键,而不是指针,例如使用像 std::wstring.

这样的容器对象