0

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.

Jakub
  • 679
  • 5
  • 16
  • 1
    The better duplicate would be https://stackoverflow.com/questions/1597405/what-happens-to-a-declared-uninitialized-variable-in-c-does-it-have-a-value. But I see no reason to reopen the question for immediately close it again. May be some "C" gold badge owner will change the dupe. – Tsyvarev May 17 '20 at 23:00
  • @CraigEstey the question is reopened – M.M May 18 '20 at 03:50
  • The diagnostics presented -- errors, not warnings -- do not appear to be matched with the code presented. – John Bollinger May 18 '20 at 04:03

1 Answers1

1

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;
}
Craig Estey
  • 30,627
  • 4
  • 24
  • 48