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方法,导致每次调用都切换到下一行,最终只能取到每行的第一个元素。
修复措施
- 添加
m_lineLoaded标志位,标记当前行是否已加载完成,避免同一行被重复解析。 - 处理完当前行后更新
m_start为当前时间,确保下一次时间判断基于新的起点,只有当再次达到下一个时间阈值时才会加载新行。
内容的提问来源于stack exchange,提问作者Delwin Mathew
相关产品推荐
相关产品推荐

