内存分配在C中是如何工作的?//我的代码有什么问题?

r9f1avp5  于 2023-08-03  发布在  其他
关注(0)|答案(4)|浏览(86)

刚接触编程,我正在解决一个问题,我应该打印一个递减数字的正方形图案,使得5将给予:

5 5 5 5 5 5 5 5 5 
5 4 4 4 4 4 4 4 5 
5 4 3 3 3 3 3 4 5 
5 4 3 2 2 2 3 4 5 
5 4 3 2 1 2 3 4 5 
5 4 3 2 2 2 3 4 5 
5 4 3 3 3 3 3 4 5 
5 4 4 4 4 4 4 4 5 
5 5 5 5 5 5 5 5 5

字符串
我想到了用数组,反复从数组中减去并打印出来来解决这个问题;

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

int main() 
{
    int n;
    scanf("%d", &n);
    // Complete the code to print the pattern.
    int *arr;
    int k = 1;
    arr = calloc(2 * n - 1, sizeof(char));
    
    for (int i = 0; i < 2 * n - 1; i++) {
        *(arr + i) = n;
    }
    do {
        for (int i = 0; i < 2 * n - 1; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
        for (int i = k; i < 2 * n - 1 - k; i++) {
            arr[i] = arr[i] - 1;
        }
        k++;
        
    } while (k <= n);
    
    k = n - 1;
    
    for (int j = 1; j < n; j++) {
        
        for (int i = k; i < 2 * n - 1 - k; i++) {
            arr[i]++;
        }
        k--;
        
        for (int i = 0; i < 2 * n - 1; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    }
    
    return 0;
}


这在Visual Studio代码中可以工作,但在网站上的编译器上不行,在我测试的另一个在线编译器上也不行。我假设我在calloc部分搞砸了。有什么问题吗?

mlmc2os5

mlmc2os51#

sizeof(int),而不是sizeof(char)

w8f9ii69

w8f9ii692#

您使用动态分配的阵列的方法是1)不安全和2)低效的。
首先,您需要检查用户在scanf调用中是否输入了有效的正数

scanf("%d", &n);

字符串
您还需要检查是否已成功分配内存。你必须正确地指定分配数组的元素的大小。也就是说,您需要使用表达式sizeof( int )而不是sizeof( char )

arr = calloc(2*n-1, sizeof(int));


第三,你需要知道最大输出值的宽度。否则,具有图案的table将不会正确对齐。例如,尝试在n等于10时运行程序。
你的程序也有太多的循环。
最后你需要释放分配的内存。
为了输出模式,不需要动态分配内存。只需使用一对嵌套的for循环和函数printf就足够了。
这是一个演示程序。这个程序的诀窍就是用这两个表达式

int value_for_row    = abs( n - i - 1 ) + 1;
int value_for_column = abs( n - j - 1 ) + 1;


调查他们。

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

int main( void )
{
    //  The value of the constant MAX_WIDTH of the pattern 
    //  may be any positive number not greater than INT_MAX / 2
    const int MAX_WIDTH = 100;

    while (1)
    {
        printf( "Enter a non-negative number not greater than %d (0 - exit): ", MAX_WIDTH );

        int n;

        if ( scanf( "%d", &n ) != 1 || ( n <= 0 )) break;

        if ( MAX_WIDTH < n ) n = MAX_WIDTH;

        int item_width = 1;

        for (int tmp = n; tmp /= 10; ) ++item_width;

        putchar( '\n' );

        for ( int i = 0, m = 2 * n - 1; i < m; i++)
        {
            for (int j = 0; j < m; j++)
            {
                int value_for_row    = abs( n - i - 1 ) + 1;
                int value_for_column = abs( n - j - 1 ) + 1;

                int current_item = value_for_row < value_for_column 
                    ? value_for_column
                    : value_for_row;

                printf( "%*d ", item_width, current_item );
            }
            putchar( '\n' );
        }

        putchar( '\n' );
    }
}


程序输出可能如下所示

Enter a non-negative number not greater than 100 (0 - exit): 1

1

Enter a non-negative number not greater than 100 (0 - exit): 2

2 2 2
2 1 2
2 2 2

Enter a non-negative number not greater than 100 (0 - exit): 3

3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3

Enter a non-negative number not greater than 100 (0 - exit): 4

4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4

Enter a non-negative number not greater than 100 (0 - exit): 5

5 5 5 5 5 5 5 5 5
5 4 4 4 4 4 4 4 5
5 4 3 3 3 3 3 4 5
5 4 3 2 2 2 3 4 5
5 4 3 2 1 2 3 4 5
5 4 3 2 2 2 3 4 5
5 4 3 3 3 3 3 4 5
5 4 4 4 4 4 4 4 5
5 5 5 5 5 5 5 5 5

Enter a non-negative number not greater than 100 (0 - exit): 10

10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
10  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9 10
10  9  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  9 10
10  9  8  7  7  7  7  7  7  7  7  7  7  7  7  7  8  9 10
10  9  8  7  6  6  6  6  6  6  6  6  6  6  6  7  8  9 10
10  9  8  7  6  5  5  5  5  5  5  5  5  5  6  7  8  9 10
10  9  8  7  6  5  4  4  4  4  4  4  4  5  6  7  8  9 10
10  9  8  7  6  5  4  3  3  3  3  3  4  5  6  7  8  9 10
10  9  8  7  6  5  4  3  2  2  2  3  4  5  6  7  8  9 10
10  9  8  7  6  5  4  3  2  1  2  3  4  5  6  7  8  9 10
10  9  8  7  6  5  4  3  2  2  2  3  4  5  6  7  8  9 10
10  9  8  7  6  5  4  3  3  3  3  3  4  5  6  7  8  9 10
10  9  8  7  6  5  4  4  4  4  4  4  4  5  6  7  8  9 10
10  9  8  7  6  5  5  5  5  5  5  5  5  5  6  7  8  9 10
10  9  8  7  6  6  6  6  6  6  6  6  6  6  6  7  8  9 10
10  9  8  7  7  7  7  7  7  7  7  7  7  7  7  7  8  9 10
10  9  8  8  8  8  8  8  8  8  8  8  8  8  8  8  8  9 10
10  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9  9 10
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10

Enter a non-negative number not greater than 100 (0 - exit): 0

kfgdxczn

kfgdxczn3#

内存分配在C中是如何工作的?//我的代码有什么问题?
您的分配语句确实存在一个主要问题,导致了未定义的行为,与您的观察结果一致:代码可以如预期的那样在一些目标上工作而在其他目标上不工作。
arr中为2 * n - 1条目分配内存,使用arr = calloc(2 * n - 1, sizeof(char));问题是arrint的数组,因此元素大小应为sizeof(int)。通过分配2 * n - 1字节,当代码写入超出所分配块的末尾时,会导致未定义的行为。
这里有一个更安全的方法:始终使用目标条目类型的大小:

int *arr = calloc(2 * n - 1, sizeof(*arr));

字符串
还要注意,您应该检查scanfcalloc故障,并在不再需要内存时释放内存。
以下是修改后的版本:

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

int main(void)
{
    int n;
    if (scanf("%d", &n) != 1 || n <= 0) {
        fprintf(stderr, "invalid input\n");
        return 1;
    }

    int width = 2 * n - 1;
    int *arr = calloc(width, sizeof(*arr));
    if (arr == NULL) {
        fprintf(stderr, "memory allocation failed\n");
        return 1;
    }

    for (int k = 0; k < n; k++) {
        for (int i = k; i < width - k; i++) {
            arr[i] = n - k;
        }
        for (int i = 0; i < width; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    }
    for (int k = n - 2; k >= 0; k--) {
        for (int i = k; i < width - k; i++) {
            arr[i] = n - k;
        }
        for (int i = 0; i < width; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
    }
    free(arr);
    return 0;
}


然而,请注意,代码可以进一步简化,而无需内存分配,通过从简单的数学公式计算动态打印值:

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

int max(int a, int b) { return a > b ? a : b; }

int main(void) {
    int n;
    if (scanf("%d", &n) != 1 || n <= 0) {
        fprintf(stderr, "invalid input\n");
        return 1;
    }

    for (int k = 1 - n; k <= n - 1; k++) {
        for (int j = 1 - n; j <= n - 1; j++) {
            printf("%d ", 1 + max(abs(k), abs(j)));
        }
        printf("\n");
    }
    return 0;
}

zte4gxcn

zte4gxcn4#

为什么不干脆:

for (int i = -n + 1; i < n; i++) {
        for (int j = -n + 1; j < n; j++)
            printf("%d ", 1 + (abs(i) > abs(j) ? abs(i) : abs(j)));
        putchar('\n');
    }

字符串

相关问题