Topical Information

Here are a few questions to help you clarify your understanding of the management of lists.

Question Set Information

Questions

  1. 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. (Why would you want a list of nothing, anyway?)

    Handily for us, using such a list means that at least some of the common list management tasks are taken care of for us. For instance, if we want to append a new item onto the list, we can simply call the push_back method. And to display the list on-screen, we can use a for loop with something like:

        cout << list [i]

    inside of it. (i.e. We'd use the subscript/indexing operator to pull out the individual list items which are each displayed on the screen.)

    However, even to simply remove an old item the user no longer desires, we'd need to search for the item's current position, swap that position's data with the last piece in the list, and then call the pop_back method. And to allow the user to change one of the items in their list, we'd also have to look for the item's current position before we could overwrite that with the new value they'd prefer it have. (Probably with a simple assignment statement — you know, operator =.)

    In fact, determining the present location of an item in a list — if it is, indeed there — is such an important task that it merits its own separate question set!

  2. Show how to declare a variable to hold a list of double values.

    
        vector<double> values;
    
    
  3. Show code to print all of the elements of the list called species_names on the screen. Be sure to number your list for the user's convenience.

    
        for (vector<string>::size_type n = 0; n != species_names.size(); ++n)
        {
            cout << n+1 << ")  " << species_names[n] << '\n';
        }
    
    
  4. When the user enters their selection from a list, the list they are referencing (the one you displayed on the screen — as above) is numbered starting at one. However, the list we have stored in our program is considered to be numbered with zero as its starting position. 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 value typed by the user to subscript into a vector, we should validate it against the list's current size (namely that it is less than this). (Technically, we should also make sure it is greater than or equal to zero, but that necessity is alleviated by the fact that integral-style positions are stored in a type that is unsigned and so they always meet that criterion.)

  5. Show code needed to insert a new long integer (currently stored in the variable popul) into the list of long integers called species_populations. Place the new value in the position the user refers to as 5 — overwriting the value currently there.

    
        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'
    
    
  6. 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(orig_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
    
    
  7. 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
    
    
  8. 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(orig_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
    
    
  9. It would be nice if the vector data type we use to store lists would automatically handle moving any elements necessary to insert an item either in the middle of or at the beginning of a list. At least it does automatically grow to accomodate new items we place at its end!

    Briefly explain why it is necessary to move data to place an item in the middle of a list. For example, if you wanted to insert q in front of the r in the list below, what elements would need to move? Is there a particular order in which you'd need to move them? Why need they move?

    
        +-----+-----+-----+-----+-----+-----+-----+
        |  a  |  k  |  m  |  n  |  r  |  t  |  w  |
        +-----+-----+-----+-----+-----+-----+-----+
    
    
    
        After a resize to make room for the new element albeit at the end of
        the vector, we need to scoot all the elements over by one slot to open
        the spot for the new element as desired.  We must start with 'w' and
        move it to the new last slot made with resizing.  Then comes 't' which
        will overwrite the original 'w'.  Then 'r' will overwrite the original
        't'.  And then we'll overwrite the original 'r' with the new element
        'q'.
    
        If we didn't move the data in this order, we'd end up overwriting the
        last two pieces of data with extra 'r' values and lose them altogether!
    
    
  10. Show code to remove an item from the list 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
    
    
  11. 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
    
    
  12. Show code to remove an item from the list 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
    
    
  13. Show code to remove a contiguous sequence of items 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
    
    
  14. 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.