- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我无法正确解析 CSV 文件。数据行中的某些值可以为空,并且 my code当我在任何值行中有空白条目时无法正常工作。如果没有空白条目,程序将返回以下结果:
Symbol: GOOG
Name: Googl Inc.
Price: $570.25
High Today: $570.25
Low Today: $560.35
Symbol: APPL
Name: Apple Inc.
Price: $123.25
High Today: $124.25
Low Today: $125.35
如果我使用以下 CSV 字符串运行相同的程序,程序将停止并出现断言错误。这是由于解析器跳过了 adjacent ,, delimiters,因此数据行中的列数与标题中的列数不匹配。
std::stringstream ifs(
"Symbol,Name,Price,High Today,Low Today\n"
"GOOG,Googl Inc.,$570.25 ,$570.25 ,$560.35\n"
"APPL,Apple Inc.,$123.25 ,,$125.35\n");
这是我的代码:
#include <iostream>
#include <vector>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <cassert>
#include <locale>
// This ctype facet classifies commas and endlines as whitespace
struct csv_whitespace : std::ctype<char> {
static const mask* make_table() {
// make a copy of the "C" locale table
static std::vector<mask> v(classic_table(), classic_table() + table_size);
v[','] |= space; // comma will be classified as whitespace
v[' '] &= ~space; // space will not be classified as whitespace
return &v[0];
}
csv_whitespace(std::size_t refs = 0)
: ctype(make_table(), false, refs)
{}
};
static int row_end = std::ios_base::xalloc();
std::istream& record(std::istream& is) {
while (std::isspace(is.peek(), is.getloc())) {
int c(is.peek());
is.ignore();
if (c == '\n') {
is.iword(row_end) = 1;
is.setstate(std::ios_base::failbit);
}
}
return is;
}
template<class Iter1, class Iter2, class Function>
void for_each_binary_range(Iter1 first1, Iter1 last1,
Iter2 first2, Iter2 last2, Function f)
{
assert(std::distance(first1, last1) <=
std::distance(first2, last2));
while (first1 != last1) {
f(*first1++, *first2++);
}
}
int main(int argc, char *argv[])
{
std::stringstream ifs(
"Symbol,Name,Price,High Today,Low Today\n"
"GOOG,Googl Inc.,$570.25 ,$570.25 ,$560.35\n"
"APPL,Apple Inc.,$123.25 ,$124.25 ,$125.35\n");
//std::ifstream ifs("c:\\temp\\csvfile.csv", std::ios::in);
std::vector<std::string> keys, values;
ifs.imbue(std::locale(ifs.getloc(), new csv_whitespace));
bool bHeaderProcessed = false;
for (std::string item;;) {
if (ifs >> record >> item) {
if (!bHeaderProcessed) {
keys.push_back(item);
} else {
values.push_back(item);
}
} else if (ifs.eof()) {
// catch case where last line does not have trailing \n
if (!values.empty()) {
for_each_binary_range(std::begin(keys), std::end(keys),
std::begin(values), std::end(values),
[&](std::string const& key, std::string const& value) {
std::cout << key << ": " << value << std::endl;
std::cout << std::endl;
});
values.clear();
}
break;
} else if (ifs.iword(row_end)) {
// reset eol flag & clear stream state
ifs.iword(row_end) = 0;
// clear the fail-bit so we can stream more values
ifs.clear();
bHeaderProcessed = true;
if (!values.empty()) {
for_each_binary_range(std::begin(keys), std::end(keys),
std::begin(values), std::end(values),
[&](std::string const& key, std::string const& value) {
std::cout << key << ": " << value << std::endl;
});
values.clear();
std::cout << std::endl;
}
} else {
break;
}
}
return -1;
}
我基于我的原始代码记录得很好 here .不幸的是,问题的答案(通过现场演示 here )似乎无法处理有多行的情况,我无法让它处理标记为空的情况。
我的版本将每一行打印为一系列名称/值,它还处理有多行或一行不以新行结尾的情况。
逻辑在上面的链接答案中描述得很好
有人可以指出如何处理我在 csv 的数据行中有相邻分隔符的情况。
最佳答案
您的问题在于您期望如何解析数据与实际解析数据的方式。双“,,”被完全忽略,没有被推到值 vector 上。这意味着您的 values 数组的大小将短一个或多个。断言失败,因为断言键的大小 <= 值的大小。如果这发生在键 vector 中有双“,,”的地方,你就没问题。
std::stringstream ifs(
"Symbol,Name,,High Today,Low Today\n"
"GOOG,Googl Inc.,$570.25 ,$570.25 ,$560.35\n"
"APPL,Apple Inc.,$123.25 ,$124.25 ,$125.35\n");
尝试使用上面的方法并观察输出。
一个简单但不优雅的解决方案是在每个“,”之间插入一个空格,以便程序将其拾取。有很多更好的解决方案,但这应该能让你继续前进。
编辑:感谢您的理解。
关于c++ - 使用 C++ iostreams 解析具有空值的 CSV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34032154/
在 C++ 中包含头文件时,和...有什么区别 在 <> 标志中包含 .h 部分与不包括 .h 部分? #include 与 #include 将标题名称用双引号括起来还是用 符号括起来? #inc
最近我在阅读 Accelerated C++ 并从练习答案中发现了这个有趣的代码。这是完整的代码, #include "stdafx.h" #include "4_4.h" #include usi
我正在开发一个需要能够在标准 C++ 编译器和准标准编译器上编译的实用程序。代码可以而且将会被扔到几乎任何现有的 C++ 编译器上。 我正在寻找一种可靠且可移植地确定目标编译器是否支持带或不带 .h
如果有一个文件 foo.cpp,那么它通常有一个关联的头文件 foo.h,其中包含 foo.cpp 中定义的函数的所有声明。这样,所有其他使用 foo.cpp 中的函数的文件都可以只包含 foo.h
iostream 和 iostream.h 有什么区别? 最佳答案 iostream.h 已被提供它的编译器弃用,iostream 是 C++ 标准的一部分。 为了明确说明,当前 C++ 标准 (IN
我知道关于 之间的区别的问题和 之前有人问过。阅读这些答案后,我发现了以下差异 当然iostream.h已弃用,新的符合标准的编译器不支持它 iostream.h不包含 std 中的所有内容命名
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Difference between iostream and iostream.h 我的教授说了以下内容:
我需要构建一些我在办公室电脑上得到的旧代码,它有 gcc 4.4.5安装。我编辑了代码(删除 .h 或添加类似 的内容)以使它们保持最新,以便它们可以由 gcc 4.4.5 编译.但是,在看似成功编
我在学习C++的时候遇到了一个问题,在编译的时候遇到了错误。 详情如下: 最佳答案 您似乎没有在 MinGW 中安装 C++ 支持。如果您使用手动安装路径,请下载 gcc-c++ dev、dll 和
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: What is the difference between #include and #include
对于我当前的任务,我需要能够读/写(主要是基于文件的)比特流。虽然如果用标准 C/C++ 编码,这或多或少是一项微不足道的任务,但我喜欢通过重载和使用更通用的方法重写代码标准的 STL iostrea
这个问题在这里已经有了答案: Difference between iostream and iostream.h (3 个答案) 关闭 9 年前。 有什么区别 #include 和 #inclu
我正在尝试为 linux/MacOS 转换一个用 C++14 编写的应用程序。它使用 boost::filesystem,但不用于某些 iostream 操作。例如: boost::filesyste
示例: namespace boostio = boost::iostreams; boostio::stream memStream(arr); while (!memStream.eof())
我编写了以下简单的 C++ 程序: #include using namespace std; int main() { cout ^~~~~~~~~~ 1 error
我想在我的代码中将流公开为它们的标准等价物,以消除用户对 boost::iostreams 的依赖性.如果有必要,当然想有效地执行此操作而无需创建拷贝。我考虑过只设置 std::istream的缓冲区
#include in header files and #include only in cpp files 被认为是最佳实践。我正在尝试将大量 #include 从 header 移动到现有
#include #include #include #include using namespace std; int main() { int ival; while(ci
假设我得到一个 stringbuf,其中包含一些必须删除的特定字符序列的内容: std::stringbuf string_buff; std::iostream io_stream (&string
我有一个包含如下记录的文件 123 Tag 现在是所有好人都来帮忙的时候了 总是有一个数字和一些标签,后面跟着一系列单词。我想将数字提取为整数,将标记提取为字符串,将句子提取为字符串。我已经使用 ge
我是一名优秀的程序员,十分优秀!