我写了一个代码来搜索文件中的字符串。实际上,我将数据像这样放在我的文件中:
[alex booth,15,1
(全名,带有空格,年龄,id)。
将数据保存在文件中没有任何问题,我在该文件中搜索字符串时遇到了很大的问题。
例如,我想在文件中搜索“ alex Booth”之类的名称,但是尽管搜索可用,但似乎找不到该单词。我猜想用空格保存名称存在问题,但是我不知道该如何解决。实际上,我不知道该如何搜索其中包含空格的名称。
这是我的代码:
using namespace std;
struct product{
string name;
int price, id;
};
int main() {
product myProduct;
ofstream productList("product.csv", ios::app | ios::out);
getline(cin, myProduct.name);
cin >> myProduct.price;
cin >> myProduct.id;
productList << myProduct.name << ',' << myProduct.price << ',' << myProduct.id << endl;
productList.close();
cout << "----" << endl;
system("pause");
ifstream checkList("product.csv");
string dummy;
string check;
cin.ignore();
getline(cin, check);
while (!checkList.eof()) {
while (checkList >> myProduct.name >> myProduct.price >> myProduct.id) {
if (myProduct.name == check) {
cout << "Product Name: " << myProduct.name <<
" - Product's Price: " << myProduct.price <<
" - ID Number: " << myProduct.id << endl;
}
}
}
checkList.close();
return 0;
}
while
loop is wrong。尝试其他类似方法:
while
或者:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <limits>
#include <cstdlib>
using namespace std;
struct product{
string name;
int price, id;
};
int main() {
product myProduct;
cout << "Enter product name: ";
getline(cin, myProduct.name);
cout << "Enter product price: ";
cin >> myProduct.price;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Enter product id: ";
cin >> myProduct.id;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
ofstream productList("product.csv", ios::app);
productList << myProduct.name << ',' << myProduct.price << ',' << myProduct.id << std::endl;
productList.close();
cout << "----" << endl;
system("pause");
cin.ignore();
cout << "Enter name to look for: ";
string check;
getline(cin, check);
ifstream checkList("product.csv");
string line;
char comma;
while (getline(checkList, line)) {
istringstream iss(line);
if (getline(iss, myProduct.name, ',') && (iss >> myProduct.price >> comma >> myProduct.id) && (comma == ',')) {
if (myProduct.name == check) {
cout << "Product Name: " << myProduct.name <<
" - Product's Price: " << myProduct.price <<
" - ID Number: " << myProduct.id << endl;
}
}
}
checkList.close();
return 0;
}
因此,在您的示例中,“ id”,“ name”和“ price”是对象的属性,从#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <limits>
#include <cstdlib>
using namespace std;
struct product{
string name;
int price, id;
};
istream& getInt(istream &in, int &value)
{
string str;
if (getline(in, str, ',')) {
try {
value = stoi(str);
}
catch (...) {
in.setstate(ios::failbit);
}
}
return in;
}
int main() {
product myProduct;
cout << "Enter product name: ";
getline(cin, myProduct.name);
cout << "Enter product price: ";
cin >> myProduct.price;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Enter product id: ";
cin >> myProduct.id;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
ofstream productList("product.csv", ios::app);
productList << myProduct.name << ',' << myProduct.price << ',' << myProduct.id << std::endl;
productList.close();
cout << "----" << endl;
system("pause");
cin.ignore();
cout << "Enter name to look for: ";
string check;
getline(cin, check);
ifstream checkList("product.csv");
string line;
while (getline(checkList, line)) {
istringstream iss(line);
if (getline(iss, myProduct.name, ',') && getInt(iss, myProduct.price) && getInt(iss, myProduct.id)) {
if (myProduct.name == check) {
cout << "Product Name: " << myProduct.name <<
" - Product's Price: " << myProduct.price <<
" - ID Number: " << myProduct.id << endl;
}
}
}
checkList.close();
return 0;
}
中提取它们或将其插入到std::istream
中应仅由该对象知道并由它。
因此,我们创建一个类/结构,将3个数据成员(即“ id”,“ name”和“ price”)定义为std::ostream
std :: stringunsigned long",
double''。然后,我们覆盖提取器运算符(>>)和插入器运算符。提取器运算符有点棘手,因为我们首先读取完整的一行,然后将其拆分为令牌。
在C ++中,您的文件结构称为CSV(逗号分隔值)。并且,阅读此内容是一项标准任务。首先,阅读整行,然后使用给定的定界符提取该字符串的标记。 “拆分”也称为“令牌化”,并且C ++为此目的具有专用功能:and the “price” as a
。这个东西是一个迭代器。用于遍历字符串,因此称为“ sregex”。开始部分定义了我们将在什么输入范围上进行操作,然后在输入字符串中有一个std :: regex表示应该匹配的内容或不应该匹配的内容。匹配策略的类型由最后一个参数给出。
std::sregex_token_iterator
我们可以使用此迭代器将令牌存储在std :: vector中。 std :: vector具有范围构造器,该构造器将2个迭代器作为参数,并将第一个迭代器和第二个迭代器之间的数据复制到std :: vector。声明
1 --> give me the stuff that I defined in the regex and
-1 --> give me that what is NOT matched based on the regex.
将变量“令牌”定义为std::vector tokens(std::sregex_token_iterator(line.begin(), line.end(), re, -1), {});
,并使用std::vector
的所谓范围构造函数。请注意:我正在使用C ++ 17,并且可以不使用模板参数定义std::vector
。编译器可以从给定的函数参数中推导出自变量。此功能称为CTAD(“类模板参数推导”)。
此外,您可以看到我没有显式使用“ end()”-迭代器。此迭代器将从空括号括起来的初始值设定项列表中以正确的类型构造,因为由于
std::vector
构造函数需要将其推导为与第一个参数的类型相同。然后,在读取该行并将其拆分为令牌之后,我们检查是否有3个令牌,然后将结果存储为“ id”,“ name”和“ price”。因此,总体而言,这是一个非常简单的操作。
在
std::vector
中,我放置了一些示例驱动程序代码。例如,您可以看到我用一个简单的[]将新产品存储到文件中
main
声明。读取完整的CSV文件并解析它,是通过简单的单行代码完成的:
productFile << product;
仅使用
std::vector productList(std::istream_iterator<Product>(productFile), {});
查找元素。
请参见下面的完整示例:(我添加了许多注释和空行以使代码更易读。)
std::find_if
我希望能给您一个想法,如何解决这个问题。当然,还有许多其他解决方案。 。 。