This is what I have currently, and I have no idea what to do to make it run:
void avg_sum(double a[], int n, double *avg, double *sum) {
int i;
*sum = 0.0;
for (i = 0; i < n; i++)
*sum += a[i];
*avg = *sum / n;
}
int main () {
int array[5] = {1, 2, 3, 4, 5};
int avg = 3;
int sum = 2;
avg_sum(array, 5, avg, sum);
}
I tried manipulating the arguments for running the function, but I can't figure out how to make it work. It can be simple, I just have to write a program to test the avg_sum function. That portion must remain the same.
You want this:
int main () {
double array[5] = {1, 2, 3, 4, 5}; // use double
double avg = 3;
double sum = 2;
avg_sum(array, 5, &avg, &sum); // call with &
}
avg_sum operates on doubles, therefore you need to provide doubles.
parametrers 3 and 4 must be pointers to double, therefore you need to use the address operator &.
All this is covered in the first chapters of your beginner's C txt book.
For starters these initializations
int avg = 3;
int sum = 2;
does not make a sense.
At least it will be more meaningfully to initialize these variables by zero
int avg = 0;
int sum = 0;
The function avg_sum expects that the third and fourth arguments will be accepted by reference through pointers to them.
void avg_sum(double a[], int n, double *avg, double *sum) {
So the function must be called like
avg_sum(array, 5, &avg, &sum);
Also the function expects that the first, third and fourth arguments declared with the type specifier double but you are passing arguments declared with the type specifier int.
The function itself should be declared and defined the following way
void avg_sum( const int a[], size_t n, double *avg, int *sum )
{
*sum = 0;
for ( size_t i = 0; i < n; i++ )
{
*sum += a[i];
}
*avg = n == 0 ? 0.0 : *sum / n;
}
So within main the variables avg and sum have to be declared like
double avg = 0.0;
int sum = 0;
Also after the call of the function
avg_sum(array, 5, &avg, &sum);
it seems you should output the obtained values like for example
printf( "sum = %d, average = %.2f\n", sum, avg );
Related
This question already has answers here:
How to pass a 2D array by pointer in C?
(5 answers)
Closed 4 months ago.
#include <stdio.h>
void triU(double **U, double *b, int n)
{
n--;
b[n] /= U[n][n];
for(int i = n - 1; i >= 0; i--)
{
double aux_sum = 0;
for(int j = i + 1; j <= n; j++)
aux_sum += (U[i][j] * b[j]);
b[i] = (b[i] - aux_sum) / U[i][i];
}
}
int main()
{
int n = 3;
double U[][n] = {{5, -5, 10}, {0, 2, 4}, {0, 0, -1}};
double b[] = {25, 16, -2};
triU(U, b, n);
for(int i = 0; i < n; i++)
printf("%le \n", b[i]);
return 0;
}
This is the code for what I am trying to do. I am supposed to make a method with the parameters written in that way to pass the two matrices.
However I keep getting the following error.
triU.c: In function ‘int main()’:
triU.c:21:10: error: cannot convert ‘double (*)[n]’ to ‘double**’
21 | triU(U, b, n);
| ^
| |
| double (*)[n]
triU.c:3:20: note: initializing argument 1 of ‘void triU(double**, double*, int)’
3 | void triU(double **U, double *b, int n)
| ~~~~~~~~~^
I would appreciate any help on how I am supposed to pass arrays by pointers in C.
Thank you very much.
In this call of the function triU:
triU(U, b, n);
the two-dimensional array U is implicitly converted to pointer to its first element of the type double ( * )[3]. But the corresponding function parameter has the type double ** and there is no implicit conversion between the pointer types. So the compiler issues a message.
If your compiler supports variable length arrays (and your compiler support VLAs) then declare the function like:
void triU( size_t n, double ( *U )[n], double *b );
or:
void triU( size_t n, double U[][n], double *b );
and call it like:
triU( n, U, b );
Otherwise declare the function like:
void triU( double ( *U )[3], double *b, size_t n );
or:
void triU( double U[][3], double *b, size_t n );
and call it like:
triU( U, b, n );
Pay attention to that this for loop:
for(int j = i + 1; j <= n; j++)
aux_sum += (U[i][j] * b[j]);
can invoke undefined behavior when j is equal to n because the valid range of indices is [0, n).
Also bear in mind that the length modifier in the format string in this call:
printf("%le \n", b[i]);
is redundant and has no effect. You may write:
printf("%e \n", b[i]);
The task is to fill an array with numbers by user input and then use our stats() function to calculate average etc. of each row of this array. The header of stats() function looks as follows:
int stats(int (*ptr)[5], int width, int height, int row_id, int* max, int* min, float *avg)
where ptr is a pointer to the matrix,width and height are its size, row_id is the index of analysed row and max, min and avg are pointers to variables storing each statistics.
When calling a function with such line:
stats(*ptr, 5,5,2, *max = NULL, *min = NULL, *avg=NULL);
the following error appears:
error: invalid type argument of unary '*' (have 'int')
I tried different approaches but there is always a mistake, how can I fix that? Thank you for any clues.
edit:
Here's the whole code:
#include <stdio.h>
int stats(int (*ptr)[5], int width, int height, int row_id, int* max, int* min, float *avg)
{
int j, vmax,vmin;
int max = &vmax;
int min = &vmin;
int i = row_id;
int m = *ptr;
for(j = 0; j<5; j++){
if(m[i][j]>max)
{
max = m[i][j] ;
j++;
else
j++;
}
}
printf("%d", max);
return 0;
}
int main(void){
int n, i, j, vmin, vmax; // vmax - value of the maximum
int min = &vmin; // min - pointer to the minimum
int max = &vmax;
float vavg;
int avg = &vavg;
int m[5][5];
for(i = 0; i<5; i++)
{
for(j = 0; j<5; j++)
{
printf("ENTER A NUMBER: ");
scanf("%d", &n);
m[i][j] = n;
}
}
int ptr = &m;
stats(*ptr, 5,5,2, *max = NULL, *min = NULL, *avg=NULL);
return 0;
}
Your code full of bugs.
For example min and max are not declared as pointers
int min = &vmin; // min - pointer to the minimum
int max = &vmax;
Also it is unclear why the variable avg has the type int and is initialized by a pointer expression of the type float *.
float vavg;
int avg = &vavg;
Or the variable ptr of the type int is initialized by the address of the two-dimensional array.
int ptr = &m;
As for the function then if the function operates only on one row then there is no any sense to pass to the function the whole two-dimensional array.
Also the return type and the returned value of the function do not make a sense.
And the function shall not output any message. It is the caller of the function that will decide output a message or not.
And also the function contains bugs where you are redeclaring its parameters like for example
int max = &vmax;
that again does not make a sense.
Using your approach the function can be declared and defined the following way
#include <assert.h>
//...
void stats( const int *a, size_t n, int *max, int *min, float *avg )
{
assert( n != 0 );
*max = a[0];
*min = a[0];
float sum = a[0];
for( size_t i = 1; i < n; i++ )
{
sum += a[i];
if ( *max < a[i] )
{
*max = a[i];
}
else if ( a[i] < *min )
{
*min = a[i];
}
}
*avg = sum / n;
}
And called like
int min = 0;
int max = 0;
float avg = 0.0f;;
//...
stats( m[2], 5, &max, &min, &avg );
printf( "max = %d\n", max );
printf( "min = %d\n", min );
printf( "average = %f\n", avg );
When you are using pointers as function parameters be carefull. If you have something like this:
int func(int *max){
}
max ,here, is a pointer which needs to hold an address. So inside this function when you need use it, you need to dereference it by using *. For example:
int func(int *max){
*max = $someAddress
}
Can someone help me fixing the syntax errors in this code?
#include <stdio.h>
int result(int v, int size);
int main(void){
int arr[5], n;
for (n = -1; n < 4; n++){
arr[n] = n + 1;
printf("the product of entered values is %d", result(n, 5));
}
return 0;
}
int product(int a[]) {
int product, i;
for (i = 0; i <= sizeof(int); i++){
product *= a[i];
}
return product;
}
for (n = -1; n < 4; n++){
arr[n] = n + 1;
You start n at -1, then immediately use arr[n].
Negative indices are not allowed in C. Valid values are 0 to the size of the array-1.In otherwords, if you have an arr[5], then the valid indices are [0], [1], [2], [3], and [4].
int product(int a[]) {
int product, i;
You create a function named product and also a variable named product.
That makes it virtually impossible to refer to the proper object. Work on your name management, so that every item is unambiguous.
You are trying to call the result function, for which you have provided the forward declaration but not an actual implementation. You need to write an implementation for the result function. That is why the compiler complains about an undefined reference.
For starters the function result is declared
int result(int v, int size);
but not defined.
On the other hand, taking into account the message in this call of printf
printf("the product of entered values is %d", result(n, 5));
you mean a function that calculates a product of elements of an array like your function defined after main but that is not used
int product(int a[]) {
int product, i;
for (i = 0; i <= sizeof(int); i++){
product *= a[i];
}
return product;
}
So let's remove the declaration of the function result and declare before main a function with name product because the name result is not enough informative.
The function deals with an array. We need to pass to the function the number of elements in the array. As the array itself will not be changed within the function then it should be declared with the qualifier const
Also a product of integer numbers of the type int can be too big to be stored in an object of the type int.
So it is better to declare the return type of the function at least like long long int (or even like double or long double).
Thus the function declaration can look like
long long int product( const int a[], size_t n );
The function can be defined the following way
long long int product( const int a[], size_t n )
{
long long int result = n == 0 ? 0 : 1;
for ( size_t i = 0; i < n; i++ )
{
result *= a[i];
}
return result;
}
As for your function product then you forgot to initialize the variable product
int product, i;
The condition in the for loop
for (i = 0; i <= sizeof(int); i++){
does not make a sense because the expression sizeof( int ) does not yield the number of elements in an array.
Try to not use magic numbers like 5 in this declaration
int arr[5], n;
in your programs. Use named constants.
Indices of arrays always start from 0. So this loop
for (n = -1; n < 4; n++){
where the variable n is used as an index does not make sense.
Also this call of printf
printf("the product of entered values is %d", result(n, 5));
must be placed outside the for loop and in the the call of the function result that is used as an argument of the function printf
result(n, 5)
you even are not using the array.
Thus the program can look the following way
#include <stdio.h>
long long int product( const int a[], size_t n );
int main(void)
{
enum { N = 5 };
int a[N];
for ( size_t i = 0; i < N; i++ )
{
a[i] = i + 1;
}
printf( "The product of entered values is %lld", product( a, N ) );
return 0;
}
long long int product( const int a[], size_t n )
{
long long int result = n == 0 ? 0 : 1;
for ( size_t i = 0; i < n; i++ )
{
result *= a[i];
}
return result;
}
The program output is
The product of entered values is 120
#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
*/
I have a Java method that multiplies 2 matrices. I have tried to port the same method in C without success.
Here is my attempt to write a method that should multiply 2 matrices in C:
float **multiply(int m1, int n1, float Xy1[], int m2, int n2, float Xy2[]) {
int i, j, k;
float **result = allocate_mem_mtrx(m1, n2);
for (i = 0; i < m1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n1; k++) {
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
At this line
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
I receive the error:
subscripted value is neither array nor pointer nor vector
Clearly my syntax is wrong, but I haven't understood how I should fix this line of code, to solve my problem.
In my main I have:
float matrix1[3][2] = {{0, 1}, {3, 4}, {6, 7}};
float matrix2[2][3] = {{5, 1, 2}, {3, 4, 5}};
with the actual signature I invoke the method in this way:
multiply(3, 2, &matrix1, 2, 3, &matrix2);
My original Java method
public static int[][] multiply(int[][] Xy1, int[][] Xy2) {
int rowsInXy1 = Xy1.length;
int columnsInXy1 = Xy1[0].length; // same as rows in B
int columnsInXy2 = Xy2.length;
int[][] result = new int[rowsInXy1][columnsInXy2];
for (int i = 0; i < rowsInXy1; i++) {
for (int j = 0; j < columnsInXy2; j++) {
for (int k = 0; k < columnsInXy1; k++) {
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
You have float Xy1[]
but you treat it as 2D
Xy1[i][k]
Same for Xy2.
You should change float Xy1[] to float** Xy1.
Also another thing, in your loop I feel that you are sure that result 2D array is initialized in your function that says allocate. If that functions just mallocs the array, then this array will have garbage inside.
For more.
[EDIT]
Also I see in one other answer that they cast what malloc returns. Ouch!
Do not cast the return value of malloc in C.
[EDIT.2]
SO, you could something like this:
#include <stdlib.h>
// We return the pointer
float **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
float **table;
table = malloc(N*sizeof(float *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(float) );
return table;
}
void free2Darray(int** p, int N) {
int i;
for(i = 0 ; i < N ; i++)
free(p[i]);
free(p);
}
// do not forget to FREE what multiply returns
float **multiply(int m1, int n1, float** Xy1,int m2, int n2, float** Xy2) {
int i,j,k;
float **result = get(m1,n2);
for (i = 0; i < m1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n1; k++) {
// this line is correct, the prototype of the function
// was not OK
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
int main(void) {
float** A = get(5, 5); // arrays declared as double pointers
float** B = get(5, 5);
float** C = get(5, 5);
C = multiply(5, 5, A, 5, 5, B);
// free2Darray function defined below
free2Darray(A, 5);
free2Darray(B, 5);
free2Darray(C, 5);
return 0;
}
[EDIT.3]
Another way, if you now the columns apriori, which you probably don't as your function implies, you could do that:
#include <stdlib.h>
#include <stdio.h>
// We return the pointer
float **get(int N, int M) /* Allocate the array */
{
/* Check if allocation succeeded. (check for NULL pointer) */
int i;
float **table;
table = malloc(N*sizeof(float *));
for(i = 0 ; i < N ; i++)
table[i] = malloc( M*sizeof(float) );
return table;
}
float **multiply(int m1, int n1, float Xy1[][2],int m2, int n2, float Xy2[][2]) {
int i,j,k;
float **result = get(m1,n2);
for (i = 0; i < m1; i++) {
for (j = 0; j < n2; j++) {
for (k = 0; k < n1; k++) {
result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j];
}
}
}
return result;
}
int main() {
float matrix1[2][2] = {{0, 1}, {3, 4}};
float matrix2[2][2] = {{0, 1}, {3, 4}};
float** C;
C = multiply(2, 2, matrix1, 2, 2, matrix2);
free2Darray(C, 2);
printf("ok\n");
return 0;
}
I got the get() function from my pseudo-site.
float Xy1[]
is not a two dimensional array, so to write
Xy1[i][k]
is an error.
In C you can use a pointer to pointer notation:
float** multiply( int m1, int n1, float** Xy1,int m2, int n2, float** Xy2) {
//...
}
or you can take advantage of the variable-length array feature in the C language and write
functions that can take multidimensional arrays of varying sizes:
float** multiply( int m1, int n1, float Xy1[m1][n1],
int m2, int n2, float Xy2[m2][n2]) {
float **result, i, j;
result = malloc( m1 * sizeof *result); // remember to free this memory
for( i = 0; i < m1; ++i)
result[i] = malloc( n2 * sizeof float);
//... I don't continue since there seems to be an issue with your indices
// however now you can use result this way:
// result[i][j] = result[i][j] + Xy1[i][k] * Xy2[k][j]; i, j, k integers
return result;
}
In C++ use a std::vector< std::vector<float> >:
typedef std::vector<std::vector<float> > array; // shorten notation
array multiply( const array& Xy1, const array& Xy2) {
//...
}
In addition
int[][] result = new int[rowsInXy1][columnsInXy2];
is not correct way to create two dimensional array. Such array is an array of pointers and correct way to create this is:
C
int **a, i;
a = malloc( rowsInXy1 * sizeof *a);
for( i = 0; i < rowsInXy1; ++i)
a[i] = malloc( columnsInXy2 * sizeof int);
C++
int** result = new int*[rowsInXy1];
for( int i = 0; i < rowsInXy1; ++i)
result[i] = new int[columnsInXy2];
I see you have already chosen a solution but here is some additional info about arrays in C.
In C there is no equivalent of Java's int[][] type. Java array storage also includes storage of how many items are in the array. However, C's array storage is purely the values in the array contiguous in memory; and you have to keep track of the size either as compile-time constants, or by storing a variable that holds the length.
Further; originally in C, arrays (using the [] syntax) had to have their size known at compile-time. There is an optional feature called variable-length array which means that the array size can be specified at runtime -- however the size can't be changed once the array is created. The major compiler vendors all support VLA, I think.
The VLA uses contiguous storage, however it is not possible to return one via a function's return value. But you can "return" them using an "out" parameter.
It's probably going to turn into a jumble if your code sometimes uses VLAs and sometimes uses dynamically-allocated arrays of pointers.
Another point: in both cases you have to store both array dimensions separately from the array, so that's 3 variables to pass around for each matrix. I'd like to suggest wrapping all of this up in a struct. Since VLAs can't live in a struct, and the compiler might not support them anyway, your best bet may be to use the dynamic allocation version.
Even though we are in C, if you are planning to do more than just a throwaway program, my recommendation would be to use an object-oriented approach for the matrix. Here's an example framework (where all Matrices are to have the Matrix be dynamically allocated, as well as the cells):
// Matrix.h
typedef struct
{
size_t y_dim, x_dim;
float **cells;
} Matrix;
Matrix *matrix_construct(size_t y_dim, size_t x_dim);
void matrix_free(Matrix *m); // frees m as well as cells
void matrix_assign(Matrix *dst, Matrix const *src); // may re-size dst
void matrix_set_values(Matrix *dst, float *row_major);
bool matrix_is_equal(Matrix const *m1, Matrix const *m2);
typedef Matrix *MatrixBinaryOperator(Matrix const *m1, Matrix const *m2);
MatrixBinaryOperator matrix_multiply;
Example usage:
float mat1_array[3][2] = {{0, 1}, {3, 4}, {6, 7}};
float mat2_array[2][3] = {{5, 1, 2}, {3, 4, 5}};
Matrix *mat1 = matrix_construct(3, 2);
Matrix *mat2 = matrix_construct(2, 3);
matrix_set_values(mat1, (float *)&mat1_array);
matrix_set_values(mat2, (float *)&mat2_array);
Matrix *mat3 = matrix_multiply(mat1, mat2);
matrix_free(mat1);
matrix_free(mat2);
matrix_free(mat3);
See it working - disclaimer: this code doesn't check for malloc failure and I have only done the most basic testing; and a lot of optimization is possible.