I know there is a bug in the code, but I am interested to know exactly how C++14 processes the code to output this
3
þÿÿt
With this code
#include <iostream>
void pretty_print(int,int,int);
int main()
{
srand(time(0));
const int LIM = 100;
int a = rand()%LIM;
int b = rand()%LIM;
int c = rand()%LIM;
if(a+b+c<500)
{
pretty_print(a,b,c);
}
else throw new std::invalid_argument("FOOBAR");
return 0;
}
void pretty_print(int a, int b,int c)
{
std::string ans = "";
int count = 0;
if(a!=0)
{
count++;
ans+=(a+" ");
}
if(b!=0)
{
count++;
ans+=(b+" ");
}
if(c!=0)
{
count++;
ans+=(c+" ");
}
std::cout << count << "\n";
std::cout << ans << "\n";
}
P.S. I have deliberately tried to add an integer to a string without conversion in order to examine why the output is such. I want to know why adding an integer without conversion to a string results in such a behaviour.
I want to know why adding an integer without conversion to a string results in such a behaviour.
A string literal is an array of characters. In a value context (such as as an operand of +), an array will be converted into pointer to first element. This implicit conversion is called decaying.
Adding an integer n to a pointer (to an element of an array) will result in a pointer to nth successive sibling of the originally pointed element. For example, "abcd" + 1 will result in a pointer to the characer b. This is called pointer arithmetic.
You generate numbers up to 100, so you end up getting a pointer to up to hundredth index of the string literal. However, the length of the string literal is only 2 (the length of the array includes the null terminator in addition to the length of the string itself), so unless you happened to generate only zeroes and ones, those pointers will be outside the bounds of the string literal.
When a character pointer is passed to the compound assignment operator of std::string, that pointer will be treated as a null terminated pointer to a character string and the pointed object will be accessed.
The behaviour of accessing an array out of bounds is undefined.
In C++ a string literal like e.g. " " is really an array of constant characters. As such it will decay to a pointer to its first element.
What you're doing with a+" " is pointer arithmetic: You add the value of a to the pointer pointing to the first character of " ". In other words, a + " " is equal to &" "[a]. (It helps knowing that for any pointer or array p and index i the expression *(p + i) is exactly equal to p[i].)
Unless the values of your variables is 0 (or 1, which is the index of the terminator), then the values as indexes will be way out of bounds of the array holding " ", leading to undefined behavior.
Related
Trying to fill an array using a pointer so each index of array contains its' index. The output I am currently getting is this +DD;D;DD. Could someone explain where I am going wrong on this? Thanks.
#include <iostream>
using namespace std;
int main()
{
int NUMBER_ELEMENTS;
cout << "Enter number of elements: ";
cin >> NUMBER_ELEMENTS;
short array1[NUMBER_ELEMENTS];
short *arrPtr;
arrPtr = array1;
short i = 0;
while(i < NUMBER_ELEMENTS)
{
*arrPtr = i;
arrPtr = arrPtr + 1;
cout << "+" + array1[i];
i++;
}
}
Problem 1: The length of an automatic array can not be given at runtime. It must be known at compile time. In order to create an array with dynamic length, you can use std::vector instead.
explain how this is a variable length array?
You can input different values in different executions of the program. Therefore the length varies. Even the value staying the same is by itself not sufficient. The expression used the array length must be a compile time constant expression.
Problem 2: "+" + array1[i] doesn't do what you probably think it does.
The string literal is an array of characters. array1[i] is an integer. When you add an integer to an array using the plus-operator, the array decays to a pointer to first element of the array, and the the pointer is incremented by number given as the operand.
Therefore "+" + 0 increments the pointer by zero places, so the string printed in the first iteration is "+". "+" + 1 increments the pointer by one places. After the + character, there is only the null terminator, so the printed string is empty. After that iteration, the later iterations overflow the array, and the behaviour of the program is undefined.
I passed an array of characters to a function and used a pointer to point at the first element of the array.
How do I point through each element of the array and delete the characters I don't want.
I am trying not to use brackets and other variables just this pointer and maybe another one.
Thanks.
if you really want to do it in your way, you have to declare a new array of characters and then count the element of the characters that you want to be left on the array by iterating on the array through your pointer, that count will be the size of the new array.
example:
char b[] = "acbbca";
char* p = &b[0];
int oldsize = 6;
int newsize = 0;
for ( int a = 0; a < oldsize; a++ )
{
if(*p!='b')
newsize++; // increment the newsize when encountered non-b char
p++;
}
in the snippet above, you count the number of non-b characters, so it will be the size of the new array.
p = &b[0]; // point again to the first element of the array.
char newone[size]; declare the new array that will hold the result
int ctr = 0;
for ( int a = 0; a < oldsize; a++ )
{
if(*p!='b')
{
newone[ctr] = *p; //store non-b characters
ctr++;
}
p++;
}
in the snippet above, it stores all non-b characters to the new array.
another way is to use std::string.
std::string b = "aabbcc";
b.erase(std::remove(b.begin(),b.end(),'b'),b.end());
Since arrays cannot be resized, there really is no such thing as "removing elements". To actually remove elements, you would need to use a container such as std::string where elements can actually be removed.
Given this, let's assume you can only use an array, and that "removal" means to move the removed values to the end of the array, and then point to where the removed elements start. The STL algorithm function std::remove can be used to accomplish this:
#include <iostream>
#include <algorithm>
int main()
{
char letters[] = "aabbccbccd";
// this will point to the first character of the sequence that is to be
// removed.
char *ptrStart = std::remove(std::begin(letters), std::end(letters), 'b');
*ptrStart = '\0'; // null terminate this position
std::cout << "The characters after erasing are: " << letters;
}
Output:
The characters after erasing are: aaccccd
Live Example
The std::remove just takes the character you want to remove and places it at the end of the array. The return value of std::remove is the point in the array
where the removed elements were placed. Basically the return value points to where the discarded elements start (even though the elements aren't actually discarded).
So if you now write a function to do this, it would probably look like this:
void erase_element(char *ptr, char erasechar)
{
char *ptrStart = std::remove(ptr, ptr + strlen(ptr), erasechar);
*ptrStart = '\0'; // null terminate this position
}
Live Example 2
We pass a pointer to the first element, and use the strlen() function to determine how long the string is (the function assumes the string is null-terminated).
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.
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.
this was an example given to us in class. Could someone explain to me why this prints 29 addresses instead of 29 "0" (zeroes) ?
int num[29]; is an array which has set aside 29 addresses for 29 integers -i get that part, but in the for loop you arent u printing the values IN those addreses rather than the addresses themselves?
also, whats the difference between (num+i) and (num[]+i)?
I'm a little confused..
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int num[29];
for (int i=0;i<29;i++)
cout << (num+i) << endl;
return 0;
}
The reason for printing addresses is that
(num+i)
Is the address of the ith element of the array, not the ith element itself. If you want to get the ith element, you can write
*(num + i)
Or, even better:
num[i]
As for your second question - the syntax (num + i) means "the address i objects past the start of num, and the syntax (num[] + i) is not legal C or C++.
Hope this helps!
A declaration such as:
int num[29];
defines a contiguous array of 29 integers.
To access elements of the array use num[i] where i is the index (starting at 0 for the 1st element).
The expression num on its own gives a pointer (memory address and type) of the first element of the array.
The expression ptr + i (where ptr is a pointer and i is an integer) evaluates to a pointer that is i positions (in units of the type of pointer) after ptr.
So num + i gives a pointer to the element with index i.
The expression &a gives a pointer to some object a.
The expression *ptr gives the object that some pointer ptr is pointing at.
So the expressions a and *(&a) are equivalent.
So num[5] is the same as *(num+5)
and num+5 is the same as &num[5]
and num is the same as &num[0]
When you print a pointer with cout it will show its address.
When you print an object it will print the value of the object.
So
cout << num + 5;
will print the address of the 5th (zero-indexed) element of num
and
cout << num[5];
will print the value of the 5th (zero-indexed) element of num