Store strings in a vector w/o push.back instruction

Hi everybody,

I am working on a program and i need to be able to store an undefined amount of strings that will be introduced by the user in a vector without using the push.back instruction.

I have in mind something like:

1
2
3
4
5
6
7
8
vector <string> words;

string s;
int position = 0;
while (cin >> s) {
    words[position] = b;
    ++position;
}


Obviously this can't be done because the size of the vector has not been defined yet, and we can't define it (I believe) because we don't know the amount of strings that will be introduced.

You can set a size in the constructor or use resize() to add elements to the vector before you try to modify the element. But using push_back() or emplace_back() is much less error prone.

closed account (o3hC5Di1)
Hi there,

You could always do the bounds-checking yourself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
constexpr int INIT_VECTOR_SIZE = 20;

vector <string> words;
words.reserve(INIT_VECTOR_SIZE); //reserve space for 20 strings

string s;
int counter = 1; //create a counter
int position = 0;
while (cin >> s) {
    words[position] = b;
    ++position;
    ++counter;

    if (counter >= vector.capacity())
        words.reserve(words.capacity()+20); //make vector larger
}


Another option would be to use std::vector.at(): http://www.cplusplus.com/reference/vector/vector/at/
Catch the out_of_bounds exception and enlarge the vector accordingly. Although I suppose exceptions are not really meant to do your bounds checking for you.

Hope that helps.

All the best,
NwN
Last edited on
Can you increase the size of the vector like that?

 
++vector.size();
closed account (o3hC5Di1)
Hi,

No, I'm afraid you can't, std::vector.size() just returns an int.

All the best,
NwN
In the following snippet:
words.reserve(words.size()+20); //make vector larger

The reserve function only increases the vector's capacity, it doesn't create any additional elements. If your program exceeds INIT_VECTOR_SIZE elements you will be accessing your vector out of bounds. If you were using the vector.at() function it would throw an exception.

You should be using vector.size() if you want to actually know how many elements your vector contains, and vector.resize() to add elements to your vector. The vector.size() function tells you how many elements the vector contains, the vector.capacity() function tells you how many elements you can add to the vectr before a reallocation will occur.

closed account (o3hC5Di1)
Thanks for pointing out the error jlb - it was what I meant to write, but it's easy to get the two mixed up. I've corrected my post.

All the best,
NwN
This still doesn't solve the problem of out of bounds access:
1
2
    if (counter >= vector.capacity())
        words.reserve(words.capacity()+20); //make vector large 

This still only increases the capacity of the vector not then number of elements contained in the vector. There is a difference between the capacity and the size. The size is how many elements the vector contains. The capacity tells you how many elements the vector can contain before a reallocation occurs.

If you are trying to use a vector without the push_back() method you must insure the vector actually contains elements before you try to alter the element, this is done by either using the constructor to create a vector that is large enough to hold all the elements, or resize() the vector as you require more elements.

1
2
3
4
5
6
7
8
9
10
11
12
13
const int INIT_VECTOR_SIZE = 20;

vector <string> words(INIT_VECTOR_SIZE); //Create a vector with 20 initial blank elements.

string s;
size_t counter = 0; // create a counter
while (cin >> s) {
    // Insure there is an element before trying to alter the element.
    if ((counter + 1) >= vector.size()) 
        words.resize(words.size()+20); //make vector larger

    words[counter++] = s;
}
closed account (o3hC5Di1)
I believe I did call words.reserve(INIT_VECTOR_SIZE); ? (I didn't use the constructor because it showed the OP more clearly what I was doing)

Now you've confused me - I would alter my example as such:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
constexpr int INIT_VECTOR_SIZE = 20;

vector <string> words(INIT_VECTOR_SIZE);
words.reserve(INIT_VECTOR_SIZE); //reserve space for 20 strings

string s;
int position = 0;
while (cin >> s) {
    words[position] = b; //should be enough space the first time
    ++position;

    if (words.size() >= words.capacity())  //did away with counter
        words.reserve(words.capacity()+20); //make vector larger
}



jlb wrote:
This still only increases the capacity of the vector not then number of elements contained in the vector. There is a difference between the capacity and the size. The size is how many elements the vector contains. The capacity tells you how many elements the vector can contain before a reallocation occurs.


Yes - but I can only alter the size by adding or removing elements - which happens by adding the read-in value to the vector. In order to be able to keep adding stuff (ie altering the size), I need to enlarge the capacity of the vector. Or am I seeing this totally wrong? Please do explain if I am, I'm interested to know.

All the best,
NwN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::vector<std::string> seq ;

    std::string str ;
    while( std::getline( std::cin, str) && str != "quit" )
        seq.insert( seq.end(), str ) ;

    for( const auto& s : seq ) std::cout << s << '\n' ;
}
Yes - but I can only alter the size by adding or removing elements - which happens by adding the read-in value to the vector.

No, adding elements happen in one of three ways.

1. When you construct the vector add some elements by using the optional size.

vector<int> vect(10); // Create a vector with 10 initial elements.

2. Use the push_back() or emplace(), insert() methods to add elements. When you use these methods this
happens:

This effectively increases the container size by one, which causes an automatic reallocation of the allocated storage space if -and only if- the new vector size surpasses the current vector capacity.


3. Re-size the vector with the resize() function. When using this method the following happens:

If n is smaller than the current container size, the content is reduced to its first n elements, removing those beyond (and destroying them).

If n is greater than the current container size, the content is expanded by inserting at the end as many elements as needed to reach a size of n. If val is specified, the new elements are initialized as copies of val, otherwise, they are value-initialized.

If n is also greater than the current container capacity, an automatic reallocation of the allocated storage space takes place.

Notice that this function changes the actual content of the container by inserting or erasing elements from it.


Notice how with either push_back() or resize() the vector class modifies the capacity if required.

In order to be able to keep adding stuff (ie altering the size), I need to enlarge the capacity of the vector. Or am I seeing this totally wrong? Please do explain if I am, I'm interested to know.


Yes you are seeing this wrong. You are not altering the size when you access a vector using the index[] or at() methods you are accessing an existing element. If an element doesn't exist you will either access the vector out of bounds, or if using the at() method throw an out of bounds exception.

To access an element of a vector with either the array notation[] or the at() function the element must exist.

You normally don't need to worry about the capacity, the vector will automatically take care of this.

Last edited on
closed account (o3hC5Di1)
*facepalm* - Of course... .insert(), I suppose that was too easy for my idiot brain to consider.

All the best,
NwN
Why are you bending the std::vector class? It wasn't designed for this. This is akin to saying: "I think it would be interesting and useful to be able to use a stack like a queue."
Topic archived. No new replies allowed.