-3

The following code takes an array of integers and create an array with the mobile means (i.e. the value in i-th place is the mean of the last n elements in the array before i (if they exists); if i<n, it is the mean of the existing elements before i. Thus as an example: for n=3 1 2 3 4 5 6 -> 1 1.5 2 3 4 5

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

float *
mobMean (int x[], int n, int nval)
{
    int i, j, sum, num;
    float *means;

    if(means=malloc(sizeof(float) * nval))
    {
        for(i=0; i<nval; i++)
        {
            sum=0;
            num=0;
            for(j=i; j>=0 && i-j>=n; j--)
            {
                sum+=x[j];
                num++;
            }
            *(means+i)=(float)sum/num;
        }
    }
    else
        printf("e");
    return means;
}

int
main()
{
    int a[10], i;
    float *b;
    for(i=0; i<10; i++)
        scanf("%d", &a[i]);
    b=mobMean(a,3,10);
    for(i=0; i<10; i++)
        printf("%f", *(b+i));
    free(b);
    return 0;
}

The console (gcc compiler) returns as an output -nan 10 times consecutively. not only my pc, but also the online compiler. google doesn't have a clue of what that is. i would really appreciate your help.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 2
    Think about the very first calculation. `i` is zero, `j` is set to `i` so it is zero. The loop never executes so `num` is zero and your code tries to divide 0 by 0... NAN = Not A Number. Suggest simplifying the code (without arcane up/down counting & calculations of indices.) – Fe2O3 Jan 02 '23 at 23:37
  • 1
    Please note that in `mobMean` you do check if `malloc` succeeds. Good! But if it has failed, `mobMean` will be returning `NULL`. You do not check for this in `main` before using `b` on the assumption that the memory was allocated. – Chris Jan 02 '23 at 23:47
  • You need to take a close look at `i-j>=n` in your `j` loop. What is it supposed to do? What happens if `i - j` are never `> n`? See [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/), consider a chat with the duck, and see [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/3422102) – David C. Rankin Jan 02 '23 at 23:48
  • Strongly suggest reworking `mobMean` so that is `means` is `NULL` after calling `malloc` you immediately return `NULL`. This will save you a level of indentation and is a reasonably common practice in C. – Chris Jan 02 '23 at 23:49
  • You also must validate EVERY input, e.g. `if (scanf("%d", &a[i]) != 1) { /* handle errror */ }` and you need additional parenthesis surrounding your assignment used as a condition, e.g. `if ((means=malloc(sizeof(float) * nval)))` (hint: if you negate the test you can eliminate unnecessary indentation returning `NULL` on failure). To improve readability of your code, use a bit more spacing and use `means[i]` instead of `*(means + i)`. While they are equivalent, the first is must easier to read. – David C. Rankin Jan 02 '23 at 23:51
  • I really appreciate your input. @DavidC.Rankin i do not agree about using [] instead of *. I would use the brackets if i had declared or had had them in the header, but in this case i am considering means as a pointer to somewhere, not as the name of the array. Fact is that i find very confusing to declare a variabile in a certain way and then accessing it differently. This said, they are equivalent. Again, thank you for you help, your tips on how to rewrite mobMean was veruy helpful. – Simone Licciardi Jan 03 '23 at 18:55
  • If you prefer `*(ptr + offset)`, then that's fine, just don't be surprised if others also suggest `ptr[offset]` as that is a fairly standard readability change. However, for your code -- it is completely up to you. I can read both, or `offset[ptr]` for that matter, but those trying to learn from your code may struggle a bit. – David C. Rankin Jan 04 '23 at 04:34

1 Answers1

2

The body of this for loop

for(j=i; j>=0 && i-j>=n; j--)

is never executed due to the condition i-j>=n because initially i - j is equal to 0.

You could write for example

        sum = x[i];
        num = 1;
        for ( j = i; j-- != 0 && num < n; ++num )
        {
            sum += x[j];
        }

Here is a demonstration program.

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

float * mobMean( const int a[], size_t size, size_t n )
{
    float *means = NULL;

    if (( means = malloc( sizeof( float ) * size ) ) != NULL)
    {
        for (size_t i = 0; i < size; i++)
        {
            float sum = a[i];
            size_t num = 1;

            for (size_t j = i; j-- != 0 && num < n; ++num)
            {
                sum += a[j];
            }

            means[i] = sum / num;
        }
    }

    return means;
}

int main( void )
{
    int a[] = { 1, 2, 3, 4, 5, 6 };
    const size_t N = sizeof( a ) / sizeof( *a );

    float *b = mobMean( a, N, 3 );
        
    if (b != NULL)
    {
        for (size_t i = 0; i < N; i++)
        {
            printf( "%.1f ", b[i] );
        }
        putchar( '\n' );
    }

    free( b );
}

The program output is

1.0 1.5 2.0 3.0 4.0 5.0

I declared local variables in for loops. You may declare them before loops in beginnings of code blocks if you marked the question with the language tag c89.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335