Search code examples
cpointerscomplex-numbers

How to add two values from a pointer in function?


My teacher said that I must add two complex numbers using a complex type. And I must add these numbers in a function. How to do that? I create something like that, but I have warning when I use cppcheck

add.c:53:26: error: Uninitialized variable: a1 [uninitvar]
    double complex  z1 = a1 + b1*I;
                         ^
add.c:57:26: error: Uninitialized variable: a2 [uninitvar]
    double complex  z2 = a2 + b2*I;
                         ^
add.c:53:31: error: Uninitialized variable: b1 [uninitvar]
    double complex  z1 = a1 + b1*I;
                              ^
add.c:57:31: error: Uninitialized variable: b2 [uninitvar]
    double complex  z2 = a2 + b2*I;
                              ^
add.c:34:29: error: Uninitialized variable: c1 [uninitvar]
    double complex  csum1 = c1 + d1*I;
                            ^
add.c:34:34: error: Uninitialized variable: d1 [uninitvar]
    double complex  csum1 = c1 + d1*I;
                                 ^
add.c:52:15: error: Uninitialized variable: p [uninitvar]
    readZ(wz, p, q);
              ^
add.c:52:18: error: Uninitialized variable: q [uninitvar]
    readZ(wz, p, q);
                 ^
add.c:56:15: error: Uninitialized variable: r [uninitvar]
    readZ(wz, r, s);
              ^
add.c:56:18: error: Uninitialized variable: s [uninitvar]
    readZ(wz, r, s);
                 ^
add.c:59:18: error: Uninitialized variable: t [uninitvar]
    sumZ(p,q,r,s,t,u);
                 ^
add.c:59:20: error: Uninitialized variable: u [uninitvar]
    sumZ(p,q,r,s,t,u);

This is my code

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <complex.h>
#ifndef M_PI
    #define M_PI 3.14159265358979323846
#endif

void readZ(FILE *wp, double *a, double *b)
{
    char c;  
    assert(fscanf(wp,"%c%lg%c%lg%c%c",&c,a,&c,b,&c,&c));

}
int writeZ(FILE *wp, double complex z)
{    
    fprintf(wp, "%.2f, %.2f\n", creal(z), cimag(z));

    return 1;
}

void sumZ(double *a1, double *a2, double *b1, double *b2, double *c1, double *c2)
{
    *c1 = *a1 + *a2;
    *c2 = *b1 + *b2;
}

int main (int argc, char *argv[])
{    
    FILE *wz, *wc;  
    double a1, a2, b1, b2, c1, d1;
    double *p, *q, *r, *s, *t, *u;
    double complex  csum1 = c1 + d1*I;

    if (argc != 3) {                                
    printf("Wrong arguments number\n");
    printf("I should run this way:\n");
    printf("%s source result\n",argv[0]);
    exit(1);
    }

    if( (wz= fopen(argv[1],"r")) == NULL) {
        printf("Open error %s\n", argv[1]);
        exit(1);
    }
    if( (wc= fopen(argv[2], "w")) == NULL) {
        printf("Open error %s\n", argv[2]);
        exit(2);
    }

    readZ(wz, p, q);
    double complex  z1 = a1 + b1*I;
    writeZ(wc, z1);
    printf("%.2f, %.2f\n", creal(z1), cimag(z1));
    readZ(wz, r, s);
    double complex  z2 = a2 + b2*I;
    printf("%.2f, %.2f\n", creal(z2), cimag(z2));
    sumZ(p,q,r,s,t,u);
    printf("%.2f, %.2f\n", creal(csum1), cimag(csum1));

    return 0;
}

When I run my code like add.x data.txt result.txt I get a segmentation fault. He said that I can use references and pointers. I have no idea what I should do now.


Solution

  • There were a number of errors.

    There were a lot of double * pointer variables [that were unitialized]. They aren't really needed. main can just pass down (e.g.) &a1 and &b1. Just because you were told to use pointers doesn't [necessarily] mean that you have to use pointer variables.

    Also, pointers as arguments to a function are only needed for return values. Others can just use variables that are "pass by value". This simpilifies things a bit.

    I had to guess at the correct function calls, based on an analysis of the code to determine your exact intent.

    Your code was still trying to use separate double variables (e.g.) a1 and b1 to get z1 instead of using [mostly] double complex variables everywhere.

    Also, it appears that the argument order for the call to sumZ were reversed.


    Here's a version that is annotated with the bugs and fixes:

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <math.h>
    #include <complex.h>
    #ifndef M_PI
    #define M_PI 3.14159265358979323846
    #endif
    
    void
    readZ(FILE *wp, double *a, double *b)
    {
        char c;
    
    #if 0
        assert(fscanf(wp, "%c%lg%c%lg%c%c", &c, a, &c, b, &c, &c));
    #else
        assert(fscanf(wp, "%c%lg%c%lg%c%c", &c, a, &c, b, &c, &c));
    #endif
    }
    
    int
    writeZ(FILE *wp, double complex z)
    {
    
        fprintf(wp, "%.2f, %.2f\n", creal(z), cimag(z));
    
        return 1;
    }
    
    // NOTE: not a bug exactly, but to simplify, b1/b2 and c1/c2 can be passed by
    // value -- otherwise, mark them with "const" (e.g. const double *b1)
    #if 0
    void
    sumZ(double *a1, double *a2, double *b1, double *b2, double *c1, double *c2)
    {
        *c1 = *a1 + *a2;
        *c2 = *b1 + *b2;
    }
    #endif
    #if 0
    void
    sumZ(double a1, double a2, double b1, double b2, double *c1, double *c2)
    {
        *c1 = a1 + a2;
        *c2 = b1 + b2;
    }
    #endif
    #if 1
    void
    sumZ(double complex a1, double complex b1, double complex *c1)
    {
        *c1 = a1 + b1;
    }
    #endif
    
    int
    main(int argc, char *argv[])
    {
        FILE *wz;
        FILE *wc;
        double a1;
        double a2;
        double b1;
        double b2;
    // NOTE: with refactoring, these are now unused
    #if 0
        double c1;
        double d1;
        double *p;
        double *q;
        double *r;
        double *s;
        double *t;
        double *u;
    #endif
    #if 0
        double csum1;
        double csum2;
    #endif
    // NOTE/BUG: c1 and d1 are _unitialized_
    #if 0
        double complex csum1 = c1 + d1 * I;
    #else
        double complex csum1;
    #endif
    
        if (argc != 3) {
            printf("Wrong arguments number\n");
            printf("I should run this way:\n");
            printf("%s source result\n", argv[0]);
            exit(1);
        }
    
        if ((wz = fopen(argv[1], "r")) == NULL) {
            printf("Open error %s\n", argv[1]);
            exit(1);
        }
        if ((wc = fopen(argv[2], "w")) == NULL) {
            printf("Open error %s\n", argv[2]);
            exit(2);
        }
    
    // NOTE/BUG: _pointers_ p and q are _unitialized_
    #if 0
        readZ(wz, p, q);
    #else
        readZ(wz, &a1, &b1);
    #endif
    // NOTE/BUG: a1 and b1 are _unitialized_ -- assume that above readZ needs to
    // be changed
        double complex z1 = a1 + b1 * I;
    
        writeZ(wc, z1);
        printf("%.2f, %.2f\n", creal(z1), cimag(z1));
    
    // NOTE/BUG: _pointers_ r and s are _unitialized_
    #if 0
        readZ(wz, r, s);
    #else
        readZ(wz, &a2, &b2);
    #endif
    
    // NOTE/BUG: a2 and b2 are _unitialized_ -- assume that above readZ needs to
        double complex z2 = a2 + b2 * I;
        printf("%.2f, %.2f\n", creal(z2), cimag(z2));
    
    // NOTE/BUG: arguments are backwards if you want csum* to be the _sum_
    #if 0
        sumZ(p, q, r, s, t, u);
    #endif
    #if 0
        sumZ(a1, b1, a2, b2, &csum1, &csum2);
    #endif
    #if 1
        sumZ(z1, z2, &csum1);
    #endif
    
        printf("%.2f, %.2f\n", creal(csum1), cimag(csum1));
    
        fclose(wz);
        fclose(wc);
    
        return 0;
    }
    

    Here's a cleaned up version that changes readZ to return a double complex directly, which is [probably] closer to what was intended:

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <math.h>
    #include <complex.h>
    #ifndef M_PI
    #define M_PI 3.14159265358979323846
    #endif
    
    void
    readZ(FILE *wp, double complex *rtn)
    {
        char c;
        double a;
        double b;
    
        assert(fscanf(wp, "%c%lg%c%lg%c%c", &c, &a, &c, &b, &c, &c));
    
        *rtn = a + b * I;
    }
    
    int
    writeZ(FILE *wp, double complex z)
    {
    
        fprintf(wp, "%.2f, %.2f\n", creal(z), cimag(z));
    
        return 1;
    }
    
    void
    sumZ(double complex a1, double complex b1, double complex *c1)
    {
        *c1 = a1 + b1;
    }
    
    int
    main(int argc, char *argv[])
    {
        FILE *wz;
        FILE *wc;
        double complex csum1;
    
        if (argc != 3) {
            printf("Wrong arguments number\n");
            printf("I should run this way:\n");
            printf("%s source result\n", argv[0]);
            exit(1);
        }
    
        if ((wz = fopen(argv[1], "r")) == NULL) {
            printf("Open error %s\n", argv[1]);
            exit(1);
        }
        if ((wc = fopen(argv[2], "w")) == NULL) {
            printf("Open error %s\n", argv[2]);
            exit(2);
        }
    
        double complex z1;
        readZ(wz, &z1);
        writeZ(wc, z1);
        printf("%.2f, %.2f\n", creal(z1), cimag(z1));
    
        double complex z2;
        readZ(wz, &z2);
        printf("%.2f, %.2f\n", creal(z2), cimag(z2));
    
        sumZ(z1, z2, &csum1);
        printf("%.2f, %.2f\n", creal(csum1), cimag(csum1));
    
        fclose(wz);
        fclose(wc);
    
        return 0;
    }