Hi!

I've been having this problem recently:

I wrote this code which, practically, reads lines of text from a text file (e.g. Microsoft Notepad file) and stores them into a vector. Each line has three parts: the product code, the product amount and the product name. The user is offered, via option number 1, to buy a product with the corresponding code and a certain amount of it. When a user buys a product (and a certain amount of it below the offered one), the amount of a product remaining is stored in place of the previous amount of product.
But whenever I the program shows all the other products (besides the one that has been updated because of buying), the last product is missing (practically, a last vector element).
What could be causing this problem? I've tried all stuff, but can't remember anything anymore. After this, I have to write all the current vector elements over (overwrite) the lines in a text file that were previously taken into the program.
But that doesn't seem to be the problem, I can do that on my own, the only problem being the last vector element missing part.

Here's my code:

Main.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <conio.h>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iosfwd>
#include <algorithm>
#include <sstream>
using namespace std;

// Variables
	int code;
		string userCode;				// user specified product code
	int amount;
		int userAmount;				// user specified product amount
		string stringAmount;			// product amount as string
		int remainingAmount;
	string name;
	string line;
	vector<string> allLines;		// vector to contain text lines
		string currentLine;			// current line in element search
		int r;								// used for going through each vector element

// Buy a product
void buyProduct()
{
	cout << "\nPlease enter code of product you want to buy:\n";
	cin >> userCode;

	cout << "\nPlease enter amount of product you want to buy:\n";
	cin >> userAmount;

	cout << endl;

	// Going through the vector elements and looking for product code
	for (r = 0; r < allLines.size(); r++)
	{
		currentLine = allLines[r];

		// Find the entered code within a line
		if (string::npos != currentLine.find(userCode + " "))
		{
			cout << "\nFound at line number " << (r+1) << endl;

			// Extract the second word (product amount) from a line
			size_t pos1 = allLines[r].find(' ') + 1;
			size_t pos2 = allLines[r].find(' ', pos1);

			string secondString = allLines[r].substr(pos1, (pos2 - pos1));

			// Convert String to int
			amount = atoi(secondString.c_str());

			// Error message for wrongly entered product code
			if (!(string::npos != currentLine.find(userCode + " ")) && r == (allLines.size()-1))
			{
				cout << "\nProduct not found! Please try again." << endl;
				buyProduct();
			}

			// Subtract the entered amount from the available amount
			if (userAmount <= amount && userAmount >= 0)
			{
				remainingAmount = amount - userAmount;
				
				stringstream ss;					// create stream for converting int to String
				ss << remainingAmount;		
				stringAmount = ss.str();	   // put the contents of the stream (int) into String
			} 

			if (!(userAmount <= amount && userAmount >= 0))
			{
				cout << "\nProduct amount invalid! Please try again." << endl;
				buyProduct();
			}

			// Extract the third word (product name) from a line
			string thirdWord = allLines[r].substr(pos2 + 1);

			// Store the updated product back into the corresponding vector position
			allLines[r] = userCode + " " + stringAmount + " " + thirdWord;

			break;

		}

	}

	for (int t = 0; t < allLines.size() - 1; ++t)
	{
		cout << endl;
		cout << allLines[t];
	}

	getch();
}


// Main method / program
void main()
{

	ifstream myfile ("items.txt");

	cout << "Displaying items.txt contents:\n\n";

	// Opening a file and sending to output
	if (myfile.is_open())
	{
		cout << endl;
		
		// Empty a vector of lines if not empty
		if (allLines.size() > 0)
		{
			allLines.erase(allLines.begin(), allLines.end());
		}

		// Send file lines to output
		while (myfile.good())
		{
			getline (myfile,line);
			cout << line << endl;

			// Insert a line into a vector
			allLines.push_back(line);
		}

		// Closing a file
		myfile.close();
		cout << endl;						 
	}


	else cout << "\nUnable to open file\n";

	cout << "\nNumber of lines: " << (int) allLines.size() << endl;


	int option;

	cout << "\n\nChoose an option (enter 1 - 3): \n"
		<< "1. Buy product\n"
		<< "2. Display products\n"
		<< "3. Exit\n\n";

	cin >> option;

	switch (option)
	{
	case 1: buyProduct();
	case 2: system("CLS"); main();
	case 3: exit(1);
	default:
		{
			cout << "\n\nInvalid option! Try again.\n";
			main();
		}
	}
}

And here is the text file to use for demonstration (put it in the same place as a Main.cpp file):

items.txt

50320 40 Monitor
20334 80 Mouse
11299 10 Speakers
29931 50 USB
50223 10 Camera

I see a bunch of potential problems, but in my environment the file reads perfectly. I don't want this post to be completely useless to you, so here is a test program that just reads the file and displays the lines in the vector. I fixed the aforementioned potential problems too and noted them with comments:

#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>

using namespace std;

vector<string> readLines(istream& is)
{
    vector<string> lines;
    string line;
    
    // Try to use the result of the input request as a loop condition
    while (getline(is, line))
    {
        lines.push_back(line);
    }
    
    return lines;
}

void displayLines(vector<string> const& lines)
{
    cout << "Displaying file contents:\n\n";
        
    for (vector<string>::size_type i = 0; i < lines.size(); i++)
    {
        cout << lines[i] << endl;
    }
    
    cout << "Number of lines: " << lines.size() << endl;
}

int main()
{
    string filename;
    
    // Use a loop, main() should not be called recursively
    while (cout << "File to read: ", getline(cin, filename))
    {
        ifstream myfile(filename.c_str());

        // istream has a conversion to boolean that looks at the state
        if (myfile)
        {
            displayLines(readLines(myfile));
        }
        else
        {
            // perror() will tell you why the open failed
            perror("Unable to open file");
        }
    }
}

I found a solution to this by myself. Just used this line:

1
// Get the last element of the vector (product)
2
// [solution to bug: last element keeps disappearing]
3
string lastElement = allLines.back();


for getting the last element before another one is updated (which I thought was causing the last one to disappear) and a bit later used this:
1
// Add the last element of the vector (product) to the end of the vector
2
// [solution to bug: last element keeps disappearing]
3
allLines.push_back(lastElement);


to put it back in as a last element in a vector. I even tested this by trying to "buy" the last element and it normally calculated the remaining amount of it and stored it back to a vector. It's working now.

Thanks anyway...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.