Finding new problem, error: expression did not evaluate to constant

This is the first time I use pointers or struct.
If someone can kindly help me with this problem.
My code needs to find the best possible combination of weight, item value in the bag.
Pretty much a bounded knapsack problem.

It should read from a (item.txt) file that contains this value:
100
Pearl 1 25 10
Ruby 4 40 12
Diamond 5 30 15
Emerald 10 5 10
Sapphire 1 50 20

The output should be printed as:
10 Emerald, 1 Sapphire 120


Current Error:
int maxPft[itemCount + 1][col + 1];

it gave me an error saying that
expression did not evaluate to a constant



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
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>

using namespace std;

struct Item {
	string Name;
	int Quantity;
	int Weight;
	int Value;
	int taken = 0;
};

ifstream& operator>> (ifstream& lhs, Item& rhs) {
	lhs >> rhs.Name;
	lhs >> rhs.Quantity;
	lhs >> rhs.Weight;
	lhs >> rhs.Value;
	return lhs;
}

int BknpSack(int maxPft, int carryWeight, int val[], int totalItems) {
	Item items[10];

	int** optTable = new int* [totalItems + 1];
	int totalWeight = 0;
	int row, col, previousBest, newItemInclude;
	
	//setup item IndexTable
	int* itemIndexTable = new int[totalItems + 1];

	for (row = 1; row < totalItems; row++) {
		optTable[row] = new int[totalWeight + 1];
		for (col = 0; col < maxPft; col++) {
			optTable[0][col] = 0;
			if (col - items[itemIndexTable[row]].Weight >= 0) {
				previousBest = optTable[row - 1][col];
				newItemInclude = optTable[row - 1][col - items[itemIndexTable[row]].Weight] + items[itemIndexTable[row]].Value;
				if (previousBest > newItemInclude) {
					optTable[row][col] = previousBest;
				}
				else {
					optTable[row][col] = newItemInclude;
				}
			}
			else {
				//cant conclude the cur item
				optTable[row][col] = optTable[row - 1][col];//copy val from above
			}
		}
	}
	int currentRow = totalItems;
	int currentCol = carryWeight;
	while (currentRow > 0 && currentCol > 0) {
		if (optTable[currentRow][currentCol] == optTable[currentRow - 1][currentCol]) {
			currentRow--;
		}
		else {
			currentCol -=
				itemIndexTable[currentRow] = items[itemIndexTable[row]].taken++;
			currentRow--;
		}
	}
	printf("The optimized Value is: \n");
	return items[itemIndexTable[row]].Quantity, items[itemIndexTable[row]].Name, items[itemIndexTable[row]].Value;
}

int main() {
	Item items[10];

	//read from file
	ifstream infile("item.txt");
	int carryWeight = 0;
	infile >> carryWeight;

	Item temp;
	int itemCount = 0;
	while (infile >> temp) {
		//creating arr for data read from file
		FILE* inFile;
		int* arr;
		int size = sizeof(arr) / sizeof(arr[0]);
		int readVal;
		fread(&size, sizeof(size), 1, inFile);
		arr = new int[size];

		for (int i = 0; i < size; i++) {
			fread(&readVal, sizeof(readVal), 1, inFile);
			arr[i] = readVal;
		}
		infile.close();

	}
        cout << BknpSack(0, 0, 0, size);
        return 0;
}
Last edited on
This now overcomes the immediate problem.
A few tips:
1. right and left are bad names because they can be confused with some often used <iomanip> functions, lhs stands for left hand side rhs ... are traditional names in lieu.

2. You have a lot of other problems with your code with arrays going out of range. Using eof() is the cause more or less. Just keep reading the Items until they run out, not to the end of the file. See my while()

3. Avoid debugging 80 lines - it's must be very annoying. It's much easier to test small pieces and get them to work as I have done and then and only then move back to the next bit.



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
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

struct Item
{
    string Name;
    int Quantity;
    int Weight;
    int Value;
    int taken = 0;
};

ifstream& operator>> (ifstream& lhs, Item& rhs)
{
    lhs >> rhs.Name;
    lhs >> rhs.Quantity;
    lhs >> rhs.Weight;
    lhs >> rhs.Value;
    return lhs;
}

int main() {
    Item items[10];
    
    ifstream infile("aaa.txt");//("item.txt");
    
    //read carryWeight
    int carryWeight = 0;
    infile >> carryWeight;
    
    std::cout << carryWeight << '\n';
    
    Item temp;
    while(infile >> temp)
    {
        std::cout << temp.Name << ' ' << temp.Quantity << '\n';
    }
    
    
    return 0;
}



100
Pearl 1
Ruby 4
Diamond 5
Emerald 10
Sapphire 1
Program ended with exit code: 0
> Currently have an error in left >> right.Quantity;
¿what error? ¿why do you think it's there?

> int totalItems = sizeof(arr) / sizeof(arr[0]);
warning: 'sizeof (arr)' will return the size of the pointer, not the array itself [-Wsizeof-pointer-div]

@againtry: thank you for your advice. I will try with your method

@ne555: using @againtry method with the lhs >> rhs. , it didn't give me an overload error.
I updated my current code up there. But its only printing 0. Seems like after reading the value inside the .txt file it didn't go through the loop.
Made some changes again. have some error in this part of the code

1
2
3
4
5
6
7
8
9
10
int BknpSack(int maxPft, int carryWeight[], int val[], int totalItems) {
	Item items[10];
	ifstream infile("item.txt");
	infile >> carryWeight; //error here >> no operator matches this operand
	while (!infile.eof()) {
		int itemCount = 0;
		infile >> items[itemCount];
		itemCount++;
	}
	infile.close();


the rest of the code has been tweaked also have some error in this part
1
2
3
4
5
6
int main() {
	int maxPft;
	int* arr;
	int totalItems = sizeof(arr) / sizeof(arr[0]);
	cout << BknapSack(maxPft, 0, 0, totalItems);
}


How do I call BknpSack here? Have trouble calling maxPft, carryWeight, and Val so at the moment I just call it as 0.
Last edited on
carryWeight is a single value not an array.

@againtry Thank you that fix that problem.

Currently printing nothing.
I think the error still in the main()
Last edited on
@Lmaverick

I'm glad it helped you to that point. You are still using eof() and that is wrong.

I looked at your earlier code in detail before you deleted it and was able to sort through some of it.

You need to read the data from the file, prepare the arrays etc, and then do the processing. These need to be separate blocks not all intertwined.

Making functions is not helping you. It's making debugging worse, not better. Do that later.

I can't really help you with the rest for 2 reasons:
1. You need to post all your code
2. You need to show your assignment statement or some reference or explanation of what you are trying to do, in other words, some context.

Up to you ...
@againtry I edited the original post for the code so it's not too cluttered.
the original post has all my current code with the modification that you suggested.
OK I have modified main so that it runs and provides some checking output.

I suggest you change your layout with {} the way I show and also make sure you have plenty of whitespace double lines so your code is easier to read.
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <iostream>
#include <fstream>
//#include <algorithm> // SO FAR NOT NEEDED
#include <string>

using namespace std;

struct Item
{
    string Name;
    int Quantity;
    int Weight;
    int Value;
    int taken = 0;
};

ifstream& operator>> (ifstream& lhs, Item& rhs)
{
    lhs >> rhs.Name;
    lhs >> rhs.Quantity;
    lhs >> rhs.Weight;
    lhs >> rhs.Value;
    return lhs;
}

ostream& operator<<(ostream& os, const Item& item)
{
    os << item.Name<< ' ' << item.Quantity << ' ' << item.Value;
    return os;
}



int BknpSack(int maxPft, int carryWeight, int val[], int totalItems)
{
    Item items[10];
    
    int** optTable = new int* [totalItems + 1];
    int totalWeight = 0;
    int row, col, previousBest, newItemInclude;
    
    //setup item IndexTable
    int* itemIndexTable = new int[totalItems + 1];
    
    for (row = 1; row < totalItems; row++)
    {
        optTable[row] = new int[totalWeight + 1];
        for (col = 0; col < maxPft; col++)
        {
            optTable[0][col] = 0;
            if (col - items[itemIndexTable[row]].Weight >= 0)
            {
                previousBest = optTable[row - 1][col];
                newItemInclude = optTable[row - 1][col - items[itemIndexTable[row]].Weight] + items[itemIndexTable[row]].Value;
                if (previousBest > newItemInclude)
                {
                    optTable[row][col] = previousBest;
                }
                else
                {
                    optTable[row][col] = newItemInclude;
                }
            }
            else
            {
                //cant conclude the cur item
                optTable[row][col] = optTable[row - 1][col];//copy val from above
            }
        }
    }
    int currentRow = totalItems;
    int currentCol = carryWeight;
    while (currentRow > 0 && currentCol > 0)
    {
        if (optTable[currentRow][currentCol] == optTable[currentRow - 1][currentCol])
        {
            currentRow--;
        }
        else
        {
            currentCol -=
            itemIndexTable[currentRow] = items[itemIndexTable[row]].taken++;
            currentRow--;
        }
    }
    printf("The optimized Value is: \n");
    return items[itemIndexTable[row]].Quantity, items[itemIndexTable[row]].Name, items[itemIndexTable[row]].Value;
}

int main() {
    Item items[10];
    
    //read from file
    ifstream infile("item.txt");
    int carryWeight = 0;
    infile >> carryWeight;
    
    // COUNT NO. OF ITEMS
    Item temp;
    int itemCount = 0;
    while (infile >> temp)
    {
        itemCount++;
    }
    std::cout << "itemCount: " << itemCount << '\n';
    
    
    //    creating arr for data read from file
    Item* arr = new Item[itemCount]; // AN ARRAY OF Items
    
    // GO BACK TO START OF FILE
    infile.clear();
    infile.seekg(0);
    
    // RE-READ FIRST LINE
    infile >> carryWeight;
    std::cout << "carryWeight: " << carryWeight << '\n';
    
    // RE-READ REMAINDER OF FILE INTO ARRAY
    for(int i = 0; i < itemCount; i++)
    {
        infile >> arr[i];
    }
    infile.close();
    
    // CHECK THAT arr IS CORRECT
    for(int i = 0; i < itemCount; i++)
    {
        std::cout << "Item " << i << ' ' << arr[i] << '\n';
    }
    
    cout << BknpSack(0, 0, 0, itemCount);
    
    return 0;
}
return items[itemIndexTable[row]].Quantity, items[itemIndexTable[row]].Name, items[itemIndexTable[row]].Value;

You can't do that!

If you want to return and Item you must have a single value - an Item in this case:

1
2
3
4
5
Item BknpSack(int maxPft, int carryWeight, int val[], int totalItems)
{
    ....

    return itemIndexTable[row]];
I've changed your code from the latest at post 1 so that it compiles and runs without error. However it doesn't produce the correct output. So all you now need to do is to debug the BknpSack() function.

Where does carryWeight get used?

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
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>

using namespace std;

struct Item {
	string Name;
	int Quantity;
	int Weight;
	int Value;
	int taken = 0;
};

ifstream& operator>> (ifstream& lhs, Item& rhs) {
	lhs >> rhs.Name;
	lhs >> rhs.Quantity;
	lhs >> rhs.Weight;
	lhs >> rhs.Value;
	return lhs;
}

int BknpSack(int maxPft, int carryWeight, Item items[], int totalItems) {
	int** optTable = new int* [totalItems + 1] {};
	int totalWeight = 0;
	int row {}, col {}, previousBest {}, newItemInclude {};

	//setup item IndexTable
	int* itemIndexTable = new int[totalItems + 1] {};

	for (row = 1; row < totalItems; row++) {
		optTable[row] = new int[totalWeight + 1];
		for (col = 0; col < maxPft; col++) {
			optTable[0][col] = 0;
			if (col - items[itemIndexTable[row]].Weight >= 0) {
				previousBest = optTable[row - 1][col];
				newItemInclude = optTable[row - 1][col - items[itemIndexTable[row]].Weight] + items[itemIndexTable[row]].Value;
				if (previousBest > newItemInclude) {
					optTable[row][col] = previousBest;
				} else {
					optTable[row][col] = newItemInclude;
				}
			} else {
				//cant conclude the cur item
				optTable[row][col] = optTable[row - 1][col];//copy val from above
			}
		}
	}

	int currentRow = totalItems;
	int currentCol = carryWeight;

	while (currentRow > 0 && currentCol > 0) {
		if (optTable[currentRow][currentCol] == optTable[currentRow - 1][currentCol]) {
			currentRow--;
		} else {
			currentCol -=
				itemIndexTable[currentRow] = items[itemIndexTable[row]].taken++;
			currentRow--;
		}
	}

	//return items[itemIndexTable[row]].Quantity, items[itemIndexTable[row]].Name, items[itemIndexTable[row]].Value;
	return itemIndexTable[row];
}

int main() {
	Item items[10];

	//read from file
	ifstream infile("item.txt");

	if (!infile.is_open()) {
		cout << "Cannot open file\n";
		return 1;
	}

	int carryWeight = 0;
	infile >> carryWeight;

	Item temp;
	int itemCount = 0;

	while (infile >> temp) {
		items[itemCount++] = temp;
	}

	infile.close();

	int result =  BknpSack(0, 0, items, itemCount);

	cout << "Optimised value is " << items[result].Quantity << "  " << items[result].Name << "  " << items[result].Value << '\n';
}

Last edited on
@againtry I see! thank you, that makes sense. I should have called it in the main() instead

@seeplus Thank you! I will work on the BknpSack and post it back here if I got some more questions.

You guys have been a really big help. Thank you!
I figure out some of my problems. Seems that I did use or declare some variable correctly.

One of the problems that I have:
Let say I need to declare maxPft so I can use it in my for loop

int maxPft[itemCount + 1][col + 1];

it gave me an error saying that
expression did not evaluate to a constant


How do I fix this?

Also, I decided it would probably easier to just write bKnpSack in my main instead of calling it as a function.

I have another error in my while loop when I try to compare currentWeight

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
int main() {
	Item items[10];

	//read from file
	ifstream infile("JBB.txt");

	if (!infile.is_open()) {
		cout << "Cannot open file\n";
		return 1;
	}

	int carryWeight = 0;
	infile >> carryWeight;

	Item temp;
	int itemCount = 0;

	while (infile >> temp) {
		items[itemCount++] = temp;
	}
	cout << "itemCount: " << itemCount << '\n';

	Item* arr = new Item[itemCount];

	infile.clear();
	infile.seekg(0);
	
	infile >> carryWeight;
	cout << "carryWeight: " << carryWeight << '\n';
	
	for (int i = 0; i < itemCount; i++) {
		infile >> arr[i];
	}
	infile.close();

	for (int i = 0; i < itemCount; i++) {
		cout << "Item " << i << ' ' << arr[i] << '\n';
	}	int** optTable = new int* [itemCount + 1];
	int totalWeight = 0;
	int row, col, previousBest, newItemInclude;
	int maxPft[itemCount + 1][col + 1]; //1st error here
	//setup item IndexTable
	int* itemIndexTable = new int[itemCount + 1]{};
	
	for (row = 1; row < itemCount; row++) {
		optTable[row] = new int[totalWeight + 1];
		for (col = 0; col < maxPft; col++) {
			optTable[0][col] = 0;
			if (col - items[itemIndexTable[row]].Weight >= 0) {
				previousBest = optTable[row - 1][col];
				newItemInclude = optTable[row - 1][col - items[itemIndexTable[row]].Weight] + items[itemIndexTable[row]].Value;
				if (previousBest > newItemInclude) {
					optTable[row][col] = previousBest;
				}
				else {
					optTable[row][col] = newItemInclude;
				}
			}
			else {
				//cant conclude the cur item
				optTable[row][col] = optTable[row - 1][col];//copy val from above
			}
		}
	}	
int currentRow = itemCount;
	int currentCol = carryWeight;

	while (currentRow > 0 && currentCol > 0) {
		if (optTable[currentRow][currentCol] == optTable[currentRow - 1][currentCol]) { //2nd error here
			currentRow--;
		}
		else {
			currentCol -=
				itemIndexTable[currentRow] = items[itemIndexTable[row]].taken++;
			currentRow--;
		}cout << "Optimised value is " << items[itemIndexTable[row]].Quantity, items[itemIndexTable[row]].Name, items[itemIndexTable[row]].Value;
	return 0;
}
Last edited on
You were asked previously to provide information on the assignment or otherwise show the context. You are making it virtually impossible without that information because this part of you code is absolute rubbish.

Your call.
@againtry: sorry if my first post wasn't so clear about what the program is
but this is the complete question, also I need to program it with Dynamic programming which I have learned that it would be best to use bounded Knapsack.

A burglar has broken into a jewelry store to steal. He can only carry out a certain amount of stuff before it gets too heavy. In addition, he can only make one trip in and out of the store before the cops arrive, so he wants to be sure to get the most value out of the stuff he takes. Input for the program will be as below. The first line will contain how much he can carry. This line is followed by a single item per line. Each of these lines will contain the name of the item, the number of items available, each individual item’s weight, and its value. There will be up to 10 different items. Output the number of each item type he should take to maximize his value as well as the max value.

100
Pearl 1 25 10
Ruby 4 40 12
Diamond 5 30 15
Emerald 10 5 10
Sapphire 1 50 20
Thank you - the additional information/context is helpful
I changed the variable names to more meaningful names and have managed to get it to run. The answer is more than likely meaningless. I have no idea what maxPft is supposed to be. I even hazard a guess and doubt whether you know either :(

You still have a problem with braces - you are using a very poor convention and mine, which clearly shows the loop structure, is better - I'm not going to fix up beyond this post.

As far as 2d arrays are concerned, you've got that wrong.
Use https://stackoverflow.com/questions/936687/how-do-i-declare-a-2d-array-in-c-using-new to do it properly.

As far as the knapsack algorithm is concerned I suggest you:
a) Fix up the code as above
b) Study carefully the algorithm before writing code and only after you write pseudocode.

Why you are adding .Weight to .Value is beyond me but I'm sure you will sort that out in time.

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
120
121
122
123
124
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct Item
{
    string Name;
    int Quantity;
    int Weight;
    int Value;
    int taken = 0;
};

ifstream& operator>> (ifstream& lhs, Item& rhs)
{
    lhs >> rhs.Name;
    lhs >> rhs.Quantity;
    lhs >> rhs.Weight;
    lhs >> rhs.Value;
    return lhs;
}

ostream& operator<<(ostream& os, const Item& item)
{
    os <<
    item.Name<< ' ' << item.Quantity << ' ' << item.Value << ' ' <<
    item.Weight << ' ' << item.taken;
    return os;
}

int main()
{
    //read from file
    ifstream infile("item.txt");
    int MAX_WEIGHT = 0;
    infile >> MAX_WEIGHT;
    
    // COUNT NO. OF ITEMS
    Item temp;
    int NO_OF_ITEMS = 0;
    while (infile >> temp)
    {
        NO_OF_ITEMS++;
    }
    std::cout << "No. of items in stock: " << NO_OF_ITEMS << '\n';
    
    //    creating Stock for data read from file
    Item* Stock = new Item[NO_OF_ITEMS]; // AN ARRAY OF Items
    
    // GO BACK TO START OF FILE
    infile.clear();
    infile.seekg(0);
    
    // RE-READ FIRST LINE
    infile >> MAX_WEIGHT;
    std::cout << "Maximum weight to carry: " << MAX_WEIGHT << '\n';
    
    // RE-READ REMAINDER OF FILE INTO ARRAY
    for(int i = 0; i < NO_OF_ITEMS; i++)
    {
        infile >> Stock[i];
    }
    infile.close();
    
    // CHECK THAT Stock IS CORRECT
    for(int i = 0; i < NO_OF_ITEMS; i++)
    {
        std::cout << "Item " << i << ' ' << Stock[i] << '\n';
    }
    
    int** Option = new int* [NO_OF_ITEMS];
    int previousBest{0}, newItemInclude{0};
    int maxPft{0};
    
    int* Index = new int[NO_OF_ITEMS]{};
    
    for (int row = 0; row < NO_OF_ITEMS; row++)
    {
        Option[row] = new int[MAX_WEIGHT];
        for (int col = 1; col < maxPft; col++)
        {
            Option[0][col] = 0;
            if (col - Stock[Index[row]].Weight >= 0)
            {
                previousBest = Option[row - 1][col];
                newItemInclude = Option[row - 1][col - Stock[Index[row]].Weight] + Stock[Index[row]].Value;
                if (previousBest > newItemInclude)
                {
                    Option[row][col] = previousBest;
                }
                else
                {
                    Option[row][col] = newItemInclude;
                }
            }
            else
            {
                Option[row][col] = Option[row - 1][col];
            }
        }
    }
    
    int currentRow = NO_OF_ITEMS;
    int currentCol = MAX_WEIGHT;
    
    while (currentRow > 0 && currentCol > 0)
    {
        if (Option[currentRow]== Option[currentRow - 1])
        {
            currentRow--;
        }
        else
        {
            currentCol -= Index[currentRow];
            Stock[Index[currentRow]].taken++;
            currentRow--;
        }
        cout << "Optimised value is " << Stock[Index[currentRow]] << '\n';
    }
    
    return 0;
}



No. of items in stock: 5
Maximum weight to carry: 100
Item 0 Pearl 1 10 25 0
Item 1 Ruby 4 12 40 0
Item 2 Diamond 5 15 30 0
Item 3 Emerald 10 10 5 0
Item 4 Sapphire 1 20 50 0
Optimised value is Pearl 1 10 25 1
Optimised value is Pearl 1 10 25 2
Optimised value is Pearl 1 10 25 3
Optimised value is Pearl 1 10 25 4
Optimised value is Pearl 1 10 25 5
Program ended with exit code: 0


Cheers, and all the best with it.
Topic archived. No new replies allowed.