C中的指针,使用数组获得意外结果

时间:2018-06-28 13:10:34

标签: c arrays function pointers dynamic-arrays

我想为多个数字计算阶乘并以数组形式返回结果。这是我的程序:

#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 :(得分:2)

fac上的每个for循环之前,您需要将j重置为1,否则在每次计算中,除第一个因素外,第一个因数都不会从1开始。

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

答案 1 :(得分:1)

如前所述,您的问题出在变量“ 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;
}

答案 2 :(得分:0)

以下建议的代码:

  1. 检查C库函数错误
  2. 检查用户输入的有效性
  3. 不允许元素数为负或0
  4. 不允许元素值为负数
  5. 消除了OPs代码中的“隐式转换”
  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;
}