is it possible to access an element within array of array? - c++

i have an array b[i] which stores the certain indices of another array a[i];both are integer arrays
Is it possible to access it as
a[b[i]]
#include <iostream>
using namespace std;
int main()
{
int k=0,v=0,i,b[10],c[10];
int a[]={1,2,3,4,5,6,7,8,9,10};
for(i=0;i<10;i++){
if(a[i]%2==0)
{b[k]=i; k++;}
}
for(i=0;i<10;i++)
{
c[v]=a[b[i]];
v++;
}
return 0;
}
results in segmentation fault

In your second loop, the b array is only half initialized (once for every even number from 1 to 10) so when you try to dereference b[5] you get undefined behavior and hence a segfault

It works fine until you get to i = 5 for the second loop. When i = 5, a[b[5]] is undefined because b[5] is uninitialized. After the first loop, you have b[] = {1, 3, 5, 7, 9, ....} the rest is uninitialized. Try to initialize b[10] and it should work.
b[10] = {};

This method should work:
a[b[i]];
I'm not 100% sure it will work though, because the compiler has a role to play here too. For example, it works perfectly in TC++...
A better way to do it is this:
for(i=0;i<10;i++)
{
int temp=b[i];
c[v]=a[temp];
v++;
}

Here is the reason for the error you see:
'Segmentation fault' in this case means that you used a[] array index well beyond a value within memory available to the process (note: it does not need to be beyond the memory range of your computer to get this error; also note that using indexes slightly bigger than array size usually do not cause segmentation faults; but such index value is still a semantic error, of course).
When you declare b[], you do not initialize it (and that is usual).
Your first loop only initializes selected elements of b[]: only as much elements from the beginning of b[], as there are even numbers in a[] (you use the condition:a[i]%2==0).
Currently, you have 5 even numbers in a: 2,4,6,8,10. This is sufficient to initialize elements of b[0]...b[4]. The elements of b[] starting with b[5] are left uninitialized, i.e. contain numbers which can be considered random, or trash. You can print b[5]...b[9] to see what do they contain without initialization – it is often 0’s (making debugging even harder, because a[0] does not cause segmentation faults - but a[0] is probably not what you want to get in c[]).
But in different runs of your program elements of b[] starting with b[5] can be anything (and then any of them can make a segmentation fault, e.g. a[-2000000000]).
Chances are extremely low that these accidental values will represent valid indexes of a[].
Relief: change your SECOND loop so it runs only k times, not 10 times. This was probably your initial intention, anyway:
for(i=0;i<k;i++)

#include <iostream>
using namespace std;
int main()
{
int k=0,v=0,i,b[10],c[10];
int a[]={1,2,3,4,5,6,7,8,9,10};
for(i=0;i<10;i++){
if(a[i]%2==0)
{b[k]=i; k++;}
}
for(i=0;i<5;i++)
{
c[v]=a[b[i]];
v++;
}
return 0;
}
works well

Related

Why are vectors' size static and we still can add more values?

I'm a complete beginner to C++ but I have some basics knowledge in programming (Python mainly) and I'm trying to learn C++. As the question implies, vectors have static sizes (at least what I've read in my learning material) but we still can add more values to what the size authorize. I wrote a simple code to know what error I get if I pass more values to a vector than the limit authorized by it's size and surprisingly I didn't get any error.
The code are these simple lines:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int it=0,a;
vector<int> v(10);
for(a=1; a<21; a++)
{
v[it]=x;
cout << v[it] << endl;
it++;
}
cout<<"Values stored in v";
for(i=0;i<it;i++)
cout<<v[i]<<" ";
cout<<endl;
cout<<"Vector's size : "<<v.size()<<endl;
return 0;
}
What I get with cout<<"Values stored in v"; are all values from 1 to 20, but I still get that the size is 10.
If that can helps I'm on Windows 10 x64 and using Qt Creator compiler.
What is fixed is
sizeof( vector<int> )
A vector can contain varying number of elements, but that elements are stored on the heap, hence do not contribute to the vectors sizeof. The number of elements is v.size() (and that can change).
You create a vector with 10 elements:
vector<int> v(10);
But then you attempt to access elements that do not exist in the loop. For example v[10] will not cause a compiler error, it is also not guaranteed to cause a runtime error. Nevertheless, it is guaranteed wrong. Accessing the vector out of bounds causes undefined behavior. The output of the code could be anything.

Why starting for loop at i=1 giving me segmentation fault in this vector problem?

I am trying to create a variable sized array which will help me store values and will allow me to retrieve and print the value as query asks. I actually completed this problem but as I am new to coding part, I just wanted to ask why using for loop starting from i=1 to i<=n gives me segmentation fault?
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n, n1, data, q1, q2, q; /*n is number of variable length arrays and q is queries*/
cin>>n>>q;
vector< vector<int> > a(n); //vector as suited for to take input in number of arrays required
for(int i=1;i<=n;i++)
{
cin>>n1; //number of element in first array index
for(int j=1;j<=n1;j++)
{
cin>>data;
a[i].push_back(data);
}
}
for(int i=1;i<=q;i++)
{
cin>>q1>>q2; /*taking input queries as array index and then inside that second query pointing to variable array elements*/
cout<<a[q1][q2]<<endl;
}
return 0;
}
When you declare a vector like this:
vector< vector<int> > a(n);
it has size n. Indexing in c++ (and in fact, most programming languages), starts from 0 and goes to n-1.
If you index into a vector of size n with the index n (as you are doing in your for loop), this is an out of bounds index, and invokes undefined behavior. The result of undefined behavior is that the program can do anything. A segmentation fault is actually a good result, since you can fix the bug before anything too unpleasant happens.
You can also try indexing into a vector with .at(). This is also wrong, but it's a different kind of wrong; it's defined behavior, and it's defined to throw a std::out_of_range exception telling you exactly what you did wrong.
When you first declared the vector, you gave it n elements, which are from 0 to n - 1. However, in your for loop, i can reach upto n, which causes a segmentation fault (or vector subscript out of range) when you try to modify a[i], since it doesn't exist yet.

Enter elements into dynamic (pointer-defined) array in C++?

I want to ask a question regarding entering elements in a dynamic array. I declare an array and then I want to enter elements in it. How can I do this using pointers into the array arr[] that I have declared previously?
Thanks in advance!
#include <iostream>
#include <algorithm>
using namespace std;
int *n = new int ;
int main()
{
cin>>*n;
int *arr = new int[*n];
int *i=new int;
for(*i=0; *i<=*n; *i++)
{
//Here, I should enter the elements but I cannot figure out how?
cin>>(*arr+i);
}
return 0;
}
While I question your usage of pointers for the size of the array and the index (They should just be int n; and int i = 0;, respectively), you can fix your code by using the subscript operator, or in code:
cin >> arr[*i];
Using pointer arithmetic is just unclear and makes it hard to tell what your goal is (In case you're wondering, the correct notation is *(arr+*i), which looks horrible IMO).
On a side note, consider using std::vector as a container, which will make your life a lot easier and prevent you from having to deal with pointers. Usage of std::vector may look like:
int main()
{
std::vector<int> arr;
for (int x; std::cin >> x;)
{
arr.push_back(x);
}
return 0;
}
This would prevent you from having to ask the user for the size of the std::vector as well and allow them to keep entering elements until they enter an EOF.
Here I am not changing your original approach at all so that you can understand pointer concept a bit more clear. As you know that array and pointer address calculation are exactly same. First you need to calculate the address and then dereference it. You just need to change it like below:-
cin>>*arr++;
Also you need to change your for loop like below:-
for(*i=0; *i<=*n; (*i)++)
But now after the above for loop you are going to face problem. The reason is that after storing each element in arr we have incremented the address of arr(arr++), so after the end of for loop arr is now pointing to the last element ( because arr = arr+*n). So first simply try with the below code:-
cout<<*arr<<endl<<endl;
if you have entered five numbers for example 0,1,2,3, and 4 the above statement will print some junk value as pointer is increment one more time.
now try with below:-
arr--;// Now arr will point to last element i.e. 4
cout<<*arr<<endl<<endl;
Hence you need one more int pointer and should store the first address of arr in it like below:-
int *arr = new int[*n];//exactly after this line of code
int *first = arr;
Now use a for loop to print the array:-
arr = first; //pointing to the first eliment
for(*i=0; *i<=*n; (*i)++)
{
//Here, I should enter the elements but I cannot figure out how?
cout<<*arr++<<endl;
}

why should i use back_inserter in function generate_n?

hi guys i will show three codes 1 and 2 makes same work but the third one doesnt work. I want to understand why doesnt work or why do work the other two ? (strrand function produces random string)
1.
int main(){
vector<string> svec(50);
randomize();
generate_n(svec.begin(), 20, strrand);
display(svec.begin(), svec.end());
return 0;
}
2.
int main() {
vector<string> svec;
randomize();
generate_n(back_inserter(svec), 20, strrand);
display(svec.begin(), svec.end());
return 0;
}
3.
int main(){
vector<string> svec;
randomize();
generate_n(svec.begin(), 20, strrand);
display(svec.begin(), svec.end());
return 0;
}
The third has undefined behavior. In the first, you specify the vector size where you define the vector. That means it starts as a vector of 50 default-initialized (empty) strings. You then overwrite those strings with your random strings.
In the second, you use a back_insert_iterator to add the strings to the vector individually.
In the third, you start with an empty vector, and you attempt to use the (invalid) iterator to its (nonexistent) beginning. You then write 20 strings starting at whatever spot in memory its (random) initial value happens to refer to. You have not, however, at any time actually inserted a string into the vector. A vector normally keeps a count of how many items it current contains; in your third case, that will start out 0, and remain 0 throughout. When you attempt to show the "contents", you should get nothing (though, since you've already had undefined behavior at that point, anything is possible -- especially if some of the data you wrote happened to overwrite part of the vector's internal data.
What you have is a marginally more subtle (but equally problematic) version of well known beginner mistakes like:
char *s;
strcpy(s, "This will give UB");

c++ for_each() and object functions

I have an assignment that is the following:
For a given integer array, find the sum of its elements and print out the final
result, but to get the sum, you need to execute the function for_each() in STL
only once (without a loop).
As of now this is my code:
void myFunction (int i) {
cout << " " << i << " " << endl;
}
int main() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
vector<int> v(array[0], array[10]);
for_each( v.begin(), v.end(), myFunction);
return 0;
}
But for some reason the output shows up as 4198853, at first I thought it was a memory address but I figured out that was wrong. Any idea's as to what I might be doing wrong?
vector<int> v(array[0], array[10]);
This doesn't do what you want. array[0] is the first value (1). array[10] is in invalid access past the end of your array. To pass pointers to the vector constructor, you want:
vector<int> v(array, array+10);
Well, there's a couple problems beyond what people have said so far. One is your fault and the other is, in my opinion, a problem with the assignment.
You're printing out the elements, not the sum. The assignment asks for the sum so...you're doing it wrong. You need some call X that sums up all the values and sticks that into a variable for later printing.
The other problem is that std::for_each is not the appropriate algorithm for this task. In fact, it's so much not the appropriate algorithm that it's not even guaranteed to work without a lot of funky hacks to make all copies of the functor you pass in to for_each share the same counter. Maybe this is what your teacher wants you to figure out how to do, but I have a feeling (having experienced the common ability of programming instructors) that he/she doesn't actually know that they're teaching you wrong. The main gist of the problem is that implementations of std::for_each are free to make any number of copies of the function object passed in to recursive or utility calls to produce the standard behavior of for_each.
The appropriate algorithm to use is std::accumulate. In any production code I'd refuse to write, or accept from another team member, use of std::for_each to produce sums. However, I'd probably respond to this situation with a fugly hack and comment mentioning that for_each is the wrong algorithm. Something like so:
struct fugly_functor
{
int * summation_variable; // using a local copy will result in correct answer, or a completely wrong answer depending on implementation of for_each
fugly_functor(int * c) : counter(c) {}
void operator(int x) { *summation_variable += x; }
};
...
int my_sum;
std::for_each(array, array+ELEM_COUNT, fugly_functor(&my_sum));
std::cout << my_sum << std::endl;
Then I'd suggest my teacher familiarize himself with the complete set of standard C++ algorithms.
The correct way would look something like so:
int my_sum = std::accumulate(array, array+ELEM_COUNT, 0);
why not just:
for_each( array, array+10, myFunction);
I'm quite sure that int* can be used as iterator
EDIT: just checked this, it can indeed
In this line:
vector<int> v(array[0], array[10]);
You've indexed out of bounds of your array. This causes undefined behavior.
Also, the constructor for vector you used doesn't do what you think. You've used:
vector(initial value, count);
array has indexes 0..9, so array[9] = 10
if array[10] doesnt throw an error it will contain erroneous data, causing this problem.
The array has 10 elements so 10 is not a valid array index.
vector<int> v(array[0], array[10]);
^^
What you want is:
vector<int> v(array, array + sizeof(array) / sizeof(int) );
You need to take the address of array[0] and array[sizeof(array) / sizeof(*array)]. Vector constructor takes iterator types (i.e. pointers in this context), it can't magically determine the value of array[1] from the value of array[0].
You're not constructing the vector right. The constructor that takes two integers is
vector(size_type _Count, const Type& _Val);
So _Count is 1 and _Value is an undefined value past the end of the array.
If you really want to compute the sum, std::accucumulate is what you want, not for_each
I know you were told to use for_each, but I would actually do this - perhaps an alternative for extra credit ;-)
#include <numeric>
using namespace std;
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sum = accumulate(array, array + (sizeof(array) / sizeof(int)), 0);
accumulate is expressly designed for summing the elements of an iterable range.