Указатели в C, получение непредвиденных результатов с массивами - PullRequest
0 голосов
/ 28 июня 2018

Я хочу вычислить факториалы для нескольких чисел и вернуть результаты в виде массива. Вот моя программа:

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

int *fact(int arr[], int n) {
    int *facts, fac = 1, i, j;

    facts = (int *) malloc(n * sizeof(int));

    for (i = 0; i < n; i++) {
        for (j = 1; j <= *(arr + i); j++)
            fac = fac * j;

        *(facts + i) = fac;
    }

    return facts;
}

int main(void) {
    int *num, *facto, n, i;     //Initializing variables.

    printf("How many numbers to calculate factorial for :\t");
    scanf("%d", &n);

    num = (int*) malloc(n * sizeof(int));   //Dynamic allocation for array num.

    printf("Enter the elements separated by spaces :\t");

    for (i = 0; i < n; i++)
        scanf("%d", num + i);

    facto = fact(num, n);

    printf("\nFactorials are :\t");

    for (i = 0; i < n; i++)
        printf("%d\t", *(facto + i));

    printf("\n");

    return 0;
}

Однако при печати элементов возвращаемого массива верным является только первое значение. Остальные кажутся случайными.

Что не так с этой программой, и как я могу это исправить?

Ответы [ 3 ]

0 голосов
/ 28 июня 2018

Как говорилось ранее, ваша проблема заключается в том, что переменная "fac" не сбрасывается в 1.

Хороший способ сделать ваш код коротким и менее подверженным ошибкам, например, с помощью функции, которая делает только одно.

Например, ваша функция фактов выделяет и вычисляет факториал. Вы можете разделить эту функцию на две части так:

int factorial(int n)
{
    int result = 1;

    for (int i = 2; i <= n; ++i) {
        result *= i;
    }

    return (result);
}


int *fact(int arr[], int n)
{
    int *facts = NULL;

    if (!(facts = malloc(n * sizeof(*facts))) {
        // TODO Log (strerror(errno));
        return (NULL);
    }

    for (int i = 0; i < n ; ++i) {
        facts[i] = factorial(arr[i]);
    }

    return facts;
}
0 голосов
/ 29 июня 2018

следующий предложенный код:

  1. проверяет ошибки функций библиотеки C
  2. проверяет правильность ввода пользователя
  3. не допускает отрицательный или 0 для количества элементов
  4. не допускает отрицательное число для значения элемента
  5. устраняет «неявные преобразования», обнаруженные в коде OP
  6. устраняет ненужное выделение кучи
  7. устраняет утечку памяти
  8. минимизирует «область видимости» локальных переменных
  9. использует соответствующие горизонтальные и вертикальные интервалы для удобства чтения и понимания
  10. следует аксиоме: только один оператор на строку и (самое большее) одно объявление переменной на оператор.

и теперь предложенный код:

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


// prototypes
void fact( size_t arr[], int n);


void fact( size_t arr[], int n)
{

    for ( int i = 0; i < n; i++)
    {
        if( !arr[i] )
        {
            puts( "factorial for 0 not calculated" );
        }

        else
        {
            size_t fac = 1;
            for ( size_t j = arr[i]; j > 1; j-- )
            {
                fac = fac * j;
            }
            arr[i] = fac;
        }
    }
}


int main( void )
{
    int n;

    printf("How many numbers to calculate factorial for :\t");
    if( scanf("%d", &n) != 1)
    {
        fprintf( stderr, "scanf for number of factorials failed\n" );
        exit( EXIT_FAILURE );
    }

    // implied else, scanf successful

    if( n < 0 )
    {
        puts( "negative number of elements is invalid" );
        exit( EXIT_FAILURE );
    }

    // implied else, scanf for number of elements successful

    if( !n )
    {
        puts( "nothing to do" );
        exit( EXIT_FAILURE );
    }

    // implied else, valid number of elements

    size_t *num = malloc( (size_t)n * sizeof( size_t ) );
    if( !num )
    {
        perror( "malloc failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, malloc successful

    printf("Enter the elements separated by spaces :\t");

    for ( int i = 0; i < n; i++ )
    {
        if( scanf( "%lu", &num[i] ) != 1 )
        {
            fprintf( stderr, "scanf for element failed\n" );
            free( num );
            exit( EXIT_FAILURE );
        }
    }

    fact(num, n);

    printf("\nFactorials are :\t");

    for ( int i = 0; i < n; i++ )
        printf("%lu\t", num[i] );

    printf("\n");

    // cleanup
    free( num );

    return 0;
}
0 голосов
/ 28 июня 2018

Вам необходимо сбросить fac до 1 перед каждым циклом for на j, в противном случае при каждом вычислении, кроме первого, первый коэффициент не будет начинаться с 1:

for(i=0; i<n; i++) {   
   fac = 1; // HERE
   for(j=1; j<= *(arr+i); j++) {
        fac = fac*j;
   }
   *(facts+i) = fac;
}
...