C-Array Sum using Pointers? - c

I made this program to find the sum of an array using pointer, but it crashes when I run it. Why is this happening and what did I do wrong?
int GetValue(int *p[], int size)
{
int i, sum = 0;
for(i = 0 ; i < size ; i++)
{
sum += *p[i];
}
return sum;
}
int main()
{
int Array[6] = { 20, 30, 40, 50, 60, 70 };
int Array_Sum;
Array_Sum = GetValue(&Array[6], 6);
printf("Array Sum= %d", Array_Sum);
return 0;
}

This ...
int Array[6] = { 20, 30, 40, 50, 60, 70 };
declares 'Array' as an array of 6 int. Note well that the declared name is 'Array', not 'Array[6]'. The latter expression, outside the context of a declaration, would designate the element at index 6 in that array if the array were long enough, but the array is not long enough, having only 6 elements, at indices 0 - 5.
If, again, the array were long enough, &Array[6] would evaluate to the address of the seventh element of Array (at index 6), but you presumably want to pass the address of the first element (at index 0). The expression &Array[0] would be one way to write that, but most people would instead simply write Array, which is completely equivalent. That is, you should call your function like so:
Array_Sum = GetValue(Array, 6);
You furthermore have a problem with your GetValue() function:
int GetValue(int *p[], int size) {
[...]
Parameter p is declared as a pointer to pointer to int. That is, the function signature is exactly equivalent to
int GetValue(int **p, int size) {
But what you're actually passing (and indeed what you want to pass) is an int *. You can write that either like this ...
int GetValue(int *p, int size) {
... or if you prefer, like this ...
int GetValue(int p[], int size) {
. Having done so, inside the function you should access the array elements as p[i], not *p[i].

Correction needed is here:
p[i] means *(p+i)
so,
*p[i] means **(p+i)
corrected function:
int GetValue(int *p, int size) //*p[] is for passing a 2D array ,pass 1D only as your need
{
int i, sum = 0;
for(i = 0 ; i < size ; i++)
{
sum += p[i]; //correction here that's why it crashes
}
return sum;
}
as p already is a pointer no need to derefence it.
live demo here http://ideone.com/kI1hXA
Thanks #JohnBollinger for pointing its 2D argument in getValuefunction in question.

I changed some things in your code
int GetValue(int *p, int size)
{
int i, sum = 0;
for(i = 0 ; i < size ; i++)
{
sum += p[i];
}
return sum;
}
int main()
{
int Array[6] = { 20, 30, 40, 50, 60, 70 };
int Array_Sum;
Array_Sum = GetValue(&Array[0], 6);
printf("Array Sum= %d", Array_Sum);
return 0;
}

The code is to be changed to -
int GetValue(int p[], int size)
{
int i, sum = 0;
for(i = 0 ; i < size ; i++)
{
sum += p[i];
}
return sum;
}
int main()
{
int Array[6] = { 20, 30, 40, 50, 60, 70 };
int Array_Sum;
Array_Sum = GetValue(Array, 6);
printf("Array Sum= %d", Array_Sum);
return 0;
}

Related

How do I declare an empty array as a function parameter correctly?

I'm currently doing some free exercises on codeStepByStep, and I particularly don't know how to solve the max_row one.
I need to input a 2D array as a function parameter, but it keeps showing me this error:
note: declaration of ‘arr’ as a multidimensional array must have bounds for all dimensions except the first *
It seems like arrays should at least have a predefined column length, but it can't be dynamic like that right?
Here is my code :
int max=row(int numColumn, int arr[][numColumn], int numRow) {
int i, j, sum = 0, maxSum = 0, a, b=0;
for (i=0; i<numRow; i++) {
for (j=0; j<numColumn; j++) {
sum = arr[i][j] + sum;
}
if (maxSum < sum) {
maxSum = sum;
a = i;
}
if (maxSum = sum) {
b = i;
}
if (b < a) {
a = b;
}
}
return a;
}
int main()
{
int list[4][3] = {
{ 3, 8, 12},
{ 2, 9, 17},
{ 43, -8, 46},
{203, 14, 97}
};
printf("%d", max_row(3, list, 4));
return 0;
}
After asking here and there I found that I should start by declaring the column variable, so instead of this :
int max_row(int arr[][numColumn], int numRow, int numColumn)
it should be something like this as in the code above:
int max_row(int numColumn, int arr[][numColumn], int numRow)
but it won't be tested by the website.
The test question:
Write a function named max_row that accepts a number of rows and columns, and a 2-D array of integers, as parameters and that returns the index of the row where the elements add up to the greatest value. For example:
int list[4][3] = {
{ 3, 8, 12},
{ 2, 9, 17},
{ 43, -8, 46},
{203, 14, 97}
};
Then the call of max_row(list, 4, 3) should return 3. If there is a tie between two or more rows, return the row with the smaller index.
Your code should work for an array of any size at least 1x1.
Everything in main is me trying to see if the code works.
It's because you can't declare a multi-dimensional array with a variable as dimension (c and c++ don't support it unless you declare them in the heap memory).
A solution could be this one:
#define MAX 10
int row(int numColumn, int arr[][MAX], int numRow)
{
int i, j, sum = 0, maxSum = 0, a, b = 0;
for (i = 0; i < MAX; i++) {
for (j = 0; j < MAX; j++) {
sum = arr[i][j] + sum;
}
if (maxSum < sum) {
maxSum = sum;
a = i;
}
if (maxSum == sum) {
b = i;
}
if (b < a) {
a = b;
}
}
return a;
}
In the first line you declare a constant named MAX with value 10, then you use it to initialize the array.
Also I don't understand the use of maxSum and b, since you never actually use maxSum (you just initialized it) and you don't return b.
Plus you didn't even initialize a (you can't return a not initialized variable).
Moreover REMEMBER that you have to write == to make a comparison in an if statement, not =.

Write a C function GetEvenNumber

For my studies, I have to write a C function GetEvenNumber:
parameters: array with n integers + array size;
returns tr array which contains even integers from td.
I don't know a priori the length of the array tr.
My below code returns errors:
#include <stdio.h> // define the header file
int *GetEvenNumber(int t[], int size)
{
int tr[];
int j = 0;
for (int i = 0; i < size; i++)
{
if (t[i] % 2 == 0)
{
printf("%d is even \n", t[i]);
tr[j] = t[i];
j++;
}
}
return tr;
}
int main() // define the main function
{
int *t; // = {4, 3, 1, 8, 6 };
int *tr = GetEvenNumber(t, 5);
for (int i = 0; i < 5; i++)
printf("%d \n", tr[i]);
}
I get error:
error: array size missing in 'tr'
int tr[];
warning: function returns address of local variable [-Wreturn-local-addr]
return tr;
How do I fix that? Thanks.
You mentioned that you could not use malloc() to dynamically create tr within GetEvenNumber() to address the two issues raised by your copmiler. This leaves making tr a global variable, or as here pass in the result array tr to be filled out:
#include <stdio.h>
#include <stdlib.h>
void GetEvenNumber(size_t size, const int *td, size_t *size2, int *tr) {
*size2 = 0;
for(size_t i=0; i<size; i++)
if(td[i] % 2 == 0)
tr[(*size2)++] = td[i];
}
int main() {
int td[] = {4, 3, 1, 8, 6 };
size_t size = sizeof(td) / sizeof(*td);
int tr[size];
size_t size2;
GetEvenNumber(size, td, &size2, tr);
for (size_t i=0; i < size2; i++)
printf("%d \n", tr[i]);
}
If the input array td contains uneven elements, then the result array tr have fewer valid elements than the input. I used size2 here to tell caller how many elements are valid in tr. Your code did not assign any values to, in this example, last 3 elements. You don't tell us what should happen with those last elements.
In modern C, if you specify the size before the array in the argument, then you can use the size in array specification which help document what is going on.
The error is due to
int tr[];
because you have to specify the size of your array during its creation.
I suggest trying to add a function that returns the number of even numbers in the array:
int getEvenNum(int t[], int lent){
int numEven = 0; // initialize counter to zero
for(int i = 0; i < lent; i++){ // for each element of the array
if ((t[i] % 2) == 0){ // if it's even,
numEven++; // add 1 to counter
}
}
return(numEven); // finaly returns the value of the counter
}
and then you replace the int tr[]; by int tr[getEvenNum(t, size)]; (maybe there's a ; after the getEvenNum(t, size) but I'm not sure)
Since the array tr can have AT MOST the same number of elements as the original integer array, it would be safe to declare the array with the same size as the array 't[]'.
I have made some changes to your code. Try the following:
#include<stdio.h> // define the header file
void GetEvenNumber(int *t, int* tr, int size, int *pCountEven)
{
int i, j=0;
for (i=0; i < size; i++)
{
if(t[i]%2==0)
{
printf("%d is even \n", t[i]);
tr[j++] = t[i];
}
}
*pCountEven = j;
}
int main() // define the main function
{
int t[] = {4, 3, 1, 8, 6 };
int tr[5], countEven = 0, i;
GetEvenNumber(t, tr, 5, &countEven);
for (i=0; i < countEven; i++)
printf("%d\n", tr[i]);
return 0;
}
Edit: As #chqrlie (who is an experienced coder) pointed out, we can simply return the length of the array instead of taking the address of a variable.
So alternatively, you can try this:
#include <stdio.h> // define the header file
int GetEvenNumber(int *t, int *tr, int size) {
int i, j = 0;
for (i = 0; i < size; i++) {
if (t[i] % 2 == 0) {
printf("%d is even \n", t[i]);
tr[j++] = t[i];
}
}
return j;
}
int main() // define the main function
{
int t[] = { 4, 3, 1, 8, 6 };
int tr[5], countEven = 0, i;
countEven = GetEvenNumber(t, tr, 5);
for (i = 0; i < countEven; i++)
printf("%d\n", tr[i]);
return 0;
}

array of scores

Given an array of scores where 60 is the highest and 36 is the passing. The function will return an array of all passing scores
#include <stdio.h>
#include <stdlib.h>
int* passingScores (int scores[], int size);
int main () {
int B[] = {55, 35, 60, 25, 10, 43}; //expect display 55,60,43
int size = 6;
int* C;
int i;
C = passingScores(B, size);
for (i=0; i<size; i++) {
printf ("%d\n", C[i]);
}
return 0;
}
code of function:
int* passingScores (int scores[], int size) {
int i;
int passingScore = 36;
int* pass;
pass = (int*)malloc(sizeof(int)*size);
if (pass != NULL) {
for (i=0; i<size; i++) {
if (scores[i] > passingScore){
pass[i] = scores[i];
}
}
}
return pass;
}
elements in the array in main are:
55, 35, 60, 25, 10, 43
the result after the function call would be:
55, 0, 60, 0, 0, 43
but I wanted to have a result like:
55, 60, 43
pls help :) thank you!
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
You should not use magic numbers like in this declaration
int size = 6;
The size of the original array can be calculated.
The function passingScores does not change the original array. So its first parameter should be declared with the qualifier const like
const int scores[]
The user of the function need to know how many elements were passed the test. So it is better when the function returns the number of the passed scores and accepts the pointer to the potentially allocated array from the user by reference.
Instead of the magic number 36 declared within the function
int passingScore = 36;
it is better to pass such a number as a function argument. In this case the function will be more flexible.
You are allocating redundant memory in the function. You should at first count the number of the passed scores. The original array of scores can be very big but its elements that passed the test can be very few.
And for the array pointed to by the pointer pass you need to use a separate index to store selected values sequentially.
And do not forget to free the allocated memory.
Here is a demonstrative program that shows how the function can be implemented.
#include <stdio.h>
#include <stdlib.h>
size_t passingScores( const int scores[], size_t size, int passingScore, int **passed );
int main( void )
{
int scores[] = { 55, 35, 60, 25, 10, 43 };
const size_t SIZE = sizeof( scores ) / sizeof( *scores );
int passingScore = 36;
int *passed_scores = NULL;
size_t n = passingScores( scores, SIZE, passingScore, &passed_scores );
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", passed_scores[i] );
}
putchar( '\n' );
free( passed_scores );
return 0;
}
size_t passingScores( const int scores[], size_t size, int passingScore, int **passed )
{
size_t n = 0;
for ( size_t i = 0; i < size; i++ )
{
n += passingScore < scores[i];
}
if ( n != 0 )
{
*passed = malloc( n * sizeof( int ) );
if ( *passed != NULL )
{
for ( size_t i = 0, j = 0; i < size; i++ )
{
if ( passingScore < scores[i] ) ( *passed )[j++] = scores[i];
}
}
}
return n;
}
The program output is
55 60 43
The following code includes several suggestions, including adding an additional index to keep track of only passing scores, and using calloc instead of malloc to initialize the array. (see other comments and suggested changes below.)
int* passingScores (int scores[], int size);
int main (void) // Or use: int main(int argc, char *argv[]){...}
{ //But never: int main(){...}
int B[] = {55, 35, 60, 25, 10, 43}; //expect display 55,60,43
//int size = 6;//do not use magic numbers
int size = sizeof(B)/sizeof(B[0]);//yields number of elements in array B
int* C;
int i;
C = passingScores(B, size);
if(C)//test before using
{
for (i=0; i<size; i++) {
if(C[i] != 0) printf ("%d\n", C[i]); //include only passing scores
//(excluding zeros)
}
free(C);//free memory when done.
}
return 0;
}
int* passingScores (int scores[], int size) {
int i, j = 0;//additional index j to track passing scores.
int passingScore = 36;
int* pass;
//pass = (int*)malloc(sizeof(int)*size);//allocates un-initialized memory
pass = calloc(size, sizeof(int));//calloc initializes memory to zero
if (pass != NULL) {
for (i=0; i<size; i++) {
if (scores[i] > passingScore){
pass[j] = scores[i];
j++;//indexed only when passing score
}
}
}
return pass;
}
Some notes on using calloc/malloc...
For your purposes, the contents of memory allocated using malloc is provided as is, including whatever contents happened to occupy that space before your process was granted ownership. On my machine and using malloc, the space is occupied with:
pass[0] == 0xBAADFOOD (-1163005939)
pass[1] == 0xBAADFOOD
pass[2] == 0xBAADFOOD
pass[3] == 0xBAADFOOD
pass[4] == 0xBAADFOOD
pass[5] == 0xBAADFOOD
So, the way in which you are selectively writing to some elements of that memory would leave that original content in some of the other areas of that memory block, causing problems when outputting the results.
When using malloc in this way it is recommended to initialize the memory before using:
pass = malloc(size * sizeof(int));
if(pass)
{
memset(pass, 0, size*sizeof(int));
...
Resulting in:
pass[0] == 0x00000000
pass[1] == 0x00000000
pass[2] == 0x00000000
pass[3] == 0x00000000
pass[4] == 0x00000000
pass[5] == 0x00000000
Using calloc allocates the memory just as malloc does, but then clears it before returning, saving the need for you to clear it with memset.
Note also it is not necessary, or recommended to cast the return of [m][c]alloc.
The problems lies with this statement:
pass[i] = scores[i];
You don't want to copy the score into the element with the same index; you want to copy it into the first "free" slot. You'll need to keep track of how elements of pass are being used.
There's a second problem: You output size numbers, even if there are fewer passing grades.
In this case, rather than having to communicate the number of elements in the returned array to the caller, we could simply place a 0 at the end to indicate the end. But we have to be careful of the case where all the grades are passing grades!
A minor third problem: You are considering a grade of 36 to be a failing grade! Let this be a lesson in testing: Whenever you do testing, always test at and around the limits (so you'd test with scores of 35, 36 and 37 in this case).
Finally, you dynamically allocate an array, but you never free it. It's not critical that you free it because you'd do so just before exiting the program, but that's a bad habit to get into. (One possible consequence is that it would cause the output of tools such as valgrind to become very noisy if you decide to use it to help resolve a crash.)
#include <stdio.h>
#include <stdlib.h>
int* getPassingScores(const int* scores, int num_scores) {
const int passingScore = 36;
// calloc is like malloc, but the memory will
// be efficiently initialized to 0. This means
// we don't need to do pass[j] = -1; later.
// Need to make sure we have enough space
// when all the grades are passing grades!
int* pass = calloc(num_scores, sizeof(int));
if (!pass)
return NULL;
for (int i=0, j=0; i<num_scores; ++i) {
if (scores[i] >= passingScore) {
pass[j++] = scores[i];
}
}
return pass;
}
int main(void) {
int scores[] = {55, 35, 60, 25, 10, 43};
int num_scores = sizeof(scores)/sizeof(*scores);
int* passingScores = getPassingScores(scores, num_scores);
for (int i=0; passingScores[i]>0; ++i) {
printf("%d\n", passingScores[i]);
}
free(passingScores);
return 0;
}
Of course, the following would suffice:
#include <stdio.h>
int main(void) {
int scores[] = {55, 35, 60, 25, 10, 43};
int num_scores = sizeof(scores)/sizeof(*scores);
const int passingScore = 36;
for (int i=0; i<num_scores; ++i)
if (scores[i] >= passingScore)
printf("%d\n", scores[i]);
}

Passing arrays to function

#include <stdio.h>
float average(float age[]);
int main()​
{
float avg, age[] = { 23.4, 55, 22.6, 3, 40.5, 18 };
avg = average(age); /* Only name of array is passed as argument. */
printf("Average age=%.2f", avg);
return 0;
}
float average(float age[])
{
int i;
float avg, sum = 0.0;
for (i = 0; i < 6; ++i)
{
sum += age[i];
}
avg = (sum / 6);
return avg;
}
If I follow the same convention ,
Would it be correct to write
int main()
{
int a[]={1,2,3};
int a1[]=a;
....
}
Can I assign the address of a into a1here
Or would this be correct
int main()
{
int a[]={1,2,3};
int a1[];
a1=a;
...
}
The second one is probably wrong since I have already created an array a1 with 0 space alloted
If we can pass it to a function like that
Why can't we use it directly like in first case I gave
In C, you cannot assign arrays to one another. Instead, you must use a pointer which points to the address of the first element in your array. Here is an example which shows this:
/* My array */
int arr[] = {1, 2, 3, 4};
/* pointer which points to the first element of arr[] */
int *ptr = &arr[0];
/* prints out contents of pointer */
for (size_t i = 0; i < sizeof arr / sizeof arr[0]; i++) {
printf("%d\n", ptr[i]);
}
/* Outputs:
1
2
3
4
*/

Insertion Sort Doing Nothing

I wrote the following insertion sort yesterday (I started learning C 3 days ago). For some reason, the sort does not modify the array AT ALL.
#include <stdio.h>
int *insert(int arr[], int index, int item);
int *isort(int arr[]);
int main() {
int a[17] = {1, 2, 9, 5, 3, 2, 1, 6, 5, 9, 0, 1, 3, 4, 2, 3, 4};
int *b = isort(a);
for (int i = 0; i < 17; i += 1) {
printf("%d ", b[i]);
}
return 0;
}
int *insert(int arr[], int index, int item) {
--index;
while (index >= 0 && item < arr[index]) {
arr[index + 1] = arr[index];
--index;
}
arr[index + 1] = item;
return arr;
}
int *isort(int arr[]) {
for (int i = 1; i < sizeof(arr) - 1; i++) {
arr = insert(arr, i, arr[i]);
}
return arr;
}
I'm thinking it could be my compiler, as I'm running a compiler that is on a non unix machine: lcc-win, but I'm not sure. Is there some fundamental thing I'm missing here?
int *isort(int arr[]) {
for (int i = 1; i < sizeof(arr) - 1; i++) {
arr = insert(arr, i, arr[i]);
}
return arr;
}
In this function sizeof(arr) actually returns the size of the pointer and not the size of the array.
In C a special rule says an array parameter is actually adjusted to a parameter of the corresponding pointer type.
That is:
int *isort(int arr[]) { /* ... */ }
is equivalent to this:
int *isort(int *arr) { /* ... */ }
To fix this, add a new parameter in your function that takes the size of the array:
int *isort(int arr[], size_t size) { /* ... */ }
The first problem, as has been pointed out, is that the isort function uses the sizeof operator on a pointer. The way C treats arrays is a little strange at first glance. The name of an array is a pointer to its first element. So when you call isort like this:
int *b = isort(a);
you are simply pushing a pointer to the array onto the stack. In the definition of isort,
int *isort(int arr[])
declares arr to be a pointer to int just like
int *isort(int *arr)
C is even more confusing in this respect: if you had said:
int *isort(int arr[17])
the arr variable is still just a pointer to int ... the "17" here is discarded! Even with this syntax, sizeof(arr) will still be the size of a pointer to int.
On a 32-bit system (ILP32), sizeof(arr) will always be 4, however big the array is.
Therefore, you need to pass the size of the array to isort. A good general way to do this is to define a macro like this:
#define NITEMS(arr) (sizeof(arr)/sizeof(arr[0]))
This will calculate the number of elements in an array of any type.
Your next problem is more a style one than an actual error:
arr = insert(arr, i, arr[i]);
This calls the insert function with a reference to "arr". The array is modified through this reference, and then a pointer to that array is returned. It will always be the same pointer as you sent in the first place, so this assignment actually does nothing, harmlessly. Like I say, a style problem, not a code error.
The final issue is your isort function stops one short (after you correct the sizeof problem), since you went from 1 to sizeof-1. Here is a fixed version:
#include <stdio.h>
#define NITEMS(arr) (sizeof(arr)/sizeof(arr[0]))
int *insert(int arr[], int index, int item);
int *isort(int arr[], size_t nitems);
int main() {
int a[17] = {1, 2, 9, 5, 3, 2, 1, 6, 5, 9, 0, 1, 3, 4, 2, 3, 4};
int *b = isort(a, NITEMS(a));
for (int i = 0; i < NITEMS(a); i += 1) {
printf("%d ", b[i]);
}
printf("\n");
return 0;
}
int *insert(int arr[], int index, int item) {
--index;
while (index >= 0 && item < arr[index]) {
arr[index + 1] = arr[index];
--index;
}
arr[index + 1] = item;
return arr;
}
int *isort(int arr[], size_t nitems) {
for (int i = 1; i < nitems; i++) {
insert(arr, i, arr[i]);
}
return arr;
}

Resources