C ++读取CSV文件直到行尾,找不到最后一个单元格
C++ Read CSV file until end of line, not finding last cell
我正在读取一个 CSV 文件,其中包含不同长度的列,看起来像这样:
1,2,3,4\n
5,,7,\n
9,,11,\n
我的问题是我希望它将以下内容读入向量中:
1 2 3 4
5 nan 7 nan
9 nan 11 nan
所以我正在使用以下内容:
int i = 0;
while(getline(data,line)) // Read each line
{
std::stringstream lineStream(line);
while(getline(lineStream,cell,',')) // Read each cell in the line
{
if(cell.empty()) // If ,, use NaN
{
strains.push_back(std::numeric_limits<double>::quiet_NaN());
}
else
{
strains.push_back(std::stod(cell));
}
}
}
问题是它跳过了行尾的空单元格,所以它输出:
1 2 3 4
5 nan 7 9
nan 11
你们都知道我如何计算最后一列,即使它是空的吗?我正在考虑 "if row length < 4, add empty cell" 之类的东西。谢谢
EDIT 我用最后一件事修复了它,我放了一个计数器来计算有多少个单元格,然后在内部循环的末尾我添加了:
if(j<cols) // If counted less than 12 columns,
{
strains.push_back(std::numeric_limits<double>::quiet_NaN());
}
如果您有任何建议或更正,我愿意接受,谢谢。
这是另一种解析来自字符串流的输入的方法。我制作了一个示例程序来说明另一种使用 getline
的方法。我本来可以做一个完整的功能,但是你原来的问题没有,所以我加了很多评论。
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <array>
#include <algorithm>
#include <functional>
int main()
{
// Test cases.
std::istringstream lineStream("1,2,3,4\n");
//std::istringstream lineStream("5,,7,\n");
//std::istringstream lineStream("9,,11,\n");
// Vector of 10-char arrays
std::vector<std::array<char, 10>> output;
// "NaN" array, instead of recreating it each iteration.
std::array<char, 10> NaN = { 'N', 'a', 'N'};
// Split lineStream on 10 characters, or comma, in cell variable.
// NOTE : Here, I assume you have maximum 10 characters field, but adjust
// this based on your specific case. Also, this will capture the "\n", so
// we'll need to handle that.
for (std::array<char, 10> cell; lineStream.getline(&cell[0], 10, ','); )
{
// Replace the \n character with an end of string.
// NOTE : this is basic character filtering, and doesn't handle
// tabulations, or windows-style endline, so it should probably be
// more robust.
std::replace(cell.begin(), cell.end(), '\n', '[=10=]');
// Check if cell is empty, and assign it "NaN"
if((cell[0] == '[=10=]') || (cell.empty()))
cell = NaN;
// Push the cell back to the output vector.
output.push_back(cell);
}
// Display the output vector
for (auto& a : output)
{
std::cout << &a[0] << " ";
}
我正在读取一个 CSV 文件,其中包含不同长度的列,看起来像这样:
1,2,3,4\n
5,,7,\n
9,,11,\n
我的问题是我希望它将以下内容读入向量中:
1 2 3 4
5 nan 7 nan
9 nan 11 nan
所以我正在使用以下内容:
int i = 0;
while(getline(data,line)) // Read each line
{
std::stringstream lineStream(line);
while(getline(lineStream,cell,',')) // Read each cell in the line
{
if(cell.empty()) // If ,, use NaN
{
strains.push_back(std::numeric_limits<double>::quiet_NaN());
}
else
{
strains.push_back(std::stod(cell));
}
}
}
问题是它跳过了行尾的空单元格,所以它输出:
1 2 3 4
5 nan 7 9
nan 11
你们都知道我如何计算最后一列,即使它是空的吗?我正在考虑 "if row length < 4, add empty cell" 之类的东西。谢谢
EDIT 我用最后一件事修复了它,我放了一个计数器来计算有多少个单元格,然后在内部循环的末尾我添加了:
if(j<cols) // If counted less than 12 columns,
{
strains.push_back(std::numeric_limits<double>::quiet_NaN());
}
如果您有任何建议或更正,我愿意接受,谢谢。
这是另一种解析来自字符串流的输入的方法。我制作了一个示例程序来说明另一种使用 getline
的方法。我本来可以做一个完整的功能,但是你原来的问题没有,所以我加了很多评论。
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <array>
#include <algorithm>
#include <functional>
int main()
{
// Test cases.
std::istringstream lineStream("1,2,3,4\n");
//std::istringstream lineStream("5,,7,\n");
//std::istringstream lineStream("9,,11,\n");
// Vector of 10-char arrays
std::vector<std::array<char, 10>> output;
// "NaN" array, instead of recreating it each iteration.
std::array<char, 10> NaN = { 'N', 'a', 'N'};
// Split lineStream on 10 characters, or comma, in cell variable.
// NOTE : Here, I assume you have maximum 10 characters field, but adjust
// this based on your specific case. Also, this will capture the "\n", so
// we'll need to handle that.
for (std::array<char, 10> cell; lineStream.getline(&cell[0], 10, ','); )
{
// Replace the \n character with an end of string.
// NOTE : this is basic character filtering, and doesn't handle
// tabulations, or windows-style endline, so it should probably be
// more robust.
std::replace(cell.begin(), cell.end(), '\n', '[=10=]');
// Check if cell is empty, and assign it "NaN"
if((cell[0] == '[=10=]') || (cell.empty()))
cell = NaN;
// Push the cell back to the output vector.
output.push_back(cell);
}
// Display the output vector
for (auto& a : output)
{
std::cout << &a[0] << " ";
}