Vector same element problem?

Hi!

My current task is to make a list of ingredients for a cocktail, stored in a vector. If the ingredient, which the user types in is already in the vector, the counter increases (the ingredient's name and quantity is in a struct). Then, I must count from the total summary of the ingredients and the individual ingredients the percentage of the given ingredient in the "cocktail".

I have problem at counting the individual quantities. It works perfectly when I type in the ingredients in an order where no same ones follow each other. However, if I type the same ingredient after each other, the vector deems it as a new element and adds it to the back. Could you help me how to solve it?

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

struct Ingredient{
	
	std::string name;
	int quantity;
	double percentage;
	
};

int main(){
	
	std::string n;
	int choice = 0, id = 0;
	
	std::vector<Ingredient>v;
	std::vector<std::string>list;
	
	
	std::cout << "Ingredient: ";
	std::cin >> n;
	
	Ingredient f;
	f.name = n;
	f.quantity = 1;
	f.percentage = 100.00;
	
	v.push_back(f);
	list.push_back(n);
	
	do{
		
		std::cout << "Ingredient: ";
		std::cin >> n;
		
		if(n == "done"){
			break;
			
		}
		
		for(int i = 0; i < list.size(); i++){
			
			if(list[i] == n){
		
				choice = 1;
				id = i;
			
			break;
			
			}
		}
		
		
		if(choice == 0){
		
			std::cout << n << " is not in the vector!\n";

			f.name = n;
			f.quantity = 1;
			f.percentage = 100.00;
			
			v.push_back(f);
			list.push_back(n);
		
		
		}else if(choice == 1){
			std::cout << n << " is in the vector!\n";
			
			for(int i = 0; i < v.size(); i++){
				if(v[i].name == n){
					
					v[i].quantity++;
					
					break;
					
				}
				
			}
			
			
			
		}
		
		
		
	}while(n != "done");
	
	
	for(int i = 0; i < v.size(); i++){
		
		std::cout << "\nName: " << v[i].name << ", quantity: " << v[i].quantity << '\n';
		
		
	}
	
	return 0;
}
Last edited on
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
#include <iostream>
#include <string>
#include <vector>

struct ingredient {

	std::string name;
	int quantity = 1 ;
	// ..
};

// add the ingredient if it is not present, update its quantity otherwise
void add_item( std::vector<ingredient>& items, const std::string& name, int qty = 1 )
{
    // range based loop: https://www.stroustrup.com/C++11FAQ.html#for
    for( ingredient& ing : items ) { // for each item in the vector

        if( name == ing.name ) { // note: name is case sensitive

            // found the ingredient with this name
            ing.quantity += qty ; // update its quantity
            return ; // and we are done
        }
    }

    // if we reach here, the ingredient was not found in the vector; add a new item
    items.push_back( { name, qty } ) ;
}

int main() {

    std::vector<ingredient> items ;

    std::string name ;
    while( std::cout << "ingredient (enter 'done' to quit): " && std::cin >> name && name != "done" )
        add_item( items, name ) ; // default value for quantity is 1

    // ...
}


Using std::map (with the name as the key) would be a good alternative.
Consider as C++17:

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

struct Ingredient {
	std::string name;
	unsigned quantity {1};
};

int main()
{
	std::vector<Ingredient> v;
	double total {};

	for (Ingredient f; (std::cout << "Ingredient (done to exit): ") && (std::cin >> f.name) && (f.name != "done"); ++total)
		if (const auto fnd {std::find_if(v.begin(), v.end(), [&](const auto& d) {return d.name == f.name; })}; fnd == v.end())
			v.push_back(f);
		else
			++fnd->quantity;

	for (const auto& [nam, qty] : v)
		std::cout << "\nName: " << nam << ", quantity: " << qty << ", " << std::fixed << std::setprecision(2) << qty / total * 100 << '%';
}



Ingredient (done to exit): qwe
Ingredient (done to exit): asd
Ingredient (done to exit): zxc
Ingredient (done to exit): qwe
Ingredient (done to exit): yui
Ingredient (done to exit): qwe
Ingredient (done to exit): done

Name: qwe, quantity: 3, 50.00%
Name: asd, quantity: 1, 16.67%
Name: zxc, quantity: 1, 16.67%
Name: yui, quantity: 1, 16.67%

Last edited on
Topic archived. No new replies allowed.