0

I want to read from a file two complex numbers

(1.1,2) (1.7,3.14)

In the beginning I do this

struct Num { double Re; 
                    double Im; 
                };

typedef struct Num zesp;

zesp readZ(FILE *wp)
{
    char c;
    zesp z;
    assert(fscanf(wp,"%c%lg%c%lg%c%c",&c,&z.Re,&c,&z.Im,&c,&c));

    return z;
}

But now I get a new task, my teacher said that I should use complex.h to read, write, etc. instead of using my type zesp

First I initialize two complex numbers

    double complex c1;
    double complex c2;

Then I know that normally I will give them value by writing this

double complex z1 = 2.6 + 3.1*I

But how to do this by reading from a file?

(1.1,2) (1.7,3.14)

Edit: Numbers are stored like that

(1.1,2) (1.7,3.14) (2.71,-15)
(4,3.21) (6,7.89)
(10,45)

parenthesis and space between complex numbers

Jakub
  • 679
  • 5
  • 16
  • How are the numbers stored in the file? Separated by spaces, pairs of (x, y) or something else? – DarkAtom May 15 '20 at 12:33
  • It stored like that (1.1,2) (1.7,3.14) (2.71,-15) (4,3.21) (6,7.89) (10,45) I edited my question – Jakub May 15 '20 at 12:39

2 Answers2

3

complex.h does not declare or define:

  • any facilities for input or output,
  • any facilities for conversion between strings and complex numbers, or
  • any means of accessing an lvalue for the parts of a complex number, which would be necessary to store values in those parts via a scanf or similar function.

Thus, it is unclear what your teacher meant by directing you to use complex.h to read complex numbers. When writing, we can use creal and cimag to obtain the values of the parts, and those are declared in complex.h.

There are means to access lvalues for the parts of a complex number. C 6.2.5 13 says “Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.” Although this statement lacks some formal niceties, we can tell, by analogy to other wording in the standard, that it intends to tell us that we can convert a pointer to complex double to a pointer to double [2] and use that to access the parts. Thus, we can do:

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

int main(void)
{
    complex double x;
    double *y = * (double (*)[2]) &x;
    if (2 != scanf("(%lg,%lg)", &y[0], &y[1]))
    {
        fputs("Error, scanf failed.\n", stderr);
        exit(EXIT_FAILURE);
    }
    printf("Read %g + %g i.\n", creal(x), cimag(x));
}
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
2

Instead of doing double complex z1 = 2.6 + 3.1*I you can use variables in place of 2.6 and 3.1. This should help in reading a single entry from the file:

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

int main(void) 
{ 
    double real, imag;

    //assuming the wp variable is properly initialized
    fscanf(wp,"%c%lg%c%lg%c%c",&c,&real,&c,&imag,&c,&c);

    double complex z = CMPLX(real, imag); 

    printf("z = %.1f% + .1fi\n", creal(z), cimag(z)); 
} 
  • CMPLX() function creates complex number objects by taking real part and imaginary parts as parameters. This function returns the object of complex numbers.
  • creal() function returns the real part of a complex number
  • cimag() function returns the imaginary part of a complex number

from cppreference.com, the following macros are supported for creating complex number object:

#define CMPLX(x, y) ((double complex)((double)(x) + _Imaginary_I * (double)(y)))
#define CMPLXF(x, y) ((float complex)((float)(x) + _Imaginary_I * (float)(y)))
#define CMPLXL(x, y) ((long double complex)((long double)(x) + \
                      _Imaginary_I * (long double)(y)))
Shubhzgang
  • 322
  • 2
  • 9