Query about vector's range constructor - c++

char mychars[] = { 'A','B','C','D' };
vector<int> a(mychars, mychars + 4);
cout << a[0] << " " << a[1] << " " << a[2] << " " << a[3];
why it's output is
65 66 67 68 ?
i have created vector of int so it should have stored A,B,C,D in one int of 4 bytes but it is storing them individually by creating 4 ints why ?

No. a vector does not know the internal representation of the contained object. When you construct a vector using the range constructor, it will only constructs a container with as many elements as the range [first,last), with each element emplace-constructed from its corresponding element in myChars array, in the same order.

When you pass an array of chars to the constructor, the constructor assumes that the array contains chars and hence loops through the array, casts each char to an integer and creates the vector from the integers.
I guess you could do a little "hack" with pointers in order to achieve
the desired result. Instead of passing a pointer to char to the vector constructor,
you can cast mychars to an integer pointer so that c++ views the 4 bytes consumed
by mychars array as a single integer.
However, you should be careful about the size of the supposed integer array that is used as offset to the constructor.
In your case, the offset is 1 instead of 4, because for every 4 chars you have 1 integer. However, I replaced it with the more general sizeof(mychars)/sizeof(int)) in order to account for arrays with more than 4 elements (the elements of mychar must be a multiple of 4).
#include <iostream>
#include <vector>
using namespace std;
/*
Id is between 0 and 3 (inclusive)
*/
char char_from_int(int number, int id) {
return (number >> (8*id)) & 0xff;
}
int main()
{
char mychars[] = { 'A','B','C','D','e','f','g','h' };
vector<int> a((int*)mychars, (int*)mychars +sizeof(mychars)/sizeof(int));
for(int i=0;i<a.size();i++) {
cout<<char_from_int(a[i],0)<<char_from_int(a[i],1)<<char_from_int(a[i],2)<<char_from_int(a[i],3)<<endl;
}
return 0;
}

Related

Does multi dimension array matter when passing it to a function?

So i have a function and a MD array
int arrayMD[2][2] = { 0,3,6,8 };
void display(int *ptr) {
cout << *(ptr + 1);
}
display(*arrayMD, 2, 2); // Invoke
When I pass the it to the function it will point to a 1-D Array
so the *ptr would point to {0,3} (CMIIW)
When I call a function / invoke
I pass a dereferenced pointer which is : An Address
cout << *arrayMD == Address to the first one which is {0,3}
so the function should be *ptr = Address from dereferenced Argument passed
So when i try to double bracket on the array: ptr[0][1] it doesn't work because it has become 1 dimensional array which consist of {0,3} but when i type ptr[3] it printed out 8. I know how it stored in the memory but is there no limit? so i could just use one dimensional array and print out the value. Then what's the point of 2D array?
I have just started learning C++ so please CMIIW
Let's put it this way first:
void display(int (*ptr)[2]) { // Takes a pointer to an array of 2 ints
std::cout << **(ptr); // Display [0][0]
std::cout << *(*(ptr)+1); // Display [0][1]
std::cout << **(ptr+1); // Display [1][0]
std::cout << *(*(ptr+1)+1); // Display [1][1]
}
int main() {
int arrayMD[2][2] = { 0,3,6,8 };
display(arrayMD); // Here, we pass the pointer to the first element of arrayMD
}
This gives us the following output:
0368
As you know, when we use the name of an array, it is automatically converts to the pointer to the first element. But when we want a pointer to an array, we need involvement of parenthesis:
int *p[100]; // is an array of 100 pointers to int
int (*p)[100]; // is a pointer to an array of 100 int
And yes, in general, consider using Standard Library, in particular the std::array.

Multiplying and displaying the values of an array in C++

I am trying to complete a C++ exercise in which an array is displayed and the user is prompted to input a multiplier, which will result in the initial numbers that were displayed being multiplied by the user's input. Here is the code that I have so far:
#include <iostream>
using namespace std;
int main()
{
int array[5] = { 1, 2, 3, 4, 5 };
for (const auto& a : array)
{
std::cout << a << std::endl;
}
double multiplier;
cout << "Input a multiplier: ";
cin >> multiplier;
for (int array = 1; array <= 5; ++array)
{
array == multiplier * array;
std::cout << array << std::endl;
}
}
When it runs, it prints the correct array, with a newline being created after each array value, and prompts the user for the multiplier. However, when the multiplier is inputted, the values do not change. Here is an example output:
1
2
3
4
5
Input a multiplier: 2
1
2
3
4
5
The goal is to get this output:
1
2
3
4
5
Input a multiplier: 2
2
4
6
8
10
Any help or code improvement would be appreciated, as figuring out how to multiply and display the multiplied values is the only thing needed to be done in order to complete the exercise. Thank you in advance!
There are three big issues with your code:
1. Naming conventions.
Do not name your array and your temporary for loop variable the same thing. This will cause an issue further down the line, which I'll illustrate.
2. Incorrect operator
As minterm has mentioned, you are using a comparison operator instead of the equal operator. But that alone will not fix your issue.
3. Not accessing array values
You are not actually multiplying the array values with the multiplier. You have to access the elements, which means you cannot start the index at 1.
for (int i = 0; i < 5; i++){
array[i] *= multiplier
cout << array[i] << endl;
}
Use = instead of ==. Currently, it just evaluates a logical statement instead of setting it to a new value.
Also, you need to change "int array" in the for loop to a different name so as to not get it confused with the array called array. Call the variable in the for loop something else, like "int i".
So then the line in question would not be "array == multiplier*array", but instead something like "int j = multiplier * array[i]", and then have it print out j instead of array.
A simpler approach would be to use another range-based for loop instead of the indexed version:
for (auto& a : array)
{
a *= multiplier;
std::cout << a << std::endl;
}
If you don't need to update the array itself (after all, your code doesn't actually read from the array again), then you a very similar, though more straightforward version might be applicable:
for (const auto& a : array)
{
std::cout << a * multiplier << std::endl;
}
You have quite a few things going on that are incorrect.
First is your over scoping (maybe not the right term) the array value.
You have an array value declared outside of your for loop, and you're using the value array again inside of the for loop for the counter. So you're not actually doing anything to your array. You're actually trying to do something to the initialization variable.
Second you're using == instead of =
You're using a comparison operator (==) instead of an assignment operator (=), but there's other big no no's going on.
array is an int[5] not just an int
To actually modify each element of your array, you need to reference the index by saying array[index] where index is a value of 0 to length of array - 1, so 4 in your case.
You're using a double multiplier and trying to apply it to an int *
If you try to multiply by a double value like 2.5, your array values are going to be int's and not a number with a decimal value. You should make your int array [] into a double array []
Not accessing your array, starting from index 0
When looping through an array, the first index is always 0. You're using array = 1 and array <= 5. This would skip your first index, and give you an out of bound index at the end. You should use int index = 0; index < 5; index++; instead.
You're trying to print array
Since array is an int [] printing array in the for loop like that will just give you the address of where the array is. You'll have to either print out each index or use the enhanced for loop method after you've applied your multiplier.
If you're wanting to use your above implementation, do this
for (int index = 0; index < 5; index++)
{
array[index] *= multiplier; // Or you can use array[index] = multiplier * array[index]
std::cout << array[index] << std::endl;
}

Are character arrays the only type that have some form of null-termination?

I've read some of my friend's code and seen functions like this:
int foo(int* arr, int n)
{
// ...
}
which he then calls like this:
int myArr [] = {69, 69, 69, 69, 69};
int f = foo(myArr, sizeof(myArr)/sizeof(int));
Now, I understand that sizeof(myArr)/sizeof(int) is dividing the size of myArr in bytes by the size of an int in bytes, thus returning the length of myArray. However, I don't understand how sizeof(myArr) is implemented unless there's some sort of generic null element that terminates arrays and then sizeof(...) works similar to how strlen(...) works:
size_t strlen(char* c)
{
size_t k = 0;
while (*c != '\0')
{
++k;
++c;
}
return k;
}
Now, if sizeof(...) does work similar to that, then I don't see why, when passing an array to a function, you can't simply do
int foo(int* arr)
{
int n = sizeof(arr)/sizeof(int);
// ....
}
which is simpler way of writing functions because the array is essentially being passed in as a single unit that gets unpacked.
My guess is that arrays of non-character type don't have the null-termination property that character arrays do. In that case, how does sizeof(...) work? And what is the point of null-termination in character arrays anyhow? Why are they created differently than any other array?
Anyways, I was wondering whether someone could clear up all the obvious confusion that I have.
sizeof works on arrays because the compiler knows the length at compile time. If you pass that array to a function, it turns into a pointer, at which point the compiler doesn't know the full size of the array anymore.
For example:
#include <iostream>
void printPointerSize(int* a) {
// a is a pointer, and all pointers are 8 bytes (64 bits) on my machine
std::cout << "int* pointer argument has size: " << sizeof a << std::endl;
}
int main() {
// the compiler determines from the initializer that this is an int[5]
int a[] = {1, 2, 3, 4, 5};
// since the compiler knows that a is an int[5],
// then sizeof a is 5 * sizeof int
std::cout << "int[5] has size: " << sizeof a << std::endl;
printPointerSize(a);
}
Output (on a platform with 64-bit pointers and 32-bit integers):
int[5] has size: 20
int* pointer argument has size: 8
Note that if you try to create a function that takes an array as an argument, the compiler will just turn it into a pointer anyway:
void printPointerSize(int a[5]) {
// this will print the size of a pointer,
// not the size of a 5-element int array
std::cout << "int[5] argument has size: " << sizeof a << std::endl;
}
In addition to Brandon's answer, you need to distinguish between array capacity and array size.
Array Capacity
Array Capacity is the maximum number items the array can hold. There can be from 0 to capacity number of items in the array. Which brings up the question, "how many items are in the array?"
Array Size
Array Size is the number of valid items in the array. An array that has a capacity of 20 items, may only have 3 valid items in it.
Example:
char array[20];
array[0] = 'M';
array[1] = 'e';
array[2] = 'a';
array[3] = 't';
The above array has a capacity of 20, but only 4 valid items.
Repeating the question, "How many items are in the array?"
The C++ language does not maintain the number of items in an array. The sizeof operator returns the capacity of an array, but not the size.
The size of an array must be maintained in a separate variable. Some crafty programmers can use an array slot to maintain this value. So when passing an array, you will have to pass: the array (or pointer to it), the capacity and the size. Most starting programmers forget about the size parameter, which leads to many difficult defects that are hard to find.

Having difficulty working with pointers

I having some issue when it comes to initializing pointers.
void findMM (int *PMM, int *theG)
{
// code I haven't written yet. It will essentially take two variables from //theG and store it in MM
}
int main()
{
int size;
int MM [2] = {1000, 0};
int *theG = NULL;
cout << "\nPlease insert size of array:" << endl;
cin >> size;
theG = new int [size];
findMM(&MM, &theG); //Get error with &MM
delete [] theG;
return 0;
}
The complier says that argument of type int (*)[2] is incompatible with parameter of type int ** So obviously that I have issue with the code in particular my (reference?) of array MM. Or perhaps there is other obvious faults that I am missing?
Edit attempt 2
void findMM (int *PMM, int *theG)
{
PMM [1] = 5;
theG [0] = 7;
}
int main()
{
int size;
int MM [2] = {1000, 0};
int *theG = NULL;
cout << "\nPlease insert size of array:" << endl;
cin >> size;
theG = new int [size];
findMM(MM, theG);
cout << MM [1] << endl << theG[0];
delete [] theG;
return 0;
}
The output would be 5 and 7 correct?
Since MM is an array, &MM is a pointer to an array (that's the type int (*)[2] that you see in the error). Instead, you seem to want to pass a pointer to the first element of the array. There are two ways to do that. Firstly, you can explicitly get the first element and then take the address of it: &MM[0]. Secondly, you can rely on array-to-pointer conversion to do it for you and just pass MM. Array-to-pointer conversion converts an array to a pointer to its first element.
I know this question has already been answered but I believe I can contribute to the asker's understanding.
Let's start with the basics:
void main()
{
int a = 2; // a is an int
cout << a << endl; // print 2
int *b; // b is a pointer-to-int
b = &a; // store the address of a in b
cout << *b << endl;// print the value that b points to, which is 2
int my_array = new int[3]; // allocate an array with 3 integers
my_array[0] = 50; // store 50 in the first element of the array
my_array[1] = 51; // store 51 in the second element of the array
my_array[2] = 52; // store 52 in the third element of the array
cout << c[0] << endl; // print 50
some_function(my_array, 3); // explained below
}
Now let's see how to pass arrays into functions. Assume we want to have a function called some_function that receives an array.
void some_function(int *some_array, int size_of_the_array)
{
// use the array however you like here
}
The function some_function receives a pointer to an int (also known as "pointer-to-int"). The name of an array is always the address of its first element, so if a function expects a pointer to an int and you give it the name of an array of ints, you are actually giving it the address of the first element in the array (this is just C++ syntax rules). So the function now has the address of the first element in the array, it can do stuff like *some_array to access the first element in the array, but what if it wants to access the other elements? It adds 1 to the pointer it already has and then applies the * operator to it: *(some_array + 1). Let's say an int is 4 bytes, if you add 1 to a pointer-to-int, the result of this addition is a new pointer that points to a location in memory 4 bytes ahead, so *(some_array + 93) is the value in the 94th element of the array some_array (array elements are stored sequentially in memory). A shorthand notation for this is some_array[93]. So if you have int *some_array = new int[100];, then some_array is a pointer and some_array[93] is the same as *(some_array + 93), which is the 94th element in the array.
The address itself though is not enough, you also need to know the number of entries in the array so that you don't try to access an element past the end of the array. In this example, assume that some_function simply prints the contents of the array, so if you don't provide 3 as the second argument to the function then it will have no way of knowing when to stop adding 1 to the pointer it received in the first argument. Beware, however, that by passing an array to a function this way, you are not passing the function a copy of the array, you are simply telling it where to find its contents in memory.

Pointer and primitive type return different array members

A few things.
When I declare my struct with a member array of size 3, wouldn't that mean that array has 4 elements? 0, 1, 2, 3? Why them, when I try to insert the characters A, B, and C, it tells me initializer-string for array of chars is too long [-fpermissive]?
#include <iostream>
using namespace std;
struct Student {
double no;
char grade[3];
};
int main() {
struct Student harry = {975, "ABC"};
}
When I print the address of a specific index of a character array I get the following results from the following code:
struct Student {
double no;
char grade[4];
};
int main() {
struct Student harry = {975, "ABC"};
for (int i = 0; i < 4; i++)
cout << "h.g[" << i << "]" << harry.grade[i] << endl;
for (int i = 0; i < 4; i++)
cout << "h.g[" << i << "]" << &harry.grade[i] << endl;
}
Results:
h.g[0]A
h.g[1]B
h.g[2]C
h.g[3]
&h.g[0]ABC
&h.g[1]BC
&h.g[2]C
&h.g[3]
Why does the first index print ABC, and then BC, and so forth instead of each character separately like the first loop?
No, declaring an array like T arr[3] gives you an array with 3 elements, not 4. The 3 in the declaration is the size of the array. Indices start at 0, so the indices for the elements are 0, 1, and 2.
The string literal "ABC" gives you an "array of 4 const char" where the last element is the null character. Your program is ill-formed if you attempt to initialise an array with a string literal that has too many characters:
There shall not be more initializers than there are array elements.
In the first loop you are getting each character of the array and printing it out. When you print a char you get only that char as output.
When you take the address of an element of the array, with &harry.grade[i], you get a char*. When you output a char*, the I/O library treats it as a C-style null-terminated string. It will output from that character to the first null character it finds. That's why you get the character at position i and the characters following it.
When I declare my struct with a member array of size 3, wouldn't that mean that array has 4 elements? 0, 1, 2, 3?
No, it means it has three elements, which you can access with indices 0,1,2.
Why does the first index print ABC, and then BC, and so forth instead of each character separately like the first loop?
You are accessing beyond the bound of an array, which leads to undefined behaviour. That means anything could happen. You are also assigning a size-4 character array, "ABC", to a size-3 array. So you have out of bonds read and write access.
The 4th element in char array "ABC" it the null-termination \0. When you print the address of any element of a char[N] with std::cout, it will see a char*, which it interprets as a null-terminated string. So it will print characters up to the null termination. So if you print from the beginning, you get A, b, C. If you print from the second element you get B,C, and so on.