2

The goal of the exercise is to calculate a complex number Z according to some formula and create an array of n such complex numbers. Here's the function that calculates Z

double complex convert(double R, int p)
    {
        double complex Z=0+0*I;
        double complex A, B, C;

        A=exp(M_PI/4) + 0*I;
        B=cos(11*M_PI/6 + 2*p*M_PI) + 0*I;
        C=I*sin(R*M_PI/6);
        Z=A*((R*B)+C);

        return Z;
    }

The function that creates the array:

double complex *array_function (double *a, int n)
{
    int i;
    double complex array[100];

    for (i=0; i<n; i++)
    {
       array[i]=convert(*(a+i),i);
    }

    return array;
}

And int main:

int main()
{
    int N, i;
    double complex *new_array[100];
    double array[100];

    printf("Enter the length of the array = ");
    scanf("%d", &N);

    for (i=0; i<N; i++)
    {
        printf("Element number %d is: ", i+1);
        scanf("%f", &array[i]);
    }

    new_array=array_function(array, N); // where I get the error message
    printf("The new array is: \n");

    for (i=0; i<N; i++)
    {
        printf("%f + i%f \n", creal(new_array[i]), cimag(new_array[i]));
    }

    return 0;
}

But I keep getting the same error message: "assignment to expression with array type" in regards to the line: "new_array=array_function(array, N);"

Edit: Here's the edited code:

double complex convert(double R, int p)
{
    double complex Z=0+0*I;
    double complex A, B, C;

    A=exp(M_PI/4) + 0*I;
    B=cos(11*M_PI/6 + 2*p*M_PI) + 0*I;
    C=I*sin(R*M_PI/6);
    Z=A*((R*B)+C);

    return Z;
}



double complex *array_function (double *a, int n)
{
    int i;
    double complex *array = malloc(100 * sizeof *array);

    for (i=0; i<n; i++)
    {
       array[i]=convert(*(a+i),i);
    }

    return array;
}

int main()
{
    int N, i;
    double complex *new_array;
    double array[100];

    printf("Enter the length of the array = ");
    scanf("%d", &N);

    for (i=0; i<N; i++)
    {
        printf("Element number %d is: ", i+1);
        scanf("%f", &array[i]);
    }

    new_array=array_function(array, N); // where I get the error message
    printf("The new array is: \n");

    for (i=0; i<N; i++)
    {
        printf("%f + i%f \n", creal(new_array[i]), cimag(new_array[i]));
    }

    return 0;
}
22
  • new_array is an array, and you can't assign to arrays in C. Commented Mar 14, 2018 at 20:39
  • 1
    @Oliver Charlesworth So what can I do instead? Commented Mar 14, 2018 at 20:40
  • There's another bug: return array; returns a pointer to local memory that goes out of scope after the return. Commented Mar 14, 2018 at 20:42
  • 1
    I mean that in array_function the array[] is an object of automatic storage duration. This ceases to exist when the function returns. If the caller uses that address, the behaviour is undefined. That's a massive bug. Never return addresses of storage with a lifetime ending at the return. Commented Mar 14, 2018 at 20:48
  • 1
    @DavidC.Rankin no, it's not intentional. Does it make a difference? Commented Mar 14, 2018 at 20:59

4 Answers 4

2

You cannot assign to arrays in C. You can only assign to array elements.

If you want to change arrays dynamically, declare a pointer of the appropriate type and assign the result of malloc and/or realloc.

Sign up to request clarification or add additional context in comments.

Comments

1

If you have made the changes to insure you are reading doubles with scanf by adding the 'l' modifier to your %f format specifier (e.g. "%lf") and you have fixed your attempt to return a statically declared array, by declaring a pointer in main() to which you assign the return from array_function, and properly allocated the array in array_function, then your code should be working without crashing. Also, M_PI should be properly typed as double eliminating the integer division concern.

You must VALIDATE ALL USER INPUT (sorry for all caps, but if you learn nothing else here, learn that). That means validating the return of scanf and checking the range of the value entered where appropriate.

Putting those pieces together, you could do something like the following (with the code sufficiently spaced so old-eyes can read it):

#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#include <math.h>

#define MAXC 100   /* if you need a constant, define one */

double complex convert (double R, int p)
{
    double complex Z = 0 + 0 * I;   /* space your code so it is readable */
    double complex A, B, C;         /* (especially for older eyes......) */

    A = exp (M_PI / 4.0) + 0 * I;
    B = cos (11 * M_PI / 6.0 + 2 * p * M_PI) + 0 * I;
    C = I * sin (R * M_PI / 6.0);
    Z = A * ((R * B) + C);

    return Z;
}

double complex *array_function (double *a, int n)
{
    int i;
    double complex *array = calloc (MAXC, sizeof *array);  /* allocate */

    if (!array) {   /* validate allocation succeeded */
        perror ("calloc-array");
        exit (EXIT_FAILURE);
    }

    for (i = 0; i < n; i++)         /* convert your values */
        array[i] = convert (a[i], i);

    return array;   /* return pointer */
}

int main (void)
{
    int N, i;
    double complex *new_array;  /* declare pointer to receive return */
    double array[MAXC];

    printf ("Enter array length: ");
    if (scanf("%d", &N) != 1 || N > MAXC) { /* VALIDATE ALL USER INPUT */
        fprintf (stderr, "error: invalid input or out of range.\n");
        return 1;
    }

    for (i=0; i<N; i++) {
        printf ("  enter array[%2d]: ", i);
        if (scanf("%lf", &array[i]) != 1) { /* VALIDATE ALL USER INPUT */
            fprintf (stderr, "error: invalid conversion, array[%d].\n", i);
            return 1;
        }
    }

    new_array = array_function (array, N);  /* call array_function */

    printf("\nThe new array is: \n\n");

    for (i=0; i<N; i++)     /* output results */
        printf ("  %10.6f + i%f \n", creal(new_array[i]), cimag(new_array[i]));

    free (new_array);   /* don't forget to free memory you allocate */

    return 0;
}

(note: you should free all memory you allocate)

Example Use/Output

$ ./bin/complex
Enter array length: 5
  enter array[ 0]: 1.81
  enter array[ 1]: 1.97
  enter array[ 2]: .31
  enter array[ 3]: 2.51
  enter array[ 4]: 6.021

The new array is:

    3.43798 + i1.781127
    3.74189 + i1.881977
    0.58883 + i0.354442
    4.76758 + i2.121489
   11.43651 + i-0.024116

Look things over and let me know if you have further questions.

6 Comments

It works! Thank you! I can't figure out what exactly was giving me the 0.000000 + i0.000000 result
I can, if you were still trying to read with scanf("%f", &array[i]);, you were filling array with zeros...
So what does the 1 if front of the f change?
It modifies the length of the value stored. With %f you are attempting to store a 32-bit floating point number in a 64-bit variable. Since the sign-bit, biased exponent and mantissa are encoded in different bits depending on the size, using %f to attempt to store a double always fails` (e.g. the sign-bit is still the MSB for both, but e.g. a float has an 8-bit exponent, while a double has 11-bits, etc....)
And note: this is for scanf. You can print a float or double with %f in printf, but if you are reading and converting to floating-point, then you must properly match the type by using %f for float and %lf for double.
|
0

double complex *new_array[100]; declares new_array to be an array of 100 pointers to double complex. That is not what you want. You merely want a pointer to double complex (which will point to the first element of an array that is provided by the function). The declaration for this is double complex *new_array;.

However, in array_function, you attempt to return array, where array is defined inside the function with double complex array[100];. That declaration, when used inside a function, declares an array that lasts only until the function returns. If you return its address (or the address of its first element), the pointer to that address will be invalid.

The proper way to return a new array from a function is to dynamically allocate the array, as with:

double complex *array = malloc(100 * sizeof *array);
if (!array)
{
    fprintf(stderr, "Error, failed to allocate memory.\n");
    exit(EXIT_FAILURE);
}

… // Assign values to the array elements.

return array;

Then the caller is responsible for releasing the array at some later time, by passing the address to the free routine.

(To use malloc, free, and exit, add #include <stdlib.h> to your program.)

2 Comments

Ah, I see. That fixes the error but the program still crashes after entering in the elements
Okay, so now it no longer crashes. You can see my updated code above. Now it prints 0.000000 + i0.000000, which is not the result I want
0

If you want to let the array_function create the content of new_array, you can send the array pointer as a parameter to the function, and let the function use that. You also need to change the definition of new_array to double complex new_array[100]

That is,

void array_function (double *a, double complex array[], int n)
{
    int i;
    for (i=0; i<n; i++)
    {
       array[i]=convert(*(a+i),i);
    }
}

And in main():

double complex new_array[100];
...
array_function(array, new_array, N);

5 Comments

I can't seem to get it work like this either. It keeps printing 0.000000 + i0.000000
Now we are no longer talking about the subject of this question. However, I think your problem is in your scanf. You need to use "%lf" when scanf:ing into a double.
I know, is there need for me to post another question? I'm not really a regular here. I changed that but I'm still getting the same result
Well, I tried your code, and after changing scanf("%f", &array[i]) to scanf("%lf", &array[I]), I got some nicely looking numbers instead of 0.0000.
Good deal. Good luck with your coding (and always validate all user input :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.