我一直在尝试创建一个可以用作收银机的简单程序。假定从文件中读取以下内容: - 名称, - 价钱, -告诉它是水果还是蔬菜, -卡路里
我认为最好的方法是检测标识号(类似于条形码),然后读取4行并在“:”定界符后得到4个字符串。
这是我创建的txt文件:
# Vegetables #
Iden number : 11
Name : Carrot
Price [zl/kg] : 2
Group : Vegetable
Calories [cal/100 g] : 33
Nr Iden : 12
Name : Tomato
Price [zl/kg] : 4
Group : Vegetable
Calories [cal/100 g] : 20
Iden number : 13
Name : Cucumber
Price [zl/kg] : 1
Group : Vegetable
Calories [cal/100 g] : 14
# Fruits #
Iden number : 21
Name : Apple
Price [zl/kg] : 2
Group : Fruit
Calories [cal/100 g] : 52
Iden number : 22
Name : Orange
Price [zl/kg] : 4
Group : Fruit
Calories [cal/100 g] : 47
Iden number : 23
Name : Kiwi
Price [zl/kg] : 1
Group : Fruit
Calories [cal/100 g] : 60
这里是检测分隔符并忽略空行或以“#”开头的代码的代码。但我不知道在检测到identy_number之后如何只读取以下4行。
int main()
{
string line;
ifstream plik ("baza_danych_produktow.txt");
if (plik.is_open())
{
while ( getline (plik,line) )
{
line.erase(std::remove_if(line.begin(), line.end(), ::isspace),line.end());
if(line[0] == '#' || line.empty()){ // if line starts with # or is empty - ignore
continue;
}
auto delimiterPos = line.find(":");
auto name = line.substr(0, delimiterPos);
std::string value = line.substr(delimiterPos + 1);
cout << value;
cout << endl;
}
plik.close();
}
else cout << "Unable to open file";
return 0;
}
我的代码在不为空或不以“#”开头的文件的每一行中显示“:”定界符之后的每个字符串。
以下是输出:
11
Carrot
2
Vegetable
33
12
Tomato
4
Vegetable
20
13
Cucumber
1
Vegetable
13
21
Apple
2
Fruit
52
22
Orange
4
Fruit
47
23
Kiwi
1
Fruit
60
您能帮我吗,例如 input:11 的输出看起来像这样吗?
Carrot
2
Vegetable
33
最诚挚的问候。
答案 0 :(得分:0)
如果找到ID,您可以在while循环内调用另一个getline 4次
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
using std::cout;
using std::endl;
using std::stringstream;
using std::string;
int main()
{
string id = "22";
string line;
stringstream plik ("# Vegetables #\n\nIden number : 11\nName : Carrot\nPrice [zl/kg] : 2\nGroup : Vegetable\nCalories [cal/100 g] : 33\n\nNr Iden : 12\nName : Tomato\nPrice [zl/kg] : 4\nGroup : Vegetable\nCalories [cal/100 g] : 20\n\nIden number : 13\nName : Cucumber\nPrice [zl/kg] : 1\nGroup : Vegetable\nCalories [cal/100 g] : 14\n\n# Fruits #\n\nIden number : 21\nName : Apple\nPrice [zl/kg] : 2\nGroup : Fruit\nCalories [cal/100 g] : 52\n\nIden number : 22\nName : Orange\nPrice [zl/kg] : 4\nGroup : Fruit\nCalories [cal/100 g] : 47\n\nIden number : 23\nName : Kiwi\nPrice [zl/kg] : 1\nGroup : Fruit\nCalories [cal/100 g] : 60\n");
if (/*plik.is_open()*/ true) {
while (getline(plik, line)) {
line.erase(std::remove_if(line.begin(), line.end(), ::isspace), line.end());
if (line[0] == '#' || line.empty()) { // if line starts with # or is empty - ignore
continue;
}
auto delimiterPos = line.find(":");
auto name = line.substr(0, delimiterPos);
if (name == "Idennumber") {
std::string currentId = line.substr(delimiterPos + 1);
for (unsigned short i{ 0 }; i < 4; ++i) {
getline(plik, line);
auto delimiterPos = line.find(":");
auto name = line.substr(0, delimiterPos);
std::string value = line.substr(delimiterPos + 1);
if (currentId == id) {
cout << value << '\n';
}
}
}
}
/*plik.close();*/
}
else
cout << "Unable to open file";
return 0;
}
答案 1 :(得分:0)
我想向您介绍一个更“现代”的C ++解决方案。使用算法和“更多” OO(面向对象)方法。
在我看来,面向对象设计的关键是将数据及其方法放到一个对象(类)中。
例如,一个产品具有一些数据成员。它具有如何读写数据的智慧,并且有责任。因此,任何第三方都不应从此类对象中读取/写入数据。
如果您采用这种方法,则可以使用fileStream >> product;
阅读完整的产品记录。而已。一个班轮。而且更直观
与打印相同。就像通过std::cout << number;
打印数字一样,对产品也是如此。为什么不写std::cout << product
。
在下面的代码中,我添加了一个功能测试,正是该测试。这非常简单。
此外,我还读取了内存中的所有数据,为您提供了更全面的示例。该代码包含大量注释,应该易于理解。
请参阅:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <string>
#include <sstream>
#include <iomanip>
// This is a file. It is the same as reading a file from a disk
std::istringstream inputFile{ R"(# Vegetables #
Iden number : 11
Name : Carrot
Price[zl / kg] : 2
Group : Vegetable
Calories[cal / 100 g] : 33
Nr Iden : 12
Name : Tomato
Price[zl / kg] : 4
Group : Vegetable
Calories[cal / 100 g] : 20
Iden number : 13
Name : Cucumber
Price[zl / kg] : 1
Group : Vegetable
Calories[cal / 100 g] : 14
# Fruits #
Iden number : 21
Name : Apple
Price[zl / kg] : 2
Group : Fruit
Calories[cal / 100 g] : 52
Iden number : 22
Name : Orange
Price[zl / kg] : 4
Group : Fruit
Calories[cal / 100 g] : 47
Iden number : 23
Name : Kiwi
Price[zl / kg] : 1
Group : Fruit
Calories[cal / 100 g] : 60
)" };
// Create Some shorter name
constexpr std::string::size_type NOK = std::string::npos;
// This is, what we are searching for in the product data
const std::vector<std::string_view> identifier{ "Name","Price","Group","Calories" };
// Our product class. Keep data and methods together in on object
struct Product
{
Product() : data(identifier.size()) {}
// The iden number
std::string iden{};
// All data. Since verything is treated as a string, we will put this in a vector
std::vector<std::string> data;
// This class knows how to read and write its data. This is the know how of this objec´t. It belongs to here.
// Overwrite extractor operator >>
friend std::istream& operator >> (std::istream& is, Product& p);
// Overwrite inserter operator <<
friend std::ostream& operator << (std::ostream& os, const Product& p);
};
// The inserter operator for a product. Very simple. Print all available data
std::ostream& operator << (std::ostream& os, const Product& p)
{
// First the iden number
os << "\n" << std::left << std::setw(15) << "Iden number" << p.iden << '\n';
// And then all data
for (size_t index = 0U; (index < p.data.size()) && (index < identifier.size()); ++index)
os << std::setw(15) << identifier[index] << p.data[index] << '\n';
return os;
}
// The products extractor operator. That is a little bit more complex
std::istream& operator >> (std::istream& is, Product& p)
{
std::string line{};
size_t pos{ 0 }; size_t index{ 0 };
// We will read lines from the input stream, until we are done
while (getline(is, line)) {
// First, search for a string that conatins "Iden" or "Nr Iden"
pos = line.find(':'); // Look if the line has a double colon
// Search
if (((line.find("Iden") == 0) || line.find("Nr Iden" == 0)) && (pos != NOK)) {
// Ok, we found a line that contains "Iden" or "Nr Iden"
std::istringstream iss(line.substr(pos + 1));
iss >> p.iden; // Read the data into our product internal variable
// Now continue to read lines. Either 4 lines or until some read error
while ((index < identifier.size()) && getline(is, line)) {
// Check the position of the double colon
pos = line.find(":");
// And now find the expected search string given in identifier{ "Name","Price","Group","Calories" }
if ((line.find(identifier[index]) != NOK) && (pos != NOK)) {
// if Foundm, then put the data into our product internal data variable
std::istringstream iss(line.substr(pos + 1));
iss >> p.data[index];
}
++index;
}
break; // After we read on product, we will stop reading lines
}
// else, if the line does not match our expected value, then ignore it and read next line
}
return is;
}
void test()
{
Product product{};
// What we want to show
std::string searchID{ "22" };
// Read all products
while (inputFile >> product) {
// If we found what we were looking for
if (product.iden == searchID) {
// Then show result
std::cout << product << "\n\n";
break; // stop further reading
}
}
}
int main()
{
test(); inputFile.seekg(0);;
// Define variable that holds all products
// Define variable with range constructor that will copy the data from somewhere begin to somewhere end
// Somewhere begin is the istream iterator that reads from the beginning of the file
// Somewhere end is the istream iterator that reads until end of file
// Since the extractor operator >> of the product has been overwritten, the istream_iteratir will call this operatir with the istream
std::vector<Product> products{std::istream_iterator<Product>(inputFile), std::istream_iterator<Product>() };
// For debug purposes. Print all products
std::cout << "\nThis is the complete list of products that we have read from the file:\n\n";
// We use the copy operator. Meaning, we copy the range products.begin/products.end to somewhere
// The somewhere is the std ostream_iterator which will simple print the given data to std::cout
// Since we have overwritten the inserter operator << of the product, this operator will be called for each element in the products list
std::copy(products.begin(), products.end(), std::ostream_iterator<Product>(std::cout, "\n"));
// Ask the user, what product he wants to see
std::cout << "\n\nWhat product do you want to see? Enter Iden number: ";
std::string searchString{};
// Get that value from the user
std::cin >> searchString;
// And now find it in the list of products. All product in the products list will be check. Their iden will be compared with the search string
std::vector<Product>::iterator iter = std::find_if(products.begin(), products.end(), [&searchString](const Product & p) { return p.iden == searchString; });
// If we could find something
if (iter != products.end())
// Show some text and the data. We show the data be inserting *iter in the std::cout stream. The will call the product inserter operator
std::cout << "\n\nFound product with Iden (" << searchString << ") -->\n" << *iter << '\n';
else
// Nothing could be found
std::cout << "\n\nProduct with Iden (" << searchString << ") NOT found in proct list\n";
return 0;
}
请查看“测试”功能的简单程度。而且,如果您对产品进行更改,它仍然可以使用。因为功能隐藏在产品所属的产品中。它被封装了。