I need to print an array by implementing the use of a function before the main function. So I tried the following function:
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++) {
cout << arr[i];
}
return arr;
}
I encountered two problems when implementing this into the whole code.
First, this is printing what I think is the address of the array and not the actual array. Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument? How can I account for this in my function?
Please keep in mind that I am new to C++ and coding in general. Also, this code was given to me, hence why I do not understand certain aspects of it.
This is my code so you can see what I mean:
#include <iostream>
using namespace std;
// Declare function printArr here
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++)
{cout << arr[i];}
return arr;
}
int main()
{
int arr[5] = {1, 3, 5, 7,9};
int last_num = arr[sizeof(arr)/sizeof(int)-1];
cout << "Before reversing" << endl;
cout << printArr(arr, 5) << endl;
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, 5);
return 0;
}
The declaration and implementation of printArr() is all wrong.
First, this is printing what I think is the address of the array and not the actual array.
The printArr() function itself is printing the contents of the array (well, the first 5 elements anyway), and then returning the address of the array. It is main() that is printing that address afterwards, when it passes the return value of printArr() to std::cout <<.
Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
By getting rid of the return type altogether. There is no good reason to return the array pointer at all in this example, let alone to pass that pointer to std::cout. So printArr() should be returning void, ie nothing.
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument?
Because main() is passing in the element count of the array (5) so that printArr() can know how many elements to actually print, instead of hard-coding that value in the loop. However, your declaration of printArr() does not have a 2nd parameter with which to accept that value, that is why you are getting errors.
How can I account for this in my function?
By adding a 2nd parameter in the function declaration, eg:
#include <iostream>
using namespace std;
// Declare function printArr here
void printArr(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
cout << arr[i] << ' ';
}
cout << endl;
}
int main()
{
int arr[5] = {1, 3, 5, 7, 9};
const int count = sizeof(arr)/sizeof(arr[0]);
int last_num = arr[count-1];
cout << "Before reversing" << endl;
printArr(arr, count);
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, count);
return 0;
}
Live Demo
Related
When using the address transfer of function, View address blocks of formal parameters and actual parameters, I find that the arguments and formal parameters of array share one address block, while the arguments and formal parameters of variables use two address block. What is the reason?
The code is as follows:
#include<iostream>
using namespace std;
void test(int *i,int * arr) {
cout << &i << endl;
cout << arr << endl;
}
int main() {
int i = 1, arr[2] = {1,2};
cout << &i << endl;
test(&i, arr);
cout << arr << endl;
system("pause");
return 0;
}
And this is the output:
0000008986B6FC54
0000008986B6FC30
0000008986B6FC78 //Arrays use the same space
0000008986B6FC78
You are passing pointers to the functions. The value of the pointers are not modified, ie in the function they point to the same objects as they do in main.
However, you are not printing what you think you print:
void test(int *i,int * arr) {
cout << &i << endl;
cout << arr << endl;
}
The pointer i gets the parameter &i (the i from main). Hence printing i in main will yield the same value as printing i in test. However, you are printing the adress of i in the function not the value of it. If you change your code to:
void test(int *i,int * arr) {
cout << &i << endl;
cout << i << endl;
cout << arr << endl;
}
You will notice the difference. I suggest you to rename at least one of the is in your code, because using same name for different entities can and does cause confusion. The i in test holds the value of the address of the i in main. That does not mean that they are the same, but rather i in test has the same value as &i in main.
In short: &i == &i but you expect &(&i) to be the same as &i.
There is no difference between passing a pointer to the int or passing a pointer to the first element of the array. From the point of view of the function they are both just pointers to int.
Note that test prints the value of arr but the location of i.
In test, &i is the location of its argument i.
That argument's value is the location of the i in main.
You will see this if you print i instead of &i.
arr, on the other hand, is implicitly converted into a pointer to its first element, and you are both passing &arr[0] to test to print, and printing &arr[0] in main.
Here is the same thing with explicit conversions and without using a function:
int main() {
int i = 1, arr[2] = {1,2};
cout << &i << endl;
// Create the "argument"...
int *p = &i;
// These two lines are 'test'...
cout << &p << endl;
cout << &arr[0] << endl;
// and this is after the function call.
cout << &arr[0] << endl;
}
This question already has answers here:
What is the purpose of sized array as function argument is c and c++?
(2 answers)
Closed 1 year ago.
Does defining a sized array in a function signature (as opposed to the more commonly used unsized array or pointer syntax) have any bearing at all? My compiler is ignoring it completely, as the following sample code shows (which runs, although it prints some garbage values when a smaller-sized array is passed).
#include <iostream>
using namespace std;
void printArray(int intArray[5]) {
for (int i = 0; i < 5; i++) {
cout << intArray[i] << " ";
}
cout << endl;
}
int main()
{
int array1[1] = {1}; // Smaller array size than in the function signature
cout << "\nInvocation 1\n";
printArray(array1);
int array2[4] = {1, 2, 3, 4}; // Smaller array size than in the function signature
cout << "\nInvocation 2\n";
printArray(array2);
int array3[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // Larger array size than in the function signature
cout << "\nInvocation 3\n";
printArray(array3);
return 0;
}
Does defining a sized array in a function signature (as opposed to the more commonly used unsized array or pointer syntax) have any bearing at all?
No, not the way you do it.
This would on the other hand make intArray a reference to the array you pass as an argument:
void printArray(int (&intArray)[5]) {
for (int i = 0; i < 5; i++) {
cout << intArray[i] << " ";
}
cout << endl;
}
A more generic form would be to make it a function template. This would then be instantiated once for each array size you call it with:
template<std::size_t N>
void printArray(int (&intArray)[N]) {
for (int i = 0; i < N; i++) {
cout << intArray[i] << " ";
}
cout << endl;
}
Does defining a sized array in a function signature (as opposed to the more commonly used unsized array or pointer syntax) have any bearing at all?
No, it has not, the passed array argument will always decay to a pointer to its first element, placing a size is indeed pointless from the compiler standpoint, it will ignore it, having void printArray(int intArray[5]){...}, void printArray(int intArray[]){...} or void printArray(int* intArray){...} will be basically the same.
My compiler is ignoring it completely, as the following sample code shows (which runs, although it prints some garbage values when a smaller-sized array is passed).
Which makes sense because in the loop you are accessing elements outside the bounds of the array, so the behavior is undefined.
This is how I would do it using std::array
#include <array>
#include <iostream>
template<typename type_t, std::size_t N>
void printArray(const std::array<type_t,N>& values)
{
for (const auto& value : values)
{
std::cout << value << " ";
}
std::cout << std::endl;
}
void printArray_s(const std::array<int, 5>& values)
{
for (const auto& value : values)
{
std::cout << value << " ";
}
std::cout << std::endl;
}
// helper function to avoid having to type value of N in std::array (syntactic sugar)
// used for array3
template<typename array_type, typename... args_t>
constexpr auto make_array(const args_t&&... values)
{
return std::array<array_type, sizeof...(args_t)>{ static_cast<array_type>(values)... };
}
int main()
{
// Smaller array size than in the function signature
std::array<int,1> array1{ 1 };
std::cout << "\nInvocation 1\n";
//printArray_s(array1); // <== will correctly give compiler error
// Smaller array size than in the function signature
std::array<int, 4> array2{ 1, 2, 3, 4 };
std::cout << "\nInvocation 2\n";
printArray(array2);
// Larger array size than in the function signature
auto array3 = make_array<int>(1, 2, 3, 4, 5, 6, 7, 8 );
std::cout << "\nInvocation 3\n";
printArray(array3);
return 0;
}
When I'm trying to print the values of an array, its memory location is getting printed instead of values. What am I doing wrong?
int main()
{
int list[3];
for (int i=0; i<3; i++)
{
list[i] = i;
std::cout<<list<<std::endl;
}
}
OUTPUT: 0x7ffffef79550
C++ doesn't provide an overload for arrays when using the iostream library. If you want to print the values of an array, you'll need to write a function or find one somebody else has written.
What's happening under the hood is list is decaying to an int*, and that's what you're seeing printed.
This looks like a typographical error:
std::cout << list
You want to print a specific element of the array, right?
std::cout << list[i]
When printing "the whole array" without index, the pointer to first element is printed (see the other answer for reason).
std::cout << list << std::endl;
You're printing the array object itself. What do you expect to see? The name of the array identifier? The address of the first element in the array? (actually this is what happens in your case). Or do you expect the array to neatly iterate over it's elements and build a comma separated string of all the values and output it to the stream? If this is what you want, you have to implement it yourself.
template <std::size_t N>
std::ostream& operator<<(std::ostream& out, int (&arr)[N]) {
std::copy(std::begin(arr), std::end(arr), std::ostream_iterator<int>{out, ", "});
return out;
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
std::cout << arr << std::endl; // Ok, prints "1, 2, 3, 4, 5, ".
}
You need to dereference the list. Instead of:
std::cout << list << std::endl;
do:
std::cout << *list << std::endl;
My main idea is to shrink they array from both sides . For example if the input is 1234 , wanna print 1234 and then 4321 (the reversed) .
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int reversedArray(int* x)
{
cout<< "*x out of while =" << *x <<endl ;
while( *x != 0 )
{
cout << "*x=" << *x << endl;
cout<< "====================== im in reversed =================" << endl ;
return reversedArray( x+1 );
}
cout<< "after return " << *x << endl;
}
int main ()
{
int Array[] = {10,2,3,4,8 ,0} ;
int* p_Array = Array;
reversedArray( Array );
}
After the "while" , why the functions that are in the stack, do not return to the next line ( " the --> cout<< "after return " <<*x <
void printReversed(int * x)
{
if (*x == 0) return;
std::cout << *x;
printReversed(x+1);
std::cout << *x;
}
The line:
return reversedArray( x+1 );
exits the function. So you never repeat the while or execute any of the code after the while if you go into the while. This makes the while effectively an if statement.
The code posted by Crazy Eddie does the job and Barmar explains the ineffectiveness of the while loop. I decided to post a non-recursive way to address the problem mentioned.
#include <iostream>
#include <vector>
using namespace std;
vector<int> reverseArray(vector<int>& arr) {
vector<int> ans;
int n = arr.size();
// insert all elements in the reverse order
for (size_t i = 0; i < n; i++) {
ans.push_back(arr[n-i-1]);
}
return ans;
}
int main ()
{
int array[] = {10, 2, 3, 4, 8, 0};
// convert into vector
vector<int> arr(array, array+6);
vector<int> rev = reverseArray(arr);
// merging the 2 arrays
arr.insert(arr.end(), rev.begin(), rev.end());
// printArray(arr) -- implement to fit your needs;
}
When you pass an int[] to a function it decays to an int* which is simply an address in memory. C++ a better plan would be to use copy_backward with an ostream_iterator:
copy_backward(Array, Array + sizeof(Array) / sizeof(*Array), ostream_iterator<int>(cout, " "))
Note that this method uses the actual size of the array, and does not depend upon a terminal element. Thus, no numbers are offlimits, and it's impossible to segfault by failing to provide the terminating element.
If you have access to C++11 you can simplify that a bit further to:
copy(crbegin(Array), crend(Array), ostream_iterator<int>(cout, " "))
Live Example
(Disclaimer: Pointers in C++ is a VERY popular topic and so I'm compelled to believe that someone before me has already raised this point. However, I wasn't able to find another reference. Please correct me and feel free to close this thread if I'm wrong.)
I've come across lots of examples that distinguish between pointer to first element of array and pointer to the array itself. Here's one program and its output:
//pointers to arrays
#include <iostream>
using namespace std;
int main() {
int arr[10] = {};
int *p_start = arr;
int (*p_whole)[10] = &arr;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
cout << "Adding 1 to both . . . " <<endl;
p_start += 1;
p_whole += 1;
cout << "p_start is " << p_start <<endl;
cout << "P_whole is " << p_whole <<endl;
return 0;
}
Output:
p_start is 0x7ffc5b5c5470
P_whole is 0x7ffc5b5c5470
Adding 1 to both . . .
p_start is 0x7ffc5b5c5474
P_whole is 0x7ffc5b5c5498
So, as expected, adding 1 to both gives different results. But I'm at a loss to see a practical use for something like p_whole. Once I have the address of the entire array-block, which can be obtained using arr as well, what can I do with such a pointer?
For single arrays, I don't think there's much point to it. Where it becomes useful is with multi-dimensional arrays, which are arrays of arrays. A pointer to one of the sub-arrays is a pointer to the row, and incrementing it gets you a pointer to the next row. In contrast, a pointer to the first element of the inner array is a pointer to a single element, and incrementing it gets you the next element.
int (*)[10] is a "stronger" type than int* as it keeps size of the array,
so you may pass it to function without passing additional size parameter:
void display(const int(*a)[10]) // const int (&a)[10] seems better here
{
for (int e : *a) {
std::cout << " " << e;
}
}
versus
void display(const int* a, std::size_t size) // or const int* end/last
{
for (std::size_t i = 0; i != size; ++i) {
std::cout << " " << a[i];
}
}