没有人会对以下内容感兴趣,因为这个答案是在提出问题 5 天后给出的。
此外,OP 是 C++ 的新手,wnd 不会理解它。但由于这个问题是用 C++ 标记的,而其他答案都非常 C 风格,我想在这里展示一个更现代的 C++ 解决方案,它采用面向对象的方法。
而且,我到处都看到滥用std::getline 来分割字符串,这令人难以置信,因为存在用于分割字符串的专用函数。 std::getline 的预期用途是从流中“获取一行”。顾名思义。人们摆弄这个函数并搜索分隔符等,但在我看来,我们不应该这样做。
大约 10 年来,我们有一个专门的、特殊的 C++ 功能,用于将字符串拆分为标记,专门为此目的而设计。 std::sregex_token_iterator。而且因为我们有这样一个专用功能,所以我们应该简单地使用它。
它背后的想法是迭代器的概念。在 C++ 中,我们有许多容器并且总是迭代器,以迭代这些容器中的相似元素。而一个字符串,具有相似的元素(标记),用分隔符分隔,也可以看作是这样的容器。并且使用std::sregex:token_iterator,我们可以遍历字符串的元素/令牌/子字符串,有效地将其拆分。
这个迭代器非常强大,你可以用它做更多花哨的事情。但这对这里来说太过分了。重要的是,将字符串拆分为标记是一行。例如,使用范围构造函数来迭代标记的变量定义。例如:
// The delimiter
const std::regex delimiter{ "," };
// Test data
std::string csvData("d1,d2,d3,d4,d5");
// Split the string
std::vector<std::string> tokens(std::sregex_token_iterator(csvData.begin(), csvData.end(), delimiter, -1), {});
Ant 因为是一个迭代器,所以你可以将它与许多算法一起使用。你真的应该stduy并使用它。对于所有那些非常关心效率的人,请注意,在 90% 的情况下,只会解析几行。没问题。
那么,接下来。我们有一种面向对象的语言。因此,让我们使用它并为您的数据定义一个类,使用您提到的数据成员,以及额外的函数或运算符,以对该数据成员进行操作。只有类应该知道它的内部。在外面,我们想使用它,而不知道实现。
在下面的示例中,extractor 和 iserter 将被覆盖,以启用流兼容的 IO 操作。在提取器中,我们还将使用regex 功能,并将准确检查输入字符串是否符合我们的预期。为此,我们使用std::regex,它准确定义了 CSV 字符串中的数据模式。然后,如果我们找到匹配项,我们就可以使用该数据。因此,这不仅是拆分字符串,而且是输入验证。这个函数是:std::regex_match。
而且,如果您查看main,读取和解析所有 CSV 数据是单行的。数据输出也一样。
请看:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <regex>
const std::regex re{R"(^\s*?(\b\w+)\s*?,\s*?(\d+\.\d+)\s*?,\s*?(\d+)\s*?$)"};
// Proxy class for easy input and output
struct MyData {
std::string name{};
double price{};
long quantity{};
// Overwrite extractor operator for easier input
friend std::istream& operator >> (std::istream& is, MyData& md) {
// Read a complete line from your CSV file
if (std::string line{}; std::getline(is, line)) {
// Check, if the input string matches to pour expectation, so split and validate
if (std::smatch match{}; regex_match(line, match, re)) {
// Match is perfect. Assign the values to our internal data members
md.name = match[1]; md.price = std::stod(match[2]); md.quantity = std::stol(match[3]);
}
else // No match. Set everything to default
md = {};
}
return is;
}
// Simple output of our data members
friend std::ostream& operator << (std::ostream& os, const MyData& md) {
return os << "Name: " << md.name << "\t\tPrice: " << md.price << "\tQuantity: " << md.quantity;
}
};
int main() {
// Open the csv File and check, if it could be opened and everything is ok
if (std::ifstream csvStream("r:\\antiquelist.txt"); csvStream) {
// Read and parse the complete source file
std::vector myData(std::istream_iterator<MyData>(csvStream), {});
// Show complete result to user
std::copy(myData.begin(), myData.end(), std::ostream_iterator<MyData>(std::cout, "\n"));
}
else {
std::cerr << "\n*** Error: Could not open input file\n";
}
return 0;
}
请查看here,以更好地了解正则表达式
很遗憾没有人会读到这个。 . .