To be honest. There are many problems in your code. Biggest issue is that you have 0 lines of comments in your code. With that it is only hardly readable.
Then, the input data has a clumsy format, which makes it hard to read. Basically, quantities and price should follow immediately after then product name, and better put in a separate line. Anyway. It is like ist is.
So, and then you have dynamic data, That means, you do not know in advance, how big your arrays will must be. In the below example I use new
and raw pointers for owned memory. This you should normally never do and use always a std::vector
instead. But ok, lets see.
The data model, so, how and with with structure you want to model the data is also and always essential. Please see my approch in the example below.
The additional difficulty while parsing the input line is the change between formatted and unformatted input. Special care must be taken to handle the semicolon correctly.
Then, you would add member functions in your structs to handle the work. Objects should be encapsulated.
All this I will not do in the below example solution. I stick more or less to your programming style, but add a lot of comments.
Please see:
#include <iostream>
#include <fstream>
#include <string>
struct Product{
std::string productName{};
unsigned int quantity{};
double price{};
double totalPriceProduct{};
};
struct Order {
std::string customerName{};
Product *products{};
unsigned int numberOfProducts;
double totalPriceOrder{};
};
struct OrderDatabase {
Order* orders{};
unsigned int numberOfOrders{};
double totalPrice;
};
int main() {
// Here we will store all our orders
OrderDatabase orderDatabase{};
// Open the source file
std::ifstream fileStream{ "r:\\Fruit Order.txt" };
// Count, how many orders we do have in the file
std::string lineWithOrder{};
// Read all lines from file an throw content away. Count the lines
while (std::getline(fileStream, lineWithOrder) and not lineWithOrder.empty())
++orderDatabase.numberOfOrders;
// Reset stream. Clear eof bit and reset file pointer
fileStream.clear();
fileStream.seekg(0, std::ios::beg); // back to the start!
// Now dynamically allocate memory for our orders
orderDatabase.orders = new Order[orderDatabase.numberOfOrders];
char dummy; // for reading the semicolon and throw it away
// Read all data
unsigned int orderIndex{};
// -----------------------------------------------------------------------------------------------------------
// Read all data
do {
// Read customer name
std::getline(fileStream, orderDatabase.orders[orderIndex].customerName, ';');
// How many products are in this order?
fileStream >> orderDatabase.orders[orderIndex].numberOfProducts >> dummy;
// Allocate memory for new products
orderDatabase.orders[orderIndex].products = new Product[orderDatabase.orders[orderIndex].numberOfProducts];
// Read product names
for (unsigned int productIndex = 0; productIndex < orderDatabase.orders[orderIndex].numberOfProducts; ++productIndex) {
std::getline(fileStream, orderDatabase.orders[orderIndex].products[productIndex].productName, ';');
}
// Read product quantity and price
for (unsigned int productIndex = 0; productIndex < orderDatabase.orders[orderIndex].numberOfProducts; ++productIndex) {
fileStream >> orderDatabase.orders[orderIndex].products[productIndex].quantity >> dummy;
fileStream >> orderDatabase.orders[orderIndex].products[productIndex].price >> dummy;
// Calculate total price for product
orderDatabase.orders[orderIndex].products[productIndex].totalPriceProduct = orderDatabase.orders[orderIndex].products[productIndex].quantity * orderDatabase.orders[orderIndex].products[productIndex].price;
// Accumulate prices in oder
orderDatabase.orders[orderIndex].totalPriceOrder += orderDatabase.orders[orderIndex].products[productIndex].totalPriceProduct;
// Accumulate overall total price
orderDatabase.totalPrice += orderDatabase.orders[orderIndex].products[productIndex].totalPriceProduct;;
}
// Read next line
++orderIndex;
} while (fileStream and orderIndex < orderDatabase.numberOfOrders);
// -------------------------------------------------------------------------------------------------------
// Show result to user
std::cout << "\n\nThere are " << orderDatabase.numberOfOrders << " orders in the database. Details:\n";
for (orderIndex = 0; orderIndex < orderDatabase.numberOfOrders; ++orderIndex) {
// Show one order
std::cout << "\nOrder number " << orderIndex + 1 << " for Customer: " << orderDatabase.orders[orderIndex].customerName << " with " << orderDatabase.orders[orderIndex].numberOfProducts << " products\n";
// Show product in this order
for (unsigned int productIndex = 0; productIndex < orderDatabase.orders[orderIndex].numberOfProducts; ++productIndex) {
std::cout << "Product: " << orderDatabase.orders[orderIndex].products[productIndex].productName << " \t Quantity: " << orderDatabase.orders[orderIndex].products[productIndex].quantity << " \tPrice: " <<
orderDatabase.orders[orderIndex].products[productIndex].price << " \t Total --> " << orderDatabase.orders[orderIndex].products[productIndex].totalPriceProduct << '\n';
}
// Show total order price
std::cout << "\nTotal price of this order: " << orderDatabase.orders[orderIndex].totalPriceOrder << '\n';
}
// Show overall total
std::cout << "\n\nTotal price overall: " << orderDatabase.totalPrice << '\n';
// Free memory
for (orderIndex = 0; orderIndex < orderDatabase.numberOfOrders; ++orderIndex) {
delete[] orderDatabase.orders[orderIndex].products;
}
delete[] orderDatabase.orders;
return 0;
}
As said. I would not do it that way, but use more advance C++ techniques.
But please try this in the beginning.