How does C++ handle vectors when passing from a function to main? - c++

I'm seeing strange behaviour in the output of a 'simple' function that generates the binary representation of an integer. I aim to use the function in another code, but first want to see it working by printing to the console. I first define the function dec2bin to take a number and the length of the required bitstring. After defining a vector that will be returned by the function, the vector is populated with the required binary values. In the main function, the vector is accessed and printed element-wise to the console. However, the output is incorrect unless I include an arbitrary cout statement within the vector populating for loop.
The function is defined as follows:
vector<int> dec2bin(int N, int j){
vector<int> myvec;
myvec.push_back(N);
for (int i = N-1; i >= 0; i--) {
int r = j >> i;
if (r & 1)
myvec[N-i-1] = 1;
else
myvec[N-i-1] = 0;
//cout << " ";
}
return myvec;
}
My main function is:
int main(){
int length = 8;
int num = 15;
vector<int> myvec = dec2bin(length,num);
for (int j=0; j<length; j++){cout << myvec[j];}
return 0;
}
When the commented out line (cout << " ") is included within the for loop the output is correct, with 00001111. Without that line (or with the line outside of the for loop) the output is incorrectly 00001141130.
I have read various things about pointers and memory allocation, so expect this is where I am going wrong; however, I can't quite see how to incorporate those ideas into my own code. Any advice would be greatly appreciated, many thanks.

On this line:
myvec[N-i-1] = 1;
You are invoking undefined behavior for any index other than 0.
myvec.push_back(N); pushes a single element to the vector, and you never add more elements to the vector. When you access a vector out of bounds, you will not get a compiler error or runtime exception, but your code has undefined behavior, which means the output could be literally anything.
Actually, it seems like you just confused push_back() with resize(). And instead of resize(), you can pass the size to the constructor. If you replace:
vector<int> myvec;
myvec.push_back(N);
with:
std::vector<int> myvec(N);
or:
std::vector<int> myvec;
myvec.resize(N);
You get a vector with N elements, and accessing myvec[i] is fine for any index 0 <= i < N. Alternatively, you could call myvec.reserve(10) to let the vector allocate space for N elements. The vector will then still be empty, and you have to push_back() any element you want to add.

You are accessing the unallocated memory because you only pushed back(push_back()) once and due to it you are getting undefined behaviour.
You should use .at() function instead of [] operator for accessing the vector element, it'll throw the exception out of bounds.
You need to use push_back() for insertion into the vector or you can use vector.resize(size) during vector declaration then it'll save you from undefined behavior.
Thanx

Related

push_back iterator in vector?

I tried to store the number 1,4,7...97 into a vector.
if I use std::out << i; the for loop is working.
but the push_back gives an error:
base of member reference is a function perhaps you meant to call it with no arguments.
i googled it and couldn't find a answer which helped me.
The only thing I found was this:
"In C++ adding elements to a vector
may cause reallocation of the contained data,
which will invalidate all iterators. That means
you can't loop over the vector using iterators
(which is what the range-based for loop does)
while also inserting new elements.
You can however iterate using indexes and use
the vector size as condition, since indexes will always be the same."
but do I loop over the vector?
I thought I just store the iterator
I appreciate every help
std::vector<int>rock();
int i;
for (int i = 1; i < 100; i+=3)
{
std::cout<< " " << i;
rock.push_back(i);
}
std::vector<int>rock(); is a .. function declaration.
use std::vector<int>rock; or std::vector<int>rock{}; instead.
The vector declaration
std::vector<int>rock();
is actually a function declaration, that returns a vector.
That's not what you intended. Drop the ():
std::vector<int> rock;

Segmentation fault: 11 c++ when using vector

i am trying to write a program for my university project the program is supposed to do first come first serve scheduling i have thought a lot about this function but i don't know how to make it work, i always get Segmentation fault: 11, i also tried to use temp.at(j) but it gave me Segmentation fault: 6, and i tried to minimise the vector so it would be in-bound by declaring the vectors outside the function, then use temp.size() instead of Processes but it also did't work.
void FCFS(Process ProcessDetails[], int Processes)
{
vector<int> temp;
vector<int> temp1;
int first = 0; //first value to compare with.
for(int j = 0; j < Processes; j++){ // to make sure that it passes through all elements.
for(int i = 0; i < Processes; i++){ // pass each PID and Burst time to vector temp and temp1.
if(ProcessDetails[i].ArrivalTime == first){
temp.operator[](j) = ProcessDetails[i].PID;
temp1.operator[](j) = ProcessDetails[i].BurstTime;
}
}
first++;// increase first value to declare the round is finished and start a new one.
}
for(int i = 0; i < Processes; i++){ // pass the sorted vector values back to the arrays.
ProcessDetails[i].PID = temp.operator[](i);
ProcessDetails[i].BurstTime = temp1.operator[](i);
}
}
the program works fine until it reaches this function, please help.
The behaviour of a vector's operator[]() is undefined if it is used to access elements that do not exist.
Since you have used default-constructed vectors, their size is zero - so they have no elements to access.
If you use the .at() member function, it will check the index and throw an exception (of type std::out_of_range, which is declared in the standard header <stdexcept>) when indices are invalid. You can confirm that by wrapping the code in an appropriate try/catch block.
To eliminate the problem, you need to reize the vector (e.g. add elements to it using push_back(), resize it using resize(), etc) before using operator[](). And ensure the index is valid, since operator[]() does not resize a std::vector.
Also, temp[j] is equivalent to temp.operator[](j). For types that supply an operator[]() function, the compiler handles turning expressions like temp[j] into a call of temp.operator[](j).
Your vectors have no elements.
Using the vector operator[] will therefore fail.
Use push_back, emplace, resize, or some other function to add elements to the vectors.
you will have to change your vector assignment to
if(ProcessDetails[i].ArrivalTime == first){
temp.push_back(ProcessDetails[i].PID);
temp1.push_back(ProcessDetails[i].BurstTime);
}

Assign a pointer to an array

I am trying to create an array that generates random values, then assign a pointer to that array in order to use it in other functions.
Question 1: Is this the right approach?
Question 2: When I run the code below, my pointer function generates values inconsistent with what the actual array's value is. What am I doing wrong?
int size = 100;
int theray[size];
for(int i=0; i<size; i++)
{
theray[i] = (rand()%100);
}
//Output array
cout<<"The array: ";
for(int j=0; j<size; j++)
{
cout<<theray[j]<<" ";
}
cout<<endl;
int (*parray)[100] = &theray;
cout<<"The array pointer: ";
for(int k=0; k<size; k++)
{
cout<<*parray[k]<<" ";
}
Question 1: is this the right approach?
No. The right approach is to use std::vector<int> if size is not known at compile time1, and std::array<int, size> if it is2. There is no need for pointers here.
void foo(const std::vector<int>& v)
{
// do stuff with v
}
...
std::vector<int> v(size); // vector with size elements
// do something with v
// pass v to a function
foo(v);
Question 2: when I run the code below, my pointer function generates values inconsistent with what the actual array's value is. What am I doing wrong?
If you use C++ idioms you won't even encounter this problem, so I consider the question moot. However, in your case you have a problem of operator precedence: be explicit about applying de-reference * before access []:
cout<< (*parray)[k] << " ";
1 As shown in the example, you can use an std::vector as a fixed size array, where the size need not be known at runtime. Just bear in mind that it is possible to change it's size after construction.
2In your example, size is not a compile time constant so you cannot use std::array. However, if you had declared it as const int size = 100; then it would be considered a compile time constant.
Your code is a bit off in three ways. First, there is no need to use &theray. Array names already reference a memory address. You can simply assign the pointer to theray. Second, you're declaring an array of 100 pointers. Based on your description, it sounds like you just want one pointer that points to the array. Your declaration should just be int *parray instead of int *parray [100]. Finally, once you have a pointer to the array, you can access elements of the array the same way you would with the original array, only with the name of the pointer, instead of the name of the array. Try changing your last block of code (starting with the pointer declaration to this:
int *parray;
parray = theray;
cout<<"The array pointer: ";
for(int k=0; k<size; k++)
{
cout<<parray[k]<<" ";
}
Question 1
Is this the right approach?
Usually not. It depends on what you are trying to achieve.
For high level semantics you'd in most cases use std::vector<int> or, if the size is fixed and you are using C++11, std::array<int, size>. If you actually have to go down to the pointer level, you'd usually write it like this:
int *parray = theray;
cout<<"The array pointer: ";
for(int k=0; k<size; k++)
{
cout<<parray[k]<<" ";
}
This works because arrays will degrade to pointers, and the […] subscripts work on these pointers just like they work on the original arrays.
Question 2
When I run the code below, my pointer function generates values inconsistent with what the actual array's value is, what am I doing wrong?
*parray[k] gets interpreted as *(parray[k]) while you intend to use it as (*parray)[k].
Question 1: is this the right approach?
No. Use std::vector<> for arrays whose size can change dynamically (at run-time). Prefer avoiding pointers and manual memory management.
Question 2: when I run the code below, my pointer function generates values inconsistent with what the actual array's value is. What am I doing wrong?
First of all, the fact of creating pointers so you can pass the array to a function. This is not necessary. Here is how I would use classes from the C++ Standard Library to write that program (in C++11):
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
// Sample function that prints the vectors's content
void foo(std::vector<int> const& v)
{
copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, " "));
}
int main()
{
// Populate the vector...
size_t sz = 10;
std::vector<int> v(sz);
generate(begin(v), end(v), [] () { return rand() % 100; });
// Pass it to a function...
foo(v);
}

Vector <int> input and output

I am stuck with simple vector input and output operations. The compiler returns error saying 'std::outof range'
Here is the code
int main()
{
int size;
cout <<"Enter size of vector\n";
cin>>size;
cout<<"Now to input the vector of size "<<size<<endl;
vector <int> trial;
for (size_t i=0;i<size;++i){
int x;
cout<<"write at position"<<trial.at(i)<<'t';
cin>>x;
trial.push_back(x);
cout<<endl;
}
ostream_iterator<int> output(cout,"");
copy(trial.begin(),trial.end(),output);
}
I would appreciate a brief explanation of the internal workings of the problem.
You invoke trial.at(i) before trial.push_back(x), accessing a not yet existing element. Since the element doesn't (yet) exist, i is an invalid index, and at() will throw a std::out_of_range exception when passed an invalid index. If an exception isn't caught, it will terminate the program. Presumably your platform's runtime library displays the exception that caused the program to be terminated.
I suppose what you actually want is this:
std::cout << "write at position " << i << '\t';
Consider the first iteration of this loop:
vector <int> trial;
for (size_t i=0;i<size;++i){
int x;
cout<<"write at position"<<trial.at(i)<<'t';
At the first iteration nothing has been pushed into the vector, so trial.at(0) isn't yet valid. The result will be an exception. Since you don't have a try/catch anywhere, that will end your program's execution.
It looks to me like you want cout << "write at position " << i; instead. i is the position; after it has been pushed onto the vector so it's valid, vector.at(i) will be the value at that position.
trial.at(i)
You're accessing an element that doesn't exist.
You probably want cout<<"write at position"<< i <<'t'; anyway.
The problem is this line:
cout<<"write at position"<<trial.at(i)<<'t';
You call this before you have set the size of the vector. I'm not really sure what that line is trying to accomplish anyway. If you're trying to print the in memory position (address) that won't do it, if you're trying to print what was already there then it would work if it had already been allocated. Using vector::push_back() means that you don't need to preallocate though.
You can fix this by resizing the vector and accessing the elements directly like this:
trial.resize(size);
// loop
// vector.push_back(x) -- now becomes
vector[i] = x;
Or, you can simply remove the printing of the position and use push_back() as you are now.
Since it seems you're investigating how to use vector I would suggest trying to gain an understanding of how the push_back() and resize() methods differ, and have also have a look at the vector::reserve() function.

C++ getting the size of an array

I'm new to programming and I was wondering, how to get the size of an array, that is, get the size of how many elements are inside the array. For example if I declare an array of size 10, but only input 3 elements into the array, how would I determine the size of this array? If I don't know how many elements I placed in initially.
If you declare an array, e.g. int array[10], then its size is always 10 * sizeof(int). There is no way to know how many times you've accessed it; you'd need to keep track of that manually.
You should consider using container classes, e.g. std::vector:
std::vector<int> vec;
vec.push_back(5);
vec.push_back(10);
vec.push_back(42);
std::cout << vec.size() << "\n"; // Prints "3"
If you declare an old-style array of 10 elements, e.g. std::string words[10], the size of the array is always 10 strings. Even with the new style (std::array), it would be a fixed size.
You might be looking for a std::vector<>. This doesn't have a fixed size, but does have a .size() method. Therefore, if you add three elements to it, it will have .size()==3
to get the array size (in number of elements) assuming you do not know it in advance
use sizeof(a)/sizeof(a[0])
see the below example program. I used C but it should carry over to C++ just fine
#include <stdio.h>
int main(){
int a[10];
printf("%d elements\n",sizeof(a)/sizeof(a[0]));
return 0;
}
//output: 10 elements
There's several possible ways, but they depend on your definition.
If you know there is a value the user won't input (also known as a sentinel value), you can use a function like memset, to set the entire array to that unused value. You would then iterate through the list counting all the variables in the list that don't match that value.
The other way is to build your own array class, which counts whenever the array is modified (you'd have to overload the = and [] functions as appropriate).
You could also build a dynamically linked list, so as the user adds variables, the count can either be determined by walking the list or keeping count.
But, if you're taking the array as the basic array, with no idea as to it's actual starting state, and no idea what to expect from the user (given this is your program, this shouldn't occur), then generally speaking, no, there is known way to know this.
You maintain a counter variable count initialized to 0.
Whenever you are adding to array increment the count by 1.
Whenever you are removing from array decrement the count by 1.
anytime count will give you the size of the array.
Suggestion:
int[10] arr;
//init all to null
for (int i =0; i < 10; i++)
arr[i] = 0;
arr[0]=1;
arr[2]=5;
int sz = 0;
for (int j = 0; j < 10; j++)
if (arr[j] != 0) sz++;