0

I am trying to have the user choose how many names they would like to add, and then use push_back() to add that many to the list.

I am new to programming and very confused.

Here is the code I have so far:

int main()
{
    int numNames;
    std::cin >> numNames;
    vector<string> names;
    numNames = read_integer("How many names would you like to add?");

    for (int i = 0; i < numNames; i++)
    {
        names[i] = read_string("Enter name:");
        i++;

        while (cin >> numNames)
        {
            names.push_back(read_string("First value:"));
        }
    }
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Nathan
  • 17
  • 5
  • You are reading names twice as many times as you should be. And the second time is definitely broken if you are expecting first and last names. The first might also be, but the code for your `read_` functions is not shown. – sweenish May 23 '22 at 01:01
  • What's the goal of `while (cin >> numNames)`? – Brian61354270 May 23 '22 at 01:02
  • @Brain My goal is to ask the user to specify how many names they would like to add, once they do the loop for adding names is looped according to the users value. Then I need to use pushback to add data to end of vector. I hope that makes sense. The purpose of while(cin>>numNames) is to loop the adding names according to the numNames declared by user – Nathan May 23 '22 at 01:07
  • @sweenish thanks, so I need to remove the i++? – Nathan May 23 '22 at 01:09
  • 1
    Using `std::vector` you don't care how many names the user wants to add -- that's the beauty of letting `std::vector` manage the memory for you. Your job is just to gather (and **validate**) the user input and then simply `.push_back()` however many the user wants to enter. – David C. Rankin May 23 '22 at 01:14

2 Answers2

2

When using the std::vector there is no need to have the user enter the number of names beforehand. That is the benefit of having std::vector handle the memory management for you. You simply read and validate the input and .push_back() to the vector until the user is done. Using getline() for input allows you to read names with whitespace (e.g. "first last") while using std::cin would stop reading at the first whitespace encountered.

Using getline() also provides a simple way for the user to indicate they are done entering names. Having the user press Enter alone on a new line instead of a name will result in the string filled by getline() having .size() == 0. You simply break your read-loop at that point.

A short example of reading names and adding to std::vector<std::string> can be done similar to:

#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::vector<std::string> names {};    /* vector of strings */
    std::string tmp {};                   /* temp string */
    
    std::cout << "Enter names below, [Enter] alone when done\n\n  name: ";
    
    /* read line while input size isn't 0 */
    while (getline (std::cin, tmp) && tmp.size() != 0) {
        names.push_back (tmp);            /* add input to vector */
        std::cout << "  name: ";          /* next prompt */
    }
    
    std::cout << "\nnames collected:\n\n";
    for (const auto& name : names) {      /* loop over each name and output */
        std::cout << name << '\n';
    }
}

Example Use/Output

$ ./bin/vector-string-names
Enter names below, [Enter] alone when done

  name: Mickey Mouse
  name: Minnie Mouse
  name: Pluto (the dog)
  name: Donald Duck
  name: Daffy Duck
  name: Daisy Duck
  name: Hughie Duck
  name: Louie Duck
  name: Dewy Duck
  name:

names collected:

Mickey Mouse
Minnie Mouse
Pluto (the dog)
Donald Duck
Daffy Duck
Daisy Duck
Hughie Duck
Louie Duck
Dewy Duck

Additional Notes

While using namespace std; is a convenience for short example programs, see Why is “using namespace std;” considered bad practice?.

Never std::cin >> numNames; without checking the stream-state after the input. (especially when a numeric conversion is involved). A simple:

  if (!(std::cin >> numNames)) {
    std::cerr << "error: invalid integer input.\n";
    return 1;
  }

To ensure the user provides valid integer input, you can loop continually until a valid int is entered and then break the read loop after you have a valid integer. You can use .clear() and use .ignore() to remove any invalid characters from stdin after a failed input and before your next input.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
-1

I noticed when you do your loop, there is a simpler way to do so that will prevent some additional and unwanted bugs:

    for (int i = 0; i < numNames; ++i)
    {
        names[i] = read_string("Enter name:");

        while (cin >> numNames)
        {
            names.push_back(read_string("First value:"));
        }
    }

this way, you are not doubling the value of i. When starting a for-loop, using i++ will add 1 to i, but will not update i and only returns i with 1 added to it. Using ++i updates and returns i plus 1, and you nolonger need to have the extra line of i++, and this will prevent doubling i.