Pointer problem

So I have this program that simulates a grocery store checkout. Somewhere in the code, whether it was reading input from the file and storing it in my LookupTable or when I call my checkout function, a problem is appearing to where the program is unable to read from memory.

The error is appearing at line 17 and 80 in store.cpp and in line 37 in product.cpp.

Here is the code:

store.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>

#include "product.h"
#include "Tokenizer.h"
#include "LookupTable.h"

LookupTable<Product *> table;

double checkout(int inputPLU, double weight) 
{
	double checkTotal = 0.0;
	Product *temp = table[inputPLU];
	checkTotal = temp->get_price() * weight;
	return checkTotal;
}

int main() {

	//Variable initialization
	int plu = 0;
	int in = 0;
	int input = 0;
	bool byWeight = 0;
	double price = 0;
	double inventory = 0;
	double total = 0;
	double weight = 0;
	bool flag = false;
	string name, line;

	//Creates two different ranges for PLU code
	table.addRange(0, 9999);
	table.addRange(90000, 99999);

	//Input and output file streams
	ifstream myfile("inventory.csv");
	ofstream outfile("output.csv");

	//Opens file then reads and writes input until it runs out of lines
 	if (myfile.is_open())
	{
		while (getline(myfile, line))
		{
			Tokenizer tok(line, ",");
			string token = tok.next();
			istringstream(token) >> plu;
			istringstream(token) >> name;
			istringstream(token) >> byWeight;
			istringstream(token) >> price;
			istringstream(token) >> inventory;

			table[plu] = new Product(plu, name, byWeight, price, inventory);
		}
	}

	while (true)
	{
		do
		{
			std::cout << "Enter PLU code or 0 to exit: ";
			outfile << "Enter PLU code or 0 to exit: ";
			std::cin >> input;
			outfile << input;

			if (input == 0)
			{
				break;
			}
			else
			{
				std::cout << "Enter weight: ";
				outfile << "Enter weight: ";
				std::cin >> weight;
				outfile << weight;

				total += checkout(input, weight);
				std::cout << "Your current total is: " << total << endl;
			}
		} while (input != 0);

		std::cout << "Enter 1 to start a new purchase, or press 0 to quit./n";
		std::cin >> in;

		if (in == 1)
		{
			return true;
		}
		else if (in == 0)
		{
			return false;
		}
		else
		{
			while (flag)
			{
				std::cout << "I'm sorry, but you need to enter either 1 or 0./n";
				std::cout << "Please enter 1 to continue, or 0 to quit.";
				std::cin >> in;

				if (in == 0 || in == 1)
				{
					flag = false;
				}
				else
					flag = true;
			}
		}
	}
	
	std::cout << "Thank you for your purchase! We hope to see you soon!";

		//later, in a loop to write output for each product, also do
		//... delete table[plu];
}


product.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef GS_PRODUCT
#define GS_PRODUCT

#include <iostream>
#include <string>

using namespace std;

class Product
{
private:
		int plu_code;
		string name;
		double price;
		bool by_weight;
		double inventory;
public:
		Product(int p_code = 0, string p_name = "", bool p_by_weight = true, double p_price = 0.0, double p_inv = 0.0);
		bool sold_by_weight(void);
		double compute_cost(double weight_or_unit);
		string get_name(void);
		int get_plu_code(void);
		double get_price(void);
		double get_inventory(void);
};

#endif 


product.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <string>

#include "product.h"

using namespace std;

Product::Product(int p_code, string p_name, bool p_by_weight, double p_price, double p_inv)
{
	plu_code = p_code;
	name = p_name;
	by_weight = p_by_weight;
	price = p_price;
	inventory = p_inv;
}

bool Product::sold_by_weight(void)
{
	return by_weight;
}

double Product::compute_cost(double weight_or_units)
{
	inventory -= weight_or_units;
	return weight_or_units * price;
}

string Product::get_name(void) {
	return name;
}

int Product::get_plu_code(void) {
	return plu_code;
}

double Product::get_price(void) {
	return price;
}

double Product::get_inventory(void) {
	return inventory;
}


LookupTable.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#ifndef LOOKUPTABLE_H
#define LOOKUPTABLE_H

#include <iostream>

using namespace std;

#define MAXRANGE 10

template <class T>
class LookupTable
{
private:
   T *aptr[MAXRANGE];
   int rangeStart[MAXRANGE];
   int rangeEnd[MAXRANGE];
   int numRanges;
   T defaultValue; //needed to return when [] operator does not find valid product

public:
   LookupTable();      
   
   //for each range, following method needs to be called.
   void addRange(int start, int end);	  
   ~LookupTable(); 	      
   T &operator[](int value);    
   // find the appropriate range based on value, then
   // use index = value-start into corresponding array
};

template <class T>
LookupTable<T>::LookupTable()
{
	numRanges = 0;
	defaultValue = T();
}

template <class T>
void LookupTable<T>::addRange(int start, int end)
{
	rangeStart[numRanges] = start;
	rangeEnd[numRanges] = end;
	aptr[numRanges] = new T [end-start+1];
	numRanges++;
}


template <class T>
T &LookupTable<T>::operator[](int value)
{
	int i = 0;
	//find the range
	//if valid range is found
	if (value < 9999)
		return aptr[i][value - rangeStart[i]];
	else if (value > 9999)
	{
		i = 1;
		return aptr[i][value - rangeStart[i]];
	}
	//default
	else
		return defaultValue;
}

template <class T>
LookupTable<T>::~LookupTable()
{
	//use a loop for numRanges
	for (int i = 0; i < numRanges; i++)
       delete [] aptr[i];
}

#endif 
Last edited on
checkTotal = temp->get_price() * weight;

get_price() belongs to an object of type Product.

This line:
Product *temp = table[inputPLU];

is most definitely not creating you a Product object.
Last edited on
So having it point to the value of the object would not work? What would you suggest?
write a function to search your lookup and return the pointer you need e.g.

Product *temp = getProduct(inputPLU);
So this is what I attempted and it didn't work.

1
2
3
4
Product * getProduct(int plu) {
	Product *info = table[plu];
	return info;
}


Again, pretty bad with pointers so I assume this isn't exactly what you had in mind.

I replaced
 
Product *temp = table[inputPLU];

with
 
Product *temp = getProduct(inputPLU);
Last edited on
I assume this isn't exactly what you had in mind

This isn't what i had in mind, because it's pretty much the same code.
I meant the function should iterate over your lookup and check every 'element' against your 'inputPLU' variable. when/if you find if return that pointer. (if you don't find it return nullptr and check for null before trying to use it in your checkout method.

edit: do you have to use pointers? Or c-style arrays?

edit2:
if not you could do something like this:
1
2
3
4
5
std::vector<Product> table;
	//....
	Product product(plu, name, byWeight, price, inventory);

	table.push_back(product);


if you do need to use pointers consider http://en.cppreference.com/w/cpp/memory/unique_ptr
Last edited on
Ya I realized it was the same after I wrote it replied lol. But ya, it was for a project which we had to use pointers and had to do it in that style. A lot of that code he gave to is which was weird that it was giving errors, but I just ended up turning in what I had. Thanks for the help though.
Topic archived. No new replies allowed.