Home > Blockchain >  Comparison in swich-case does not give the correct value
Comparison in swich-case does not give the correct value

Time:09-26

I am very new to programming with C. I am making a small program that calculates:

  • Arithmetic mean (A)
  • Geometric mean(G)
  • Harmonic Mean (H)

the program receives some letter of the above that indicates which function is going to be executed and a list of floats with which it will work in said function:

float aritmetic(float datos[], int n)
float geometric(float datos[], int n)
float harmonic(float datos[], int n)

the main function is as follows:

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

int main(int argc, char *argv[])
{
    int n = argc-2;

    float data[1];

    char operation = *argv[1];

    for(int j = 0;j < argc-2;j  ){
        data[j] = atof(argv[j 2]);
    }

    switch(operation)
    {   
        case 'A':
            printf("%f\n",aritmetic(data,n));
        case 'G':
            printf("%f\n",geometric(data,n));
        case 'H':
            printf("%f\n",harmonic(data,n));
        default:
            return 0;
    }

}

But in the switch, it does not recognize any character, it always sends me to the default clause, could someone guide me to solve the problem?

CodePudding user response:

I created this minimal example to verify your description.

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

int main(int argc, char *argv[])
{
    int n = argc-2;


    if(argc < 2) return 1;
    
    char operation = *argv[1];



    switch(operation)
    {   
        case 'A':
            printf("a\n");
            //break;
        case 'G':
            printf("g\n");
            //break;
        case 'H':
            printf("h\n");
            //break;
        default:
            return 0;
            //break;
    }
    
    return 2;

}

It turns out that the switch executes not only the default case, but all the cases, if the input starts with "A".
This is because you omitted the needed breaks, which I inserted as comments.

In case this does not match your observation, the problem is likely caused by the undefined behaviour and lack of plausibility checking, as hinted in the comments.

CodePudding user response:

There are multiple issues in the code:

  • There is a typo in float data[1]; you should define an array of length n instead.

  • Furthermore, you should test the value of argc before this definition.

  • There are missing break; statements after the printf() in each clause in the switch statement.

Here is a modified version:

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

float arithmetic(float datos[], int n);
float geometric(float datos[], int n);
float harmonic(float datos[], int n);

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("missing arguments\n");
        return 1;
    }
    char operation = *argv[1];
    if (!operation || !strchr("AGH", operation)) {
        printf("invalid operation: %c, expect A, G or H\n", operation);
        return 1;
    }
    int n = argc - 2;
    float data[n];

    for (int i = 0; i < n; i  ) {
        char *p;
        data[i] = strtof(argv[i   2], &p);
        if (p == argv[i   2] || *p != '\0') {
            printf("invalid number: %s\n", argv[i   2]);
        }
    }

    switch (operation) {   
      case 'A':
        printf("%f\n", arithmetic(data, n));
        break;
      case 'G':
        printf("%f\n", geometric(data, n));
        break;
      case 'H':
        printf("%f\n", harmonic(data, n));
        break;
    }
    return 0;
}

CodePudding user response:

In light of the issues pointed out in the comments above, and realising that a short list of numbers will be processed in the wink-of-an-eye:

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

int main( int argc, char *argv[] )
{
    float data[ argc ]; // an unused float floating around
    memset( data, 0, sizeof data );

    for( int j = 1; j < argc; j   )
        data[ j - 1 ] = atof( argv[ j ] );

    printf( "Arithmetic mean: %f\n", aritmetic( data, argc - 1 ) );
    printf( "Geometric mean: %f\n", geometric( data, argc - 1 ) );
    printf( "Harmonic mean: %f\n", harmonic( data, argc - 1 ) );

    return 0;
}

EDIT: Forgive me for taking advantage of this question and trying to learn what the last two items actually are... (Thank you Wikipedia!)

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

int main( int argc, char *argv[] )
{
    if( argc < 2 ) return 1;

    float sum = 0.0;
    float sumrecip = 0.0;
    float prod = 1.0;

    int count = --argc;
    while( argc ) {
        float v = (float)atof( argv[ argc-- ] );
        sum  = v;
        sumrecip  = 1.0/v;
        prod *= v;
    }

    printf( "Arithmetic mean: %f\n", sum/count );
    printf( "Geometric mean: %f\n", (float) powf( prod, 1.0/count ) );
    printf( "Harmonic mean: %f\n", count/sumrecip );

    return 0;
}

for command ./a.out 1 4 4

Arithmetic mean: 3.000000
Geometric mean: 2.519842
Harmonic mean: 2.000000

Sure 'nuff. Done in the wink-of-an-eye.
Life's lesson: Don't go looking for confusion. It'll find you.
(I do hope the math is right in this answer...)

  • Related