How can I solve this problem with arrays in C++? - c++

I am working on the Edabit challenge: Get arithmetic mean of the given array. Now I have code like that:
#include <iostream>
int data;
using namespace std;
int mean(int data);
int main()
{
int data[] = { 1, 2, 3, 4 };
cout << mean(data);
}
int mean(int data)
{
double mean = 0;
for (int i = 0; i < sizeof(data) / sizeof(data[0]); i++)
{
mean += data[i];
}
mean /= sizeof(data) / sizeof(data[0]);
}
and I am stuck. I use Visual Studio 2019 on Windows 7 Professional, and I have underlined 3 characters ( data[i], and 2x data[0]). For this x Visual Studio says expression must have pointer-to-object type (Error E0142) and I have no idea what it means with this. I only know what pointer is.
In Visual studio I added the return statement, but while shortening the code here for publishing I forgot to add it. Otherwise, this wasn't the actual problem. Now I mustn't add it in the question because the comments would be wrong. The comments are related to the upper question, but my real question (for future readers stuck on this problem) is rather:
How to pass array as an argument in the function.
Now, that I am more proficient in C++, I know the terminology and how to state it, and I also know that this isn't so clear to a total beginner: you can't just write f(int[] arr) (you can't pass arrays), but you have to write f(int* arr) (you can pass a pointer that points on that array). At that time I couldn't just search it because I didn't know much of C++ terminology.

Arrays decay into pointers (an int* in this case) when passed as argument to functions. Your mean function only accepts one single int.
When the array decays into a pointer the size information is lost. You can however prevent that by defining a function that accepts arrays of the exact type and size you need. This can be done with templates:
#include <iostream>
template<typename T, size_t N>
double mean(const T (&data)[N]) {
double sum = 0;
for (size_t i = 0; i < N; ++i)
{
sum += data[i];
}
return sum / N;
}
int main()
{
int input[] = { 1, 2, 3, 4, 5, 6, 7 };
std::cout << mean(input) << '\n';
}
If you don't want to use templates (or only accept arrays of a certain size), you need to pass the size information on to the function manually:
#include <iostream>
#include <iterator> // std::size
double mean(const int* data, size_t N)
{
double sum = 0;
for (size_t i = 0; i < N; ++i)
{
sum += data[i];
}
return sum / N;
}
int main()
{
int input[] = { 1, 2, 3, 4, 5, 6, 7 };
std::cout << mean(input, std::size(input)) << '\n';
}

Your mean function, well, is mean.
1. It doesn't return a value; there is no return statement.
2. It uses variable name the same as the function (not a recommended coding style).
3. There is a global variable data that is hidden by a local variable data inside main.
4. You're confusing the compiler and the reader: the global data variable is a single int. The local variable in main is an array of int.
You should have the last line be:
return mean;

Related

Why am I getting a totally random number when trying to iterate through an array and adding up the sum by using sizeof()?

I am trying to get the size of an array, using that for the expression in my for loop, and getting a random sum when I compile.
#include <iostream>
int main()
{
int prime[5];
prime[0] = 2;
prime[1] = 3;
prime[2] = 5;
prime[3] = 7;
prime[4] = 11;
int holder = 0;
for (int i = 0; i < sizeof(prime); i++)
{
holder += prime[i];
}
std::cout << "The sum of the 5 prime numbers in the array is " << holder << std::endl;
}
The sum I get is 1947761361. Why is this? Shouldn't using the sizeof() function work here?
The sizeof operator returns the size in memory of its operand - in the case of arrays this is thus the number of element multiplied by the size in memory of each one - NOT the number of elements in the array. For that you want sizeof(array)/sizeof(prime[0])
#include <iostream>
int main()
{
int prime[5];
prime[0] = 2;
prime[1] = 3;
prime[2] = 5;
prime[3] = 7;
prime[4] = 11;
int holder = 0;
int arraySize = sizeof(prime)/sizeof(prime[0]);
for (int i = 0; i < arraySize; i++)
{
holder += prime[i];
}
std::cout << "The sum of the 5 prime numbers in the array is " << holder << std::endl;
}
The error is in your use of sizeof(). It returns the total size of what is passed in. You passed in an array of 5 integers. An int is typically 4 bytes, so your sizeof() should return 20.
The bare minimum fix is to change your for loop Boolean Expression:
i < sizeof(prime) becomes i < sizeof(prime) / sizeof(*prime)
It takes the total size of your array (20) and divides it by the size of the first element (*prime) to give you the number of elements in your array.
To explain a bit more about *prime, you need to understand that C-arrays decay to pointers to the first element if you look at them funny. The syntax here de-references the pointer and gives us the actual first element, an int. And so we get the size of an int.
All the stuff below is tangential to your actual question, but I like to put it out there.
Here's your code, squashing your array initialization and using a range-based for loop.
#include <iostream>
int main()
{
int prime[]{2, 3, 5, 7, 11}; // CHANGED: Declare and initialize
int holder = 0;
// CHANGED: Range-based for loop
for (auto i : prime) {
holder += i; // CHANGED: in a range-based for loop, i is the value of each
// element
}
std::cout << "The sum of the 5 prime numbers in the array is " << holder
<< std::endl;
}
The range-based for loop works here because the array is in the same scope as the array. If you were passing the C-array to a function, it wouldn't work.
Here's your code using a Standard Library function:
#include <iostream>
#include <iterator> // std::begin and std::end because C-array
#include <numeric> // std::reduce OR std::accumulate
int main() {
int prime[]{2, 3, 5, 7, 11};
std::cout << "The sum of the 5 prime numbers in the array is "
<< std::reduce(std::begin(prime), std::end(prime)) << std::endl;
}
The need for <iterator> is due to the fact that you are using a C-array. If we instead use a std::array or [better yet] std::vector, we can lose that requirement.
#include <iostream>
#include <numeric> // std::reduce
#include <vector>
int main() {
std::vector<int> prime{2, 3, 5, 7, 11};
std::cout << "The sum of the 5 prime numbers in the array is "
<< std::reduce(prime.begin(), prime.end()) << std::endl;
}
We got rid of the #include <iterator> requirement because std::arrays and std::vectors come with their own iterators. I also got rid of the holder variable completely, as there was no demonstrated need to actually store the value; so we print it directly.
NOTES: std::reduce() requires C++17, which any fairly recent compiler should provide. You could also use std::accumulate() if you wish.
You can specify that you're compiling C++17 code by passing -std=c++17 to the compiler. It's always a good idea to specify what C++ standard you expect your code to run against. And while we're talking about compiler flags, it's in your best interest to enable warnings with -Wall -Wextra at a minimum.
You expect sizeof(prime) == 5,
which will not be.
And int prime[5]; will always should
be known size, so
to avoid problems
use int const sizeOfArray = 5; which then
you can use for the loop.
And for better understanding of what is happening
monitor holder inside the loop with cout/cerr.

How to use `sizeof` operator inside the condition of for-loop properly? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Do the conditions of the for-loop always need constant?
How can I put sizeof function there to run an output showing all the elements of an array?
#include<iostream>
using namespace std;
void array_output(int a[])
{
for (int i = 0; i < (sizeof(a)) / (sizeof(a[0])); i++)
{
cout << a[i] << endl;
}
}
int main()
{
int a[] = { 22, 53, 13, 65, 80, 31, 46 };
array_output(a);
return 0;
}
i<(sizeof(a) output shows first 4 elements
i<(sizeof(a))/(sizeof(a[0])) output shows only the first element
instead of sizeof when 7 is directly used as a condition, it gives
the right output, showing all the elements.
†(This answer is for c++17 users...)
where no need of using sizeof operator at all.
Use instead std::size() function which will get you the size of the given container or array.
#include <iostream>
#include <iterator> // std::size
#include <cstddef> // std::size_t
int main()
{
int a[]{ 22,53,13,65,80,31,46 };
for (std::size_t i = 0; i < std::size(a); i++)
{
std::cout << a[i] << `\n`;
}
}
† Update
The OP has edited the question after posting this answer,
where the std::size can not be applied.
When the array a passed to void array_output(int a[]), it deduced to void array_output(int* a)
instead if of the its actual type int a[7].
i<(sizeof(a) output shows first 4 elements
Here, you are doing size of(int*) (pointer to int), depending up
on the architecture
it could be efferent. In your case it is 32 bit machine which is why you got sizeof(a) = 4.
i < sizeof(a)/ sizeof(a[0]) output shows only the first element
Dividing sizeof(a)(which is sizeof(int*) equal to 4 bytes in
your machine) by sizeof(a[0])(which is sizeof(int), also 4 bytes), is nothing but one and loops only once.
The #Timo's
answer, provide a templated function where size will be a non-type template parameter, which can be accessed directly, without going for sizeof.
How can I put sizeof in function and run an output showing all the
elements of an array?
This is possible only when passing the array a of actual type as it is.
For that, let the array to deduce to its int [7], by forwarding it perfectly.
#include<iostream>
template<typename Type>
void array_output(Type&& a) // deduced to `int a[7]`
{
for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { // or std::size(a)
std::cout << a[i] << '\n';
}
}
int main()
{
int a[] = { 22, 53, 13, 65, 80, 31, 46 };
array_output(a);
return 0;
}
If you use the actual array in the sizeof operator you will get the size of the array in bytes, meaning you can calculate the number of elements like you expected it using sizeof(array) / sizeof(array_type).
int x[] = {1, 1, 1, 1, 1, 1};
int sum = 0;
for (int i = 0; i < sizeof(x) / sizeof(int); i++)
sum += x[i];
// sum == 6
However if you pass the array as a function parameter you will encounter pointer decay. This means that the array size information is lost and you get the pointer size instead, which is the behavior that you described.
int sum(int arr[]) // arr decays to int*
{
int sum = 0;
for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
sum += arr[i];
return sum;
}
int main()
{
int x[] = {1, 1, 1, 1, 1, 1};
return sum(x); // will return 1 or 2, depending on architecture
}
You can still get the array size in the function if you use a template function for it.
#include <cstddef>
template <std::size_t N>
int sum(int (&arr)[N])
{
int sum = 0;
for (int i = 0; i < N; i++)
sum += arr[i];
return sum;
}
int main()
{
int x[] = {1, 1, 1, 1, 1, 1};
return sum(x); // will return 6
}
You can use vector for this.
vector<int> nums{1,2,3,4};
for(std::size_t i = 0; i < nums.size(); ++i)
cout<<nums[i]<<endl;
If you insist on using int a[], you should be aware of the size before traversing it.
By the way, on GCC
sizeof(nums) = sizeof(int) * total number of element
it's not the total number of element.

C++ generic template

Hello all i am just beginning to learn c++ and just looked at templates. I was asked to make a template function print that would take an array and a int input and print out the elements in the array. Here is my code.
#include <iostream>
using namespace std;
template <typename T>
void print(T a[], int b)
{
for(int y=0; y < b; y++)
{
cout << a[y] <<" ";
}
}
int main()
{
int arr[5];
int size = sizeof(arr);
for(int h=0; h<=size; h++)
{
arr[h]=0;
}
print(arr,size);
}
The program compiles with no errors but when I run it there is no output. Can anyone help? or point me in the right direction?
Your program has Undefined Behavior at this point:
for (int h = 0; h <= size; h++)
{
arr[h] = 0;
}
You defined size to be the number of bytes held in the array arr, not the actual number of integers present. Therefore, an integer on your platform is most likely greater than 1 byte, so size will be equal to a number far greater than 5.
And when you do arr[h], you're eventually going to access an address beyond the bounds of the array. It is at that point that your program contracts a case of Undefined Behavior. At that moment, anything in your program can happen, including the output not appearing.
The fix to this problem is to divide the bytes present in arr by the size in bytes of a single int. That will tell you the number of elements:
int size = sizeof(arr)/sizeof(int);
An even better solution is to use std::array so that the size is known and can be accessed through its member function size:
std::array<int, 5> arr{{}};
for (int i = 0; i < arr.size(); ++i)
arr[i] = 0;
Note that using aggregate-initialization on std::array causes zero-initialization of each element. Thus, there is no use for the subsequent for loop.
You'll also need to adapt your function so that it can access an array object:
template<typename T, unsigned N>
void print(const std::array<T, N>& a)
{
for (const auto& x : a) // range-based for loop
{
std::cout << x;
}
}
The error is in the value of the variable size.
int size = sizeof(arr);
gives the size of the array in bytes, it is not 5.
int size = sizeof(arr)/sizeof(arr[0]);
will give the right answer.
It would also be a good idea to add
cout << endl;
at the end of main.

How to pass array in C++

I trying to pass an array but don't understand why it gives me those errors. The code is also available in ideone.com
#include <iostream>
using namespace std;
class Max
{
int max = 0;
public:
int getMax(int array[], int size)
{
for(int num : array)
{
if(num > max)
max = num;
}
return max;
}
};
int main( )
{
Max m;
int arr[5] = { 5, 3, 2, 7, 6 };
cout << "Max number is: " << m.getMax(arr,5);
return 0;
}
The problem here as has been mentioned is that passing an array to a function it decays to a pointer. The fix that involves the least changes is to pass the array by reference like so:
template <int U>
int getMax(int (&array)[U])
this fix is probably not the most intuitive for a beginner though. The fix that requires a bit more changes and probably makes more sense to a beginner is to use std::vector or std::array:
int getMax(const std::vector<int> &array)
and in main:
std::vector<int> arr = { 5, 3, 2, 7, 6 };
cout << "Max number is: " << m.getMax(arr);
The cause is the for(:) can not get the size of "int array[]".
You have a size argument, but the begin() & end() can not use it. You must wrap the begin() and end() member functions or just simple it to
for(int i = 0; i< size; i++)
{
int num = array[i];
if(num > max)
max = num;
}
size argument needs type specified (proper type is size_t).
array in getMax function is a pointer (not an array). You can't use range-based for loop with it. You have to use regular for loop which will make use of size argument.

extracting rows or columns from a 2D-array C++

I'd like to make a function that receives a 2-dimensional array and returns one of its rows ('which') as a simple array. I wrote this:
int *row(int *array, int lines, int columns, int which)
{
int result[columns];
for (int i=0; i<columns; i++)
{
result[i] = *array[which][i];
}
return result;
}
However, in line 7 I got the following error: invalid types 'int[int]' for array subscript. Any idea how to do this properly? I also tried to handle the 2D-array as an array of arrays, but didn't succeed. I'm novice, so please avoid too advanced concepts.
Thanks for the help!
UPDATE: thanks for the help! Now my code looks like:
int n; //rows
int m; //columns
int data[100][100];
int array[100];
int *row(int *array, int rows, int columns, int which)
{
int* result = new int[columns];
for (int i=0; i<columns; i++)
{
result[i] = *array[which*columns+i];
}
return result;
delete[] result;
}
int main()
{
array=row(data, n, m, 0);
}
I still get an error in main: incompatible types in assignment of 'int*' to 'int [100]'
What could be the problem now? I also don't know where to use the delete[] function to free up the array.
Thank you very much for the help!
You can't just do this:
int result[columns];
You need a dynamic allocation:
int* result = new int[columns];
Also, your use of array looks wrong. If array is going to be a single pointer, then you want:
result[i] = array[which*columns + i];
"array" is one dimensional. You can access the element with index [which][i] via: array[which*columns + i]. Also remove the asterisk as the array is only a single pointer.
EDIT: Also you can not return local array - you need to deal with dynamic memory:
int* result = new int[columns];
And then take special care to free this memory. Other option would be to use std::vector.
There are few errors that needs to be fixed first.
You should never return a pointer to a local variable from a function. In the above code, you are trying to return a pointer to contents of 'result' which is a local variable.
An array cannot be declared with a size that is variable, in your case the variable columns.
If array is a two dimensional array, which i think is your intent, then array[which][i] gives you an int.You do not have to de-reference it.
Though I know I am not following the posting etiquette here, I recommend you to please start with a nice text book, grab the basics and come here when you encounter problems.
The size of an array needs to be a compile-time constant.
Instead of messing with arrays, you should probably use std::vector (possibly along with a 2D matrix class).
You can avoid all of this pointer arithmetic and memory allocation by using std::vector
#include <vector>
#include <iostream>
typedef std::vector<int> Row;
typedef std::vector<Row> Matrix;
std::ostream& operator<<(std::ostream& os, const Row& row) {
os << "{ ";
for(auto& item : row) {
os << item << ", ";
}
return os << "}";
}
Row getrow(Matrix m, int n) {
return m[n];
}
Row getcol(Matrix m, int n) {
Row result;
result.reserve(m.size());
for(auto& item : m) {
result.push_back(item[n]);
}
return result;
}
int main () {
Matrix m = {
{ 1, 3, 5, 7, 9 },
{ 2, 4, 5, 6, 10 },
{ 1, 4, 9, 16, 25 },
};
std::cout << "Row 1: " << getrow(m, 1) << "\n";
std::cout << "Col 3: " << getcol(m, 3) << "\n";
}
double *row(double **arr, int rows, int columns, int which)
{
double* result = new double[columns];
for (int i=0; i<columns; i++)
{
result[i] = arr[which][i];
}
return result;
delete[] result;
}
This will return the row.