passing array to function in c - c

can someone please help me figure out what i'm doing wrong here? i'm getting inaccurate results here. I seem to be getting the first value in the array each time and i cant seem to figure out what i'm doing incorrectly
#include <stdio.h>
int getbillsum ( int price[] );
int main( void )
{
int itemprice [10];
int total = 0;
for (int c=0;c <10;c++ ) //Looping to get item prices
{
printf ("\nEnter the price of the item: ");
scanf (" %d", &itemprice[c]);
}
total = getbillsum (itemprice);
printf ("%d", total);
return 0;
}
int getbillsum (int price []) //function to sum the values in array
{
int sum = 0;
for (int i=0; i<sizeof(price); i++)
{
sum+=price[i];
}
return sum;
}

You can't pass arrays to functions in C (well, not as an array anyway). Arrays decay into pointers, the sizeof which is always the same (4 for 32 bit systems, 8 for 64 bits).
For more information see paragraph 2.3 here.
The easiest, most common and most reliable way of solving your issue is to pass the length of the array as a second argument:
int getbillsum (int *price, size_t len)
{
int sum = 0;
for (int i=0; i<len; ++i)
sum += price[i];
return sum;
}
//usage
int main ( void )
{
int price[10];
for(int i=0;i<10;++i)
scanf(" %d", &price[i]);
printf("Sum: %d\n", getbillsum(price, sizeof(price)/sizeof(*price)));
return 0;
}
You also had a problem in your code: you added the return statement inside of your loop.
Just a quick-tip: The sum of an array of ints is not unlikely to be too much for a single int to hold, so I'd change the return-type of getbillsum to long, too
I've also edited your question, addressing quite a lot of issues considering how short your code was:
int getbillsum ( price );//missing type, changed to
int getbillsum ( int price[] );//better would be int getbillsum ( int *price ); but considering your question, left it as array
scanf ("%d", &itemprice[c]);//unsafe, changed it to
scanf (" %d", &itemprice[c]);//add space
total = getbillsum (itemprice,9);//why the second param?
total = getbillsum (itemprice);//to match function prototype
return sum;//moved OUTSIDE of the loop...

sizeof(price) does not give you the length of the array, but the size of the pointer (int price[]), which is probably 4. Also, you immediately return in the first for run. Put return outside the for loop.
You do fix it by supplying the array size, but you never use it. Update your getbillsum function:
int getbillsum (int price [], int length) //function to sum the values in array
{
int sum = 0;
for (int i=0; i<length; i++)
{
sum+=price[i];
}
return sum;
}

In addition to posted answers, you can consider a technique suggested in this answer.
Edit Quoted from comment
it's non-standard, dangerous (think of overflow, forgetting to
dereference at the correct offset and the like), and you should not
try this
In your case it will be something like that :
void *p = calloc(sizeof(itemprice) + sizeof(unsigned long int),1));
*((unsigned long int*)p) = 10;
quote from linked answer
n is now stored at ((unsigned long int)p)
Your getbillsum will look like that now (did not compile it, consider it as pseudocode)
int getbillsum (void* p)
{
int* price = p+sizeof(unsigned long int);
unsigned long int size = *p;
int sum = 0;
for (int i=0; i<size; i++)
{
sum+=price[i];
}
return sum;
}

Related

Use a function to change the contents of the array, i.e. multiply each number in the array by 2

Question
Use your function to change the contents of the array, i.e. multiply each number in the array by 2.
When your function has finished and your program continues in your main(), print the contents of your array in your main().
See if the changes made to the contents of the array in your function can be seen. If not, why?
Further
I'm trying to multiply the original array by 2 onto another array. Can anyone spot where I've went wrong?
#include <stdio.h>
#include <math.h>
#define SIZE 5
//function signatures
int getMultiples(int[]);
//main function
int main()
{
//main variables
int array[SIZE];
int multiples[SIZE];
printf("\nPlease enter 5 numbers into an array.\n");
for(int i = 0; i < SIZE; i++)
{
scanf("%d", &array[i]);
}
multiples[] = getMultiples(array);
printf("\nThis program will multiply all numbers by 2\n\n");
for (int i = 0; i < SIZE; i++)
{
printf("%d\n", multiples[i]);
}
return 0;
}
int getMultiples(int arr[])
{
//function variables
int i;
int multiples[SIZE];
for (i = 0; i < SIZE; i++)
{
multiples[i] = arr[i] * 2;
}
return multiples[];
}
This statement
multiples[] = getMultiples(array);
is syntactically and semantically invalid. This construction multiples[] is wrong and arrays do not have the assignment operator.
Also the definition of the function getMultiples is also wrong.
Again this statement
return multiples[];
is invalid.
What you are trying to do is to return the local array
int multiples[SIZE];
but the function return type is int. At least you needed to declare the return type as int *.
But in any case the local array that has automatic storage duration will not be alive after exiting the function.
If to use your approach then the function can look the following way
void getMultiples( int a1[], const int a2[], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
a1[i] = 2 * a2[i];
}
}
and in main the function is called like
getMultiples( multiples, array, SIZE );
Pay attention to that the function definition should not depend on the magic number SIZE.
By the way in your assignment there is written
Use your function to change the contents of the array, i.e. multiply
each number in the array by 2.
It means that you need to change the source array,
In this case the auxiliary array multiples is redundant. The function could be defined the following way
void getMultiples( int a[], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
a[i] *= 2;
}
}
and called in main like
getMultiples( array, SIZE );
You promise to return a single int.
int getMultiples(...);
You don't:
return multiples[];
You attempt to assign to a whole array (either a single int or an array....).
multiples[] = getMultiples(array);
That does not work in C.
And judging from what happens when trying your code, your compiler should have told you.

Function for addition and getting average of a user defined single dimensional array

This is the question "Write a function which gets an integer array and number of elements as parameters and calculates and displays sum and average of all the integers of the array in C language"
Below is the code which I have done, it's running but consists of bugs which give false answers
#include <stdio.h>
void SumAvg(int x, int arr[x]) {
int i, sum = 0;
float avg = 0;
for (i = 0; i < x; ++i) {
sum += arr[i];
}
avg = (float)sum / x;
printf("The sum is %d", sum);
printf("\nThe average is %.2f", avg);
}
int main() {
int x, i;
printf("Enter number of elements");
scanf("%d", &x);
int arr[x];
for (i = 0; i < x; ++i) {
printf("Enter integers for array[%d]", i + 1);
scanf("%d", &arr[i]);
}
SumAvg(x, arr[x]);
return 0;
}
First , your function calling is wrong .It should be SumAvg(x,arr) instead of SumAvg(x, arr[x]);.
also in function declaration , in some compiler void SumAvg(int x, int arr[x]) might be problematic.
For starters the function should be declared the following way
void SumAvg( const int arr[], size_t n );
That is the parameter that declares the array shall have the qualifier const because the array is not changed in the function.
The number of elements of the array should have the type size_t.
The function definition can look the following way
void SumAvg( const int arr[], size_t n )
{
long long int sum = 0;
for ( size_t i = 0; i < n; i++ )
{
sum += arr[i];
}
double avg = n == 0 ? 0 : ( double )sum / n;
printf( "The sum is %lld\n", sum );
printf( "The average is %.2f\n", avg );
}
That is within the function the variable sum should have the type long long int to decrease the risk of overflow.
In general the user can pass to the function the number of elements equal to 0. In this case if not to check this value the function will have undefined behavior.
This call of the function
SumAvg(x, arr[x]);
is invalid because instead of passing the array you are passing its non-existent element with the index x.
Taking into account the provided function definition above a valid call of the function will look like
SumAvg( arr, x );

Changing the value of a variable with pointers not working

Basically I have a function called MinSubTab that is supposed to calculate the sum of the array passed and also to change the value passed in the first argument from inside the function without using return. This is done with pointers. Anyway, I think it'd be easier if I just showed you the code so here it is:
maintab.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "tab.h"
int main(){
int *reftab;
int min;
reftab = (int *)malloc(sizeof(int) * NMAX);
InitTab(reftab,NMAX);
printf("\n Total: %d et min: %d", MinSumTab(&min, reftab, NMAX), min);
free(reftab);
return 0;
}
tab.c
void InitTab(int *tab, int size){
srand(time(NULL));
for (int i=0; i<size; i++){
*(tab+i) = rand() % 10;
}
}
int MinSumTab(int *min, int *tab, int size){
int total=0;
int minimum = NMAX;
int temp = *min;
for (int i=0; i<size; i++){
total += *(tab+i);
}
for (int i=0; i<size; i++){
if(*(tab+i)<minimum){
minimum = *(tab+i);
}
}
*min = minimum;
return total;
}
So the expected result here is that the sum is printed (which it is) and the minimum value of the array is printed (which it is not). Every single time the min variable equals 8 and I've no idea how to actually change the value of min from within that function.
Please help as my brain has no more capacity for rational thought, it's been 1.5 hrs and no solution in sight. Thanks
Looks like a small mistake:
You initialize minimum with NMAX, which I assume is 8 (the size of the array). 99.9% of the random numbers will be bigger. So 8 is chosen as the minimum.
What you really want is to initialize it with RAND_MAX – the maximum value rand() can return.
In C order of evaluation and argument passing is undefined.
You can of course the order yourself but it only to feed your curiosity.
#include <stdio.h>
volatile char *message[] = {
"fisrt", "second", "third", "fourth"
};
int print(size_t x)
{
printf("%s\n", message[x]);
return x;
}
int main()
{
printf("%d %d %d %d\n", print(0), print(1), print(2), print(3));
return 0;
}
Note. There is one exception from this rule.
Logical operators are evaluated form the left to the right.
if( x != NULL && *x == 5)is safe because x will not be dereferenced if it is NULL

Segmentation fault when trying to add elements of an array

I'm trying to create a function that returns as its result the sum of the elements in the array. When I try to run the program, I get a segmentation fault. Could someone please point me in the right direction? Thank you!
int arraySum (int array[], int numberOfElements) {
int result = 0;
for (int i = 0; i < numberOfElements; i++)
{
result += array[i];
}
return result;
}
int main (void) {
int numberOfElements;
int *array = NULL;
printf("How many elements would you like in your array: ");
scanf("%i", &numberOfElements);
printf("\nPlease list the values of the elements in the array: ");
for (int i = 0; i < numberOfElements; i++)
{
scanf("%i", &array[i]);
}
int result = arraySum(array, numberOfElements);
return result;
}
The problem you have is, that in C you need to manually allocate the memory if you are using a pointer instead of say a fixed-size array.
This is usually done by calling malloc, which will return a void-pointer (void*), which you need to cast to the desired type (in your case (int*)) before assigning it.
It is also important to note, that, when using malloc, you need to specify the amount of Bytes you want to allocate. This means that you can't just call it with the number of integers you want to store inside, but rather have to multiply that number with the amount of Bytes that one integer occupies (which depends on the Hardware and Operating System you use, hence you should use sizeof(int) for that purpose, which evaluates to that size at compile time).
I modified your code with a working example of how it could be done:
#include <stdio.h>
#include <stdlib.h>
int arraySum (int array[], int numberOfElements) {
int result = 0;
int i;
for (i = 0; i < numberOfElements; i++) {
result += array[i];
}
return result;
}
int main(int argc, char **argv) {
int numberOfElements;
int *array = NULL;
printf("How many elements would you like in your array: ");
scanf("%i", &numberOfElements);
array = (int*) malloc(numberOfElements * sizeof(int));
printf("\nPlease list the values of the elements in the array: ");
int i;
for (i = 0; i < numberOfElements; i++) {
scanf("%i", &array[i]);
}
int result = arraySum(array, numberOfElements);
printf("\n\nThe result is: %d\n", result);
return 0;
}
You are also trying to return the result in your main function, but the return value of main in C is used to signal whether your program terminated without errors (signalled by a return value of 0) or didn't encounter any issues (any value other than 0).
You need to allocate memory. It is not enough to just declare a pointer. You do it like this: array=malloc(numberOfElements*sizeof(*array));
Also, although it is possible to return result from the main function, you should not do that. The return value from main is usually used for error checking. Change the end of your program to
printf("Sum: %d\n", result);
return 0;
Returning 0 usually means that no error occurred.

Array pointers and functions

I have to write a C program to do the following:
Write a function that takes three arguments: a pointer to the first
element of a range in an array, a pointer to the element following
the end of a range in an array, and an int value. Have the function
set each element of the array to the int value.
My code is not working. Here is what I have so far. Any help is appreciated.
#include <stdio.h>
#include <iostream>
int listNumbers[3]{ 1,2,3 };
void Sorter(int *first, int * last, int *value);
int * first = &listNumbers[0];
int * last = &listNumbers[2];
int value;
int main() {
printf("your list numbers are:\n");
int i;
for (int i = 0; i < 3; ++i) {
printf("%d", listNumbers[i]);
}
printf("\n");
printf("enter an integer:\n");
scanf_s("%d", &value);
Sorter( first, last, &value);
printf("your new list numbers are:\n");
int j;
for (int j = 0; j < 3; ++j) {
printf("%d", listNumbers[j]);
}
printf("\n");
system("PAUSE");
return 0;
}
void Sorter(int *first, int * last, int *value) {
int i=0;
printf("value = %d\n", &value);
*first = value;
while (i <= *last) {
*(first + i) = value;
i++;
}
}
First, work out the different between the 2 pointers.
int count = last - first + 1;
The compiler will automatically divide by the size of an integer. We add 1 to make the range inclusive. Now just iterate through each element:
for (int i = 0; i < count; i++) {
first[i] = value;
}
Also, why are you passing the value as a pointer? This should just be a value.
void Sorter(int *first, int *last, int value) {
And when you call it...
Sorter(first, last, value);
Your Sorter function does not satisfy the problem criteria. The parameters are supposed to be two pointers into an array, and an int. Your function instead accepts three pointers.
You could nevertheless have made it implement at least the apparent spirit of the exercise, by using the value to which the third argument points as the fill value, but you don't do that. Instead you assign the pointer itself to each array element. That ought to at least elicit a warning from your compiler, and you ought not to be ignoring its warnings, especially when your code it not doing what you think it should.
Furthermore, the last pointer is expected to point to just past the last element to set, but you use it as if it points to an integer offset from the start pointer. This is almost the opposite of the previous problem: here, you need to use the pointer value itself, not the int to which it points.

Resources