You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ CSV读取异常:逐元素更新而非逐行导致对角线输出

CSV读取代码异常:仅读取每行首个元素即跳行

我有一段用于CSV读取的C++代码,本应按照输入逐行读取数据,但实际仅读取每行的首个元素就跳至下一行,导致输出呈对角线形式。nextUpdate本应在读完一整行后执行读取下一行的操作,但当前逻辑异常。

完整代码

头文件 csvreader.h

#ifndef CSVREADER_H
#define CSVREADER_H

#include <string>
#include <map>
#include <fstream>
#include <sstream>
#include <iostream>
#include <chrono>
#include <time.h>

class CsvReader
{
public:
    CsvReader(std::string fileName)
    : m_nextLine(""), m_nextUpdate(0), m_infile(fileName.c_str()), m_lineLoaded(false)
    {
        m_start = std::chrono::steady_clock::now();
        if(m_infile.is_open())
        {
            /* read type and name from file */
            std::string type, name;
            std::getline(m_infile, type); // type
            std::getline(m_infile, name); // name

            std::stringstream ssname(name);
            std::stringstream sstype(type);
            m_type.clear();
            while (!ssname.eof())
            {
                std::string n,t;
                std::getline(ssname, n, ',');
                if(!sstype.eof())
                {
                    std::getline(sstype, t, ',');
                }
                m_type.insert(std::pair<std::string, std::string>(n,t));
            }
            std::getline(m_infile, m_nextLine); // first
            m_nextUpdate = (m_nextLine.length() > 0) ? atoi(m_nextLine.c_str()) : INT_MAX;
        }
    }

    int getInt(const char * varName);
    char getChar(const char * varName);
    float getFloat(const char * varName);

private:
    void update(void);

    std::ifstream m_infile;
    std::string m_nextLine;
    std::chrono::steady_clock::time_point m_start;
    int m_nextUpdate;
    std::map<std::string, std::string> m_line;
    std::map<std::string, std::string> m_type;
    bool m_lineLoaded; // 标记当前行是否已加载完成
};

#endif

主函数代码

#include "csvreader.h"
#include <Windows.h>
using namespace std;

void printData(CsvReader *csvReader)
{
    cout << csvReader->getInt("var1") << '\t'
        << csvReader->getInt("var2") << '\t'
        << csvReader->getFloat("var3") << '\t'
        << csvReader->getFloat("var4") << '\t'
        << csvReader->getChar("var5") << '\t'
        << csvReader->getInt("var6") << endl;
}

int main()
{
    CsvReader *csvReader = new CsvReader("input.csv");
    Sleep(10);  cout <<  10 << '\t'; printData(csvReader);
    Sleep(210); cout <<  210 << '\t'; printData(csvReader);
    Sleep(20);  cout <<  20 << '\t'; printData(csvReader);
    Sleep(10);  cout <<  10 << '\t'; printData(csvReader);
    Sleep(510); cout << 210 << '\t'; printData(csvReader);
    Sleep(20);  cout <<  20 << '\t'; printData(csvReader);

    return 0;
}

实现文件 csvreader.cpp

#include "csvreader.h"

void CsvReader::update(void)
{
    std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
    long long elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_start).count();

    /* Read new values only if time is elapsed AND current line not loaded */
    if(elapsed >= m_nextUpdate && !m_lineLoaded)
    {
        if(m_nextLine.length() > 0)
        {
            /* parse this line elements */
            m_line.clear();
            std::stringstream ssline(m_nextLine);
            std::map<std::string, std::string>::iterator itr;
            for (itr = m_type.begin(); itr != m_type.end(); ++itr)
            {
                if(!ssline.eof())
                {
                    std::string element;
                    std::getline(ssline, element, ',');
                    m_line[itr->first] = element;
                }
                else
                {
                    std::cout << "Error: invalid number of elements" << '\n';
                }
            }

            /* set next timer value */
            std::getline(m_infile, m_nextLine);
            m_nextUpdate = (m_nextLine.length() > 0) ? atoi(m_nextLine.c_str()) : INT_MAX;
            
            // 更新时间起点,标记当前行已加载
            m_start = now;
            m_lineLoaded = true;
        }
    }
}

int CsvReader::getInt(const char * varName)
{
    update();
    return atoi(m_line[std::string(varName)].c_str());
}

char CsvReader::getChar(const char * varName)
{
    update();
    return m_line[std::string(varName)].c_str()[0];
}

float CsvReader::getFloat(const char * varName)
{
    update();
    return atof(m_line[std::string(varName)].c_str());
}

问题根源与修复说明

问题核心

每个getXXX()方法都会调用update(),而原代码中只要时间满足条件,每次调用update()都会重新读取新行并解析。printData()一次会调用6次get方法,导致每次调用都切换到下一行,最终只能取到每行的第一个元素。

修复措施

  1. 添加m_lineLoaded标志位,标记当前行是否已加载完成,避免同一行被重复解析。
  2. 处理完当前行后更新m_start为当前时间,确保下一次时间判断基于新的起点,只有当再次达到下一个时间阈值时才会加载新行。

内容的提问来源于stack exchange,提问作者Delwin Mathew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 03:21:01