c++ - 在字段中用逗号解析 csv

标签 c++ parsing csv

我正在尝试使用具有以下数据的 csv 创建一个对象

Alonso,Fernando,21,31,29,2,Racing
Dhoni,Mahendra Singh,22,30,4,26,Cricket
Wade,Dwyane,23,29.9,18.9,11,Basketball
Anthony,Carmelo,24,29.4,21.4,8,Basketball
Klitschko,Wladimir,25,28,24,4,Boxing
Manning,Peyton,26,27.1,15.1,12,Football
Stoudemire,Amar'e,27,26.7,21.7,5,Basketball
"Earnhardt, Jr.",Dale,28,25.9,14.9,11,Racing
Howard,Dwight,29,25.5,20.5,5,Basketball
Lee,Cliff,30,25.3,25.1,0.2,Baseball
Mauer,Joe,31,24.8,23,1.8,Baseball
Cabrera,Miguel,32,24.6,22.6,2,Baseball
Greinke,Zack,33,24.5,24.4,50,Baseball
Sharapova,Maria,34,24.4,2.4,22,Tennis
Jeter,Derek,35,24.3,15.3,9,Baseball

我正在使用以下代码来解析它:

void AthleteDatabase::createDatabase(void)
{
    ifstream inFile(INPUT_FILE.c_str());
    string inputString;

    if(!inFile)
    {
        cout << "Error opening file for input: " << INPUT_FILE << endl;
    }
    else
    {
        getline(inFile, inputString);
        while(inFile)
        {
            istringstream s(inputString);
            string field;
            string athleteArray[7];
            int counter = 0;
            while(getline(s, field, ','))
            {
                athleteArray[counter] = field;
                counter++;
            }

            string lastName = athleteArray[0];
            string firstName = athleteArray[1];
            int rank = atoi(athleteArray[2].c_str());
            float totalEarnings = strtof(athleteArray[3].c_str(), NULL);
            float salary = strtof(athleteArray[4].c_str(), NULL);
            float endorsements = strtof(athleteArray[5].c_str(), NULL);
            string sport = athleteArray[6];

            Athlete anAthlete(lastName, firstName, rank,
                              totalEarnings, salary, endorsements, sport);
            athleteDatabaseBST.add(anAthlete);
            display(anAthlete);
            getline(inFile, inputString);
        }
        inFile.close();
    }
}

我的代码在线中断:

"Earnhardt, Jr.",Dale,28,25.9,14.9,11,Racing

显然是因为引号。有没有更好的方法来处理这个问题?我对 C++ 还是很陌生,所以非常感谢任何帮助。

最佳答案

我建议只使用合适的 CSV 解析器。您可以在 this earlier question 的答案中找到一些内容, 或者只是 search for one on Google .

如果您坚持自己动手,最简单的方法可能是从基础开始,将其设计为一次处理一个输入字符的有限状态机。对于单字符前瞻,您基本上需要两种状态:“读取正常输入”和“读取带引号的字符串”。如果你不想使用前瞻,你可以用更多的状态来做到这一点,例如像这样:

  • 初始状态:如果下一个字符是引号,切换到状态quoted field;其他行为就好像处于状态未加引号的字段

  • unquoted field:如果下一个字符是EOF,结束解析;否则,如果是换行符,则开始一个新行并切换到初始状态;否则,如果是分隔符(逗号),则在同一行开始一个新字段并切换到初始状态;否则将字符追加到当前字段并保持状态 unquoted field。 (可选地,如果字符是引号,则发出解析错误信号。)

  • quoted field:如果下一个字符是EOF,表示解析错误;否则,如果是引号,则切换到状态结束引号;否则将字符追加到当前字段并保持状态 quoted field

  • end quote:如果下一个字符是引号,将其附加到当前字段并返回状态quoted field;否则,如果它是逗号或换行符或 EOF,则表现得就像在状态 unquoted field 中一样; else 信号解析错误。

(这适用于“传统”CSV,如 RFC 4180 中所述,其中引用字段中的引号通过加倍转义。添加对反斜杠转义的支持,这在 CSV 格式的一些相当常见的变体中使用, 留作练习。它需要一个或两个以上状态,具体取决于您是否要支持带引号或不带引号的字符串或两者中的反斜杠,以及是否要同时支持传统和反斜杠转义。)

在高级脚本语言中,这种逐个字符的迭代确实效率低下,但由于您正在编写 C++,所以它需要快速运行的只是一些像样的 I/O 缓冲和一个合理的高效的字符串追加操作。

关于c++ - 在字段中用逗号解析 csv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29446705/

相关文章:

php - 解析爬虫的 url

c++ - read int per line c++ 错误需要解决方案

c++ - 硬件级别的 'for loop' 中发生了什么?内存是自动分配的吗? (C++)

php - PHP解析/语法错误;以及如何解决它们

java - 如何用Java从文本文件中提取数据并写入CSV文件

c++ - 从派生类调用时推断 'this' 指针类型?

linux - Linux环境下Oracle External Tables字段解析

Java:无法从 String 转换为 int

python - 如何将 csv 字符串转换为 pandas 中的列表?

python - XML 到 CSV 格式