3

我正在做将 python 代码转换为 C++ 的项目,以获得更好的性能。该python项目名称是Advanced EAST,现在,我在.csv文件中获得了nms函数的输入数据,如下所示:

"[ 5.9358170e-04  5.2773970e-01  5.0061589e-01 -1.3098677e+00
 -2.7747922e+00  1.5079222e+00 -3.4586751e+00]","[ 3.8175487e-05  6.3440394e-01  7.0218205e-01 -1.5393494e+00
 -5.1545496e+00  4.2795391e+00 -3.4941311e+00]","[ 4.6003381e-05  5.9677261e-01  6.6983813e-01 -1.6515008e+00
 -5.1606908e+00  5.2009044e+00 -3.0518508e+00]","[ 5.5172237e-05  5.8421570e-01  5.9929764e-01 -1.8425952e+00
 -5.2444854e+00  4.5013981e+00 -2.7876694e+00]","[ 5.2929961e-05  5.4777789e-01  6.4851379e-01 -1.3151239e+00
 -5.1559062e+00  5.2229333e+00 -2.4008298e+00]","[ 8.0250458e-05  6.1284608e-01  6.1014801e-01 -1.8556541e+00
 -5.0002270e+00  5.2796564e+00 -2.2154367e+00]","[ 8.1256607e-05  6.1321974e-01  5.9887391e-01 -2.2241254e+00
 -4.7920742e+00  5.4237065e+00 -2.2534993e+00]

一个单位是 7 个数字,但是在前四个数字之后有一个 '\n',我想把这个 csv 文件读入我的 C++ 项目,这样我就可以用 C++ 做数学工作,让它更快。

using namespace std;

void read_csv(const string &filename)
{
//File pointer
fstream fin;
//open an existing file
fin.open(filename, ios::in);

vector<vector<vector<double>>> predict;

string line;
while (getline(fin, line))
{
    std::istringstream sin(line);
    vector<double> preds;
    double pred;
    while (getline(sin, pred, ']'))
    {
        preds.push_back(preds);
    }

}

}

现在......我的代码 emmmmmm 无法正常工作,我完全不知道这个......请帮助我将 csv 数据读入我的代码中。谢谢

4

2 回答 2

8

不幸的是,在 C++ 中解析字符串(以及相应的文件)非常繁琐。

我强烈建议使用一个库,最好是一个只有标题的库,比如这个

如果你坚持自己写,也许你可以从这个 StackOverflow 问题中获得一些灵感,关于如何在 C++ 中解析通用 CSV 文件。

于 2019-07-11T11:42:37.763 回答
0

你可以看看getdelim(',', fin, line)

但另一个问题是那些引号,除非你 /know/ 文件总是以这种方式完全格式化,否则会变得很困难。

我过去使用过的一个不完美的技巧,如果第一个字符是引号,那么逗号之前的最后一个字符也必须是匹配的引号,而不是转义。

如果它不是引号,那么getdelim()还有更多,但 getdelim 的自动分配功能意味着您必须使用另一个缓冲区。在 C++ 中,我最终得到一个包含所有getdelim结果的向量,然后需要将这些结果连接起来以生成最终字符串:

std::vector<char*> gotLine;
gotLine.push_back(malloc(2));
*gotLine.back() = fgetch();
gotLine.back()[1] = 0;
bool gotquote = *gotLine.back() == '"'; // perhaps different classes of quote
if (*gotLine.back() != ',')
 for(;;)
 {
  char* gotSub= nullptr;
  gotSub=getdelim(',');
  gotLine.push_back(gotSub);
  if (!gotquote) break;
  auto subLen = strlen(gotSub);
  if (subLen>1 && *(gotSub-1)=='"') // again different classes of quote
    if (sublen==2 || *(gotSub-2)!='\\') // needs to be a while loop
       break;
 }

然后将所有这些字符串段连接在一起。

请注意,getdelim 支持空字节。如果您希望内容中有空字节,而不是由字符序列表示,\000或者\@您需要存储 getdelim 返回的实际长度,并使用 memcpy 连接它们。

哦,如果你允许 utf-8 扩展引号,它会变得非常混乱!

这不包括的情况是一个以\\"or结尾的字符串\\\\"。理想情况下,您需要同时计算前导反斜杠的数量,如果计数是偶数,则接受引号。

请注意,这会留下取消转义引用内容的问题,即将任何内容转换为\""和等。同时丢弃封闭的引号。\\\

最后,如果您需要处理完全任意的内容,库可能会更容易。但是,如果内容是“已知的”,你可以不用。

于 2019-07-11T11:18:18.783 回答