Here are a few questions to help you clarify your understanding of the management of lists in vectors.
A list is commonly stored in a vector type variable. Thus, we can make a list of almost any type of information — anything except void.
Handily for us, using such a list means that many common tasks are taken care of for us. These include inserting a new item into the list (we can call the push_back method) and removing an item from a list (we can call the pop_back method).
However, we'll have to print it out for the user and search for items' presence within the list on our own.
Show how to declare a variable to hold a list of double values.
vector<double> list;
Show code to print all of the elements of the list of strings called species_names on the screen. Be sure to number your list for the user's convenience.
for (vector<string>::size_type p = 0; p != species_names.size(); ++p) { cout << p+1 << ") " << species_names[p] << '\n'; }
When the user enters their selection from a list, the list they are referencing (from your screen display — as above — for example) is numbered from 1 (one). However, the list we have stored in our program is considered numbered from 0 (zero). To adjust for this discrepancy, we should subtract one from the user's entry before using it to access part of the list.
Of course, before using any user choice to subscript into a list stored in a vector, we should validate it against the list's current .size() (namely that it is strictly less than this). (Technically, we should also make sure it is greater than or equal to 0 (zero), but that is alleviated because integral positions are stored in an unsigned type that always meets that criterion.)
Show code needed to insert a new long integer (currently stored in the variable popul) into the long integer list called species_populations. Place the new value into the position the user refers to as 5.
bool okay{false}; target--; // decrement the 5 to get vector position if ( target < species_populations.size() ) { species_pupulations[target] = popul; okay = true; } // okay is true or false depending on success of the 'insertion'
Show code needed to insert a new long integer (currently stored in the variable popul) into the long integer list called species_populations. Place the new value in front of the position the user refers to as 5.
auto orig_size{species_populations.size()}; bool okay{false}; target--; // decrement the 5 to get vector position if ( target == orig_size ) { species_populations.push_back(popul); okay = orig_size != species_populations.size(); } else { species_pupulations.resize(species_pupulations.size()+1); okay = species_pupulations.size() > orig_size; if ( okay ) { for ( auto pos{orig_size}; pos > target; --pos ) { species_pupulations[pos] = species_pupulations[pos-1]; } species_pupulations[target] = popul; } } // okay is true or false depending on success of the insertion
Show code needed to insert a new long integer (currently stored in the variable popul) into the long integer list called species_populations. Place the new value at the end of the list.
auto orig_size{species_populations.size()}; bool okay{false}; species_populations.push_back(popul); okay = orig_size != species_populations.size(); // okay is true or false depending on success of the insertion
Show code needed to insert a new long integer (currently stored in the variable popul) into the long integer list called species_populations. Place the new value in the front of the list.
auto orig_size{species_populations.size()}; bool okay{false}; target = 0; // where to place the new value if ( target == orig_size ) { species_populations.push_back(popul); okay = orig_size != species_populations.size(); } else { species_pupulations.resize(species_pupulations.size()+1); okay = species_pupulations.size() > orig_size; if ( okay ) { for ( auto pos{orig_size}; pos > target; --pos ) { species_pupulations[pos] = species_pupulations[pos-1]; } species_pupulations[target] = popul; } } // okay is true or false depending on success of the insertion
It is sad for us that the vector type we use to store lists will not automatically handle moving any elements necessary to insert an item either in the middle or at the beginning of a list.
Briefly explain why this movement of data is necessary. For example, if you wanted to insert q in front of the r in the list below, what would need to move? Why need they move?
+-----+-----+-----+-----+-----+-----+-----+ | a | k | m | n | r | t | w | +-----+-----+-----+-----+-----+-----+-----+
r, t, and w would need to move to the right to make room for the q to be inserted. If we don't move them over, we'd overwrite the r and it would be lost.
Since our list variables don't automatically grow to store more items in such situations, what is needed before handling the insertion request?
We need to resize the vector to make room for the w to move into during the right shifting.
Show code to remove an item from the list of strings called research_sites. The user says the item is in position 12.
// if the user wants to remove 12, then we need to remove 11 -- one off // due to the 1-based shift // assume remove_this is 11 and keep_this is 12 -- one more than the // position 11 that is to be removed vector<string>::size_type count; keep_this = keep_this > research_sites.size() ? research_sites.size() : keep_this; bool okay{keep_this >= remove_this}; // since keep_this is already // <= research_sites.size(), // transitivity will protect // remove_this, too count = keep_this - remove_this; if ( okay && count > 0 ) { auto orig_size{research_sites.size()}; for ( auto pos{keep_this}; pos < orig_size; ++pos ) { research_sites[pos-count] = research_sites[pos]; } research_sites.resize(orig_size-count); okay = research_sites.size() < orig_size; } // okay is true or false depending on success of the removal
Show code to remove an item from the list called research_sites. The item is at the end of the list.
auto orig_size{research_sites.size()}; bool okay{false}; research_sites.pop_back(); okay = orig_size != research_sites.size(); // okay is true or false depending on success of the removal
Show code to remove an item from the list of strings called research_sites. The item is at the head (beginning) of the list.
// assume remove_this is 0 and keep_this is 1 -- one more than the // position 0 that is to be removed vector<string>::size_type count; keep_this = keep_this > research_sites.size() ? research_sites.size() : keep_this; bool okay{keep_this >= remove_this}; // since keep_this is already // <= research_sites.size(), // transitivity will protect // remove_this, too count = keep_this - remove_this; if ( okay && count > 0 ) { auto orig_size{research_sites.size()}; for ( auto pos{keep_this}; pos < orig_size; ++pos ) { research_sites[pos-count] = research_sites[pos]; } research_sites.resize(orig_size-count); okay = research_sites.size() < orig_size; } // okay is true or false depending on success of the removal
Show code to remove a sequence of strings from the list called research_sites. The items are at positions [5..8] in the list (as a programmer would see it).
// assume remove_this is 5 and keep_this is 9 -- one more than the // position 8 that is to be removed vector<string>::size_type count; keep_this = keep_this > research_sites.size() ? research_sites.size() : keep_this; bool okay{keep_this >= remove_this}; // since keep_this is already // <= research_sites.size(), // transitivity will protect // remove_this, too count = keep_this - remove_this; if ( okay && count > 0 ) { auto orig_size{research_sites.size()}; for ( auto pos{keep_this}; pos < orig_size; ++pos ) { research_sites[pos-count] = research_sites[pos]; } research_sites.resize(orig_size-count); okay = research_sites.size() < orig_size; } // okay is true or false depending on success of the removal
What do you do if the user wants to remove an item from a list that is already empty?
Use an if to trap this issue and print a nice message telling them
about it.