I'm trying to assign an array's values to a vector. It seems to be working fine for one vector, but when I do it for a second, I'm getting back garbage values. I cout the number and I know it's correct, but it's not assigning correctly. I don't understand because it's working fine for the first vector.
int sorted[] = {0,1,2,3,4,5,6,7,8,9,10};
// make two smaller arrays, do this untill they are a base case size;
void split(int *dataIN, int dataSize){
// new data will be broken up into two vectors with each half of the
// original array. These will be size firstHalfSize and secondHalfSize.
int firstHalfSize;
int secondHalfSize;
vector<int> firstHalf;
vector<int> secondHalf;
// test to see if array in is odd or even
bool isOdd;
if (dataSize%2 == 1){
isOdd = true;
}else if (dataSize%2 == 0){
isOdd = false;
}
// determine length of new vectors
// second half is firstHalf + 1 if odd.
firstHalfSize = dataSize/2;
if (isOdd){
secondHalfSize = firstHalfSize + 1;
}else if (!isOdd){
secondHalfSize = firstHalfSize;
}
// assign first half of dataIn[] to firstHalf vector
cout << "firs: " << firstHalfSize << endl;
for (int i = 0; i < firstHalfSize; i++){
cout << "a: " << dataIN[i] << endl;// make sure i have the right number
firstHalf.push_back(dataIN[i]);// assign
cout << "v: " << firstHalf[i] << endl;// make sure assigned correctly
}
// do the same for second half
cout << "second: " << secondHalfSize << endl;
for (int i = firstHalfSize; i < (firstHalfSize+secondHalfSize); i++){
cout << "a: " << dataIN[i] << endl;
secondHalf.push_back(dataIN[i]);
cout << "v: " << secondHalf[i] << endl;
}
}
int main(void){
split(sorted, sizeof(sorted)/sizeof(int));
return 0;
}
This is my result. As you can see the first vector push_back went fine and the array values (after "a: ") are also correct.
firs: 5
a: 0
v: 0
a: 1
v: 1
a: 2
v: 2
a: 3
v: 3
a: 4
v: 4
second: 6
a: 5
v: -805306368
a: 6
v: 2
a: 7
v: -805306368
a: 8
v: 0
a: 9
v: 0
a: 10
v: 0
In the second case, you are indexing from firstHalfSize.
You need to cout the values starting from index 0. For example:
cout << "v: " << secondHalf[i-firstHalfSize] << endl;
You are iterating firstHalf from 0 to firstHalfSize with the variable i, so i will be within the range of firstHalf, when you use operator[] - in the second vector's case, i does not mean the same thing.
The filling of the vector is working. It is just your debug output that is incorrect. When outputting values from secondHalf you need to use indexes from 0, not from firstHalfSize.
You can write your code more simply if you take advantage of the std::vector range constructor that takes a pair of iterators. Array pointers can be treated as iterators:
void print(const std::vector<int>& data){
for(int value : data)
std::cout << value << " ";
std::cout << "\n";
}
void split(int *dataIN, int dataSize){
auto firstHalfSize = (dataSize + 1) / 2;
std::vector<int> firstHalf(dataIN, dataIN + firstHalfSize);
std::vector<int> secondHalf(dataIN + firstHalfSize, dataIN + dataSize);
std::cout << "firstHalf: ";
print(firstHalf);
std::cout << "seconHalf: ";
print(secondHalf);
}
Live demo
Related
I need to insert for every element of vector it's opposite.
#include <iostream>
#include <vector>
int main() {
std::vector < int > vek {1,2,3};
std::cout << vek[0] << " " << vek[1] << " " << vek[2] << std::endl;
for (int i = 0; i < 3; i++) {
std::cout << i << " " << vek[i] << std::endl;
vek.insert(vek.begin() + i + 1, -vek[i]);
}
std::cout << std::endl;
for (int i: vek) std::cout << i << " ";
return 0;
}
OUTPUT:
1 2 3
0 1 // it should be 0 1 (because vek[0]=1)
1 -1 // it should be 1 2 (because vek[1]=2)
2 1 // it should be 2 3 (because vek[2]=3)
1 -1 1 -1 2 3 // it should be 1 -1 2 -2 3 -3
Could you explain me why function insert doesn't insert the correct value of vector? What is happening here?
Note: Auxiliary vectors (and other data types) are not allowed
During the for loop, you are modifying the vector:
After the first iteration which inserts -1, the vector becomes [1, -1, 2, 3]. Therefore, vec[1] becomes -1 rather than 2. The index of 2 becomes 2. And after inserting -2 into the vector, the index of the original value 3 becomes 4.
In the for loop condition, you need to add index i by 2, instead of 1:
#include <iostream>
#include <vector>
int main() {
std::vector < int > vek {1,2,3};
std::cout << vek[0] << " " << vek[1] << " " << vek[2] << std::endl;
for (int i = 0; i < 3 * 2; i+=2) {
std::cout << i << " " << vek[i] << std::endl;
vek.insert(vek.begin() + i + 1, -vek[i]);
}
std::cout << std::endl;
for (int i: vek) std::cout << i << " ";
return 0;
}
I am trying to understand vectors and assign(). I am following syntax of
vectorname.assign(int Num, int value)
Below is the sample code. To my understanding 'value' will be assigned to 'Num' of elements in a vector. My query is why after assign() even the size() of container is getting changed. This should occur only when my container is small and the 'Num' is greater. Please correct me if I am wrong in my understanding.
int main()
{
cout << endl << "---- assign() on already ----" << endl;
// Assign vector
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
cout << "Size : " << v.size() << endl;
cout << "Capacity : " << v.capacity() << endl;
cout << "The vector elements are: ";
for (int i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << endl;
// fill the array with 10 five times
v.assign(5, 10);
cout << "Size : " << v.size() << endl;
cout << "Capacity : " << v.capacity() << endl;
cout << "The vector elements after assign() using size() are: ";
for (int i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << endl;
return 0;
}
std::vector::assign:
Replaces the contents with count copies of value value.
void print(std::vector<int>& v){
std::cout << "size " << v.size() << "\n";
for(auto& i: v)
std::cout << i << " ";
std::cout << "\n";
}
int main(){
std::vector<int> vec(10, 2);
print(vec);
// size 10
// 2 2 2 2 2 2 2 2 2 2
vec.assign(5, -1);
print(vec);
// size 5
// -1 -1 -1 -1 -1
vec.assign(15, 3);
print(vec);
// size 15
// 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
}
Demo
If you want to fill N values of your vector with a value from the given start point use std::fill_n
int main(){
std::vector<int> vec(10, 2);
print(vec);
// size 10
// 2 2 2 2 2 2 2 2 2 2
std::fill_n(vec.begin(), 5, -1) // Fills first 5 values with -1
// size 10
// -1 -1 -1 -1 -1 2 2 2 2 2
std::fill_n(vec.begin(), 15, 3); // Error. Since going out of bounds.
}
Demo
std::vector::assign replaces the content of the vector.
See here: std::vector<T,Allocator>::assign
Therefore the following line replaces the current content of v with 5 elements of value 10.
v.assign(5, 10);
This is why the size() is changes from 9 to 5.
The capacity however does not have to change. The capacity relates to the size of the actual block of memory that was allocated to store the vector's elements. It can be equal or greater than the number of actual elements.It was 9 and can stay 9. You can use std::vector::shrink_to_fit to attempt to reduce the allocated memory.
But as you can see here: std::vector<T,Allocator>::shrink_to_fit,
It depends on the implementation whether the request is fulfilled.
fuction assign() will release the old memory totally, and request a new memory section, the new size is 'Num', then copy the the 'value' to every element to the new memory.
I am trying to split one large user given vector into x sub vectors. Everything "seems" to work as it should but the outcome is not right.
std::vector<std::vector<std::string>> split_to_sub_vectors(std::vector<std::string> initial_vector, int thread_amount) {
std::cout << "initial size: " << initial_vector.size() << std::endl;
int size_for_splitting = initial_vector.size();
std::cout << "split amount: " << thread_amount << std::endl;
int r = size_for_splitting / thread_amount;
std::cout << r << " need to be in each sub-vector" << std::endl;
std::cout << "There will be: " << size_for_splitting % thread_amount << " element remaining" << std::endl;
std::vector<std::vector<std::string>> perm_vector;
for (int x = 0; x < thread_amount; x++) {
std::vector<std::string> temp_vector;
for (int a = 0; a < r; a++) {
hm++;
std::cout << hm << std::endl;
temp_vector.push_back(initial_vector[hm]);
}
perm_vector.push_back(temp_vector);
}
std::cout << "Size of vector holding the sub vectors after splitting: " << perm_vector.size() << std::endl;
std::cout << perm_vector[0][0];
return perm_vector;
Running this code will give you this:
initial size: 7
split amount: 3
2 need to be in each sub-vector
There will be: 1 element remaining
1
2
3
4
5
6
Size of vector holding the sub vectors after splitting: 3
2
the vector i pass in is called test holds strings and is like so:
test.push_back("1");
test.push_back("2");
test.push_back("3");
test.push_back("4");
test.push_back("5");
test.push_back("6");
test.push_back("7");
Everything up until the last print statement seems to work. So perm_vector should hold 3 sub vectors containing every element in the main user given vector. When you print perm_vector[0][0] you would expect the output to be "1", but it is 2, also 7 should not be in the vector and 6 should be the last one but since it starts at 2, 7 is in it. the counter is defined outside of the function and it starts at 0. My question is why is it starting at 2?
I see two problems in your code:
hm is incremented before use. Furthermore, there is no point in making it global.
size_for_splitting is the result of an integer division, so the remainder is missing
I modified your code so the issues with hm are solved. I get the intended output <<1, 2>, <3, 4>, <5, 6>>, the 7 is missing as mentioned above.
#include <iostream>
#include<vector>
#include<string>
std::vector<std::vector<std::string> > split_to_sub_vectors(std::vector<std::string> initial_vector, int thread_amount) {
std::cout << "initial size: " << initial_vector.size() << std::endl;
int size_for_splitting = initial_vector.size();
std::cout << "split amount: " << thread_amount << std::endl;
int r = size_for_splitting / thread_amount;
std::cout << r << " need to be in each sub-vector" << std::endl;
std::cout << "There will be: " << size_for_splitting % thread_amount << " element remaining" << std::endl;
std::vector<std::vector<std::string> > perm_vector;
int hm = 0;
for (int x = 0; x < thread_amount; x++) {
std::vector<std::string> temp_vector;
for (int a = 0; a < r; a++) {
std::cout << hm << std::endl;
temp_vector.push_back(initial_vector[hm]);
hm++;
}
perm_vector.push_back(temp_vector);
}
std::cout << "Size of vector holding the sub vectors after splitting: " << perm_vector.size() << std::endl;
return perm_vector;
}
int main()
{
std::vector<std::string> test;
test.push_back("1");
test.push_back("2");
test.push_back("3");
test.push_back("4");
test.push_back("5");
test.push_back("6");
test.push_back("7");
std::vector<std::vector<std::string> > out = split_to_sub_vectors(test, 3);
}
Even if hm starts at 0, you increment it before you use it. Probably if you increment at the end of the internal for loop, you might get the output you expect. It's hard to tell the problem because I don't know what's in 'initial_vector', I assume initial_vector[0] = 1?
If you use the range-v3 library, implementing this logic becomes much easier, and less error prone:
#include <range/v3/all.hpp>
namespace rs = ranges;
namespace rv = ranges::views;
auto split_to_sub_vectors(std::vector<std::string> initial_vector, int thread_amount) {
auto res = initial_vector
| rv::chunk(thread_amount)
| rs::to<std::vector<std::vector<std::string>>>;
if (res.back().size() != thread_amount)
res.pop_back();
return res;
}
Here's a demo.
I'm doing some stuff with vectors and I'm trying to write a program that can loop through and perform operations on objects inside a vector. I've read a lot about minimal code so I've programmed this little application to illustrate the problem.
The output of this program is:
Element 1 is equal to 2
Element 2 is equal to 4
Element 1 is equal to 2
Element 2 is equal to 4
Press any key to continue...
The output should be:
Element 1 is equal to 2
Element 2 is equal to 4
Element 1 is equal to 7
Element 2 is equal to 9
Press any key to continue...
Why am I not achieving the desired output?
#include <vector>
#include <iostream>
// Some object
class A {
public:
A(int data)
: data(data)
{}
int data;
};
class B {
public:
// A function that adds a new 'A' object to the vector in class b
void push_back_to_vector(A &element);
// A function that changes the data of the objects stored in vector_of_a
void add_to_vector();
// A vector to hold objects of A
std::vector<A> vector_of_a;
};
void B::push_back_to_vector(A &element) {
vector_of_a.push_back(element);
}
void B::add_to_vector() {
for (size_t i = 0; i < vector_of_a.size(); i++) {
// Add five to all the elements in the vector
vector_of_a[i].data += 5;
}
}
int main() {
A element_1(2);
A element_2(4);
B b;
b.push_back_to_vector(element_1);
b.push_back_to_vector(element_2);
std::cout << "Element 1 is equal to " << element_1.data << std::endl;
std::cout << "Element 2 is equal to " << element_2.data << std::endl;
// This should change element_1.data to 7 and element_2.data to 9
b.add_to_vector();
std::cout << "Element 1 is equal to " << element_1.data << std::endl;
std::cout << "Element 2 is equal to " << element_2.data << std::endl;
system("pause");
return 0;
}
The push_back copies new elements. If you want to do what you seem to want to do, you need to store pointers to A, not just A.
Basically, your code is just this:
A element_1(2);
A element_2(4);
std::cout << "Element 1 is equal to " << element_1.data << std::endl;
std::cout << "Element 2 is equal to " << element_2.data << std::endl;
std::cout << "Element 1 is equal to " << element_1.data << std::endl;
std::cout << "Element 2 is equal to " << element_2.data << std::endl;
system("pause");
return 0;
Everything related to B doesn't work. Try this:
class B {
public:
// A function that adds a new 'A' object to the vector in class b
void push_back_to_vector(A *element);
// A function that changes the data of the objects stored in vector_of_a
void add_to_vector();
// A vector to hold objects of A
std::vector<*A> vector_of_a;
};
void B::push_back_to_vector(A* element) {
vector_of_a.push_back(element);
}
void B::add_to_vector() {
for (size_t i = 0; i < vector_of_a.size(); i++) {
// Add five to all the elements in the vector
vector_of_a[i]->data += 5;
}
}
And pass pointers:
b.push_back_to_vector(&element_1);
b.push_back_to_vector(&element_2);
Of course, be aware of the lifetime of the objects on the stack that you are pointing to in B.
I'm trying to get the last defined element in a C++ vector, but both vector::capacity and vector::size are just giving me the max size. For example:
int main() {
char* array = new char[MAX_SIZE]; //MAX_SIZE is a const int equaling 100
std::cout << "Enter in a number: ";
std::cin >> array;
std::vector<char> cVector;
cVector.reserve(MAX_SIZE);
cVector.assign(array, array + MAX_SIZE);
for (std::vector<char>::const_iterator i = cVector.begin(); i != cVector.end(); ++i)
{
std::cout << *i;
}
std::cout << std::endl;
std::cout << "Size: " << cVector.size() << std::endl;
std::cout << "Actual size: " << cVector.capacity() << std::endl;
}
Sample Output:
Enter in a number: 55
55
Size: 100
Actual size: 100 [Should say 2]
I've tried using vector::end() and similar methods, but there's no way for me to get the index of the last element.
When you call reserve(MAX_SIZE), you change the capacity, so the output 100 is what it should be. That loop where you print out the values, actually iterates all 100 times, but all the remaining chars are \0, so std::cout interprets those pointers as empty strings. Here is a slightly modified version that create a proper vector, so vector.back() will point to the last element and vector.end() to the next position in memory.
int main() {
std::string s;
std::cout << "Enter in a number: ";
std::cin >> s;
std::vector<char> cVector;
cVector.reserve(MAX_SIZE);
cVector.assign(&s[0], &s[0]+s.size());
for (std::vector<char>::const_iterator i = cVector.begin();
i != cVector.end(); ++i)
{
std::cout << *i;
}
std::cout << std::endl;
std::cout << "Size: " << cVector.size() << std::endl;
std::cout << "Actual size: " << cVector.capacity() << std::endl;
}
UPDATE: Note that I used std::string only to make it more C++-ish. You can keep using char[], just you need to replace your original assignment with:
cVector.assign(array, array + strlen(array));
size() gives the length of the vector (the number of elements actually in it, not the number of elements that it can currently fit). You're seeing the same number because you call assign(array, array + MAX_SIZE) on the vector, which will obviously fill it with MAX_SIZE elements.