鱼C论坛

 找回密码
 立即注册
查看: 715|回复: 18

[已解决]调用函数后,main函数里变量的值发生改变

[复制链接]
发表于 2024-2-4 22:53:57 | 显示全部楼层 |阅读模式
60鱼币
本帖最后由 孤不冷cing 于 2024-2-4 22:56 编辑
#include <stdio.h>

void create_magic_square(int n, char magic_square[n][n]);
void print_magic_square(int n, char magic_square[n][n]);

int main(void)
{
        int n;
        char magic_square[n][n];

        printf("Enter size of magic square:");
        scanf(" %d", &n);

        printf("%5d\n", n);
        print_magic_square(n, magic_square);

        create_magic_square(n, magic_square);

        printf("%5d\n", n);

        return 0;   19   25    1    7   13
   24    5    6   12   18
    4   10   11   17   23
    9   15   16   22    3
   14   20   21    2    8

}

void create_magic_square(int n, char magic_square[n][n])
{
        for (int i = 0; i < n; i++)
        {
                for (int j = 0; j < n; j++)
                {
                        magic_square[i][j] = 0;
                }
        }

        int row = 0, column = n/2;

        for (int i = 1; i < (n*n+1); i++)
        {
                magic_square[row][column] = i;
                row--, column++;
                if (row < 0) row+=n;
                if (column >= n) column-=n;
                if (magic_square[row][column]) row++;
        }
}

void print_magic_square(int n, char magic_square[n][n])
{
        for (int row = 0; row < n; row++)
        {
                for (int column = 0; column < n; column++)
                {
                        printf("%5d", magic_square[row][column]);
                }
                putchar('\n');
        }
}

运行结果
[fal@ah-ipv6 c_9]$ gcc -g -o 9_5 9_5.c && ./9_5
Enter size of magic square:5
    5
    0    0    0    0    0
    0    0    0    0    0
    0    0    0    0    0
    0    0    0    0    0
    5    0    0    0 -128
34935822

原本设想结果
   19   25    1    7   13
   24    5    6   12   18
    4   10   11   17   23
    9   15   16   22    3
   14   20   21    2    8

为什么会这样啊?进create函数之后,main中的n和magic_square就直接扔了吗?create结束这俩又被随机弄了个值?
但是他俩不是main的块作用域吗,这就算离开块作用域了?那我应该怎么写啊?

第二次只打印了n,没有打印magic_square。因为n太大了,一调用打印函数直接打印飞了
最佳答案
2024-2-4 22:53:58
#include <stdio.h>

void create_magic_square(int n, char magic_square[n][n]);
void print_magic_square(int n, char magic_square[n][n]);

int main(void)
{
        int n;
        //char magic_square[n][n];    // 提问,这个数组有多少个字节?
        // 换句话说,程序执行到这里的时候,n的值是几?

        printf("Enter size of magic square:");
        scanf(" %d", &n);

        char magic_square[n][n];

        printf("%5d\n", n);
        print_magic_square(n, magic_square);

        create_magic_square(n, magic_square);

        printf("%5d\n", n);

        return 0;
}

void create_magic_square(int n, char magic_square[n][n])
{
        for (int i = 0; i < n; i++)
        {
                for (int j = 0; j < n; j++)
                {
                        magic_square[i][j] = 0;
                }
        }

        int row = 0, column = n/2;

        for (int i = 1; i < (n*n+1); i++)
        {
                magic_square[row][column] = i;
                row--, column++;
                if (row < 0) row+=n;
                if (column >= n) column-=n;
                if (magic_square[row][column]) row++;
        }
}

void print_magic_square(int n, char magic_square[n][n])
{
        for (int row = 0; row < n; row++)
        {
                for (int column = 0; column < n; column++)
                {
                        printf("%5d", magic_square[row][column]);
                }
                putchar('\n');
        }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-4 22:53:58 | 显示全部楼层    本楼为最佳答案   
#include <stdio.h>

void create_magic_square(int n, char magic_square[n][n]);
void print_magic_square(int n, char magic_square[n][n]);

int main(void)
{
        int n;
        //char magic_square[n][n];    // 提问,这个数组有多少个字节?
        // 换句话说,程序执行到这里的时候,n的值是几?

        printf("Enter size of magic square:");
        scanf(" %d", &n);

        char magic_square[n][n];

        printf("%5d\n", n);
        print_magic_square(n, magic_square);

        create_magic_square(n, magic_square);

        printf("%5d\n", n);

        return 0;
}

void create_magic_square(int n, char magic_square[n][n])
{
        for (int i = 0; i < n; i++)
        {
                for (int j = 0; j < n; j++)
                {
                        magic_square[i][j] = 0;
                }
        }

        int row = 0, column = n/2;

        for (int i = 1; i < (n*n+1); i++)
        {
                magic_square[row][column] = i;
                row--, column++;
                if (row < 0) row+=n;
                if (column >= n) column-=n;
                if (magic_square[row][column]) row++;
        }
}

void print_magic_square(int n, char magic_square[n][n])
{
        for (int row = 0; row < n; row++)
        {
                for (int column = 0; column < n; column++)
                {
                        printf("%5d", magic_square[row][column]);
                }
                putchar('\n');
        }
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-4 22:54:22 | 显示全部楼层
在C语言中,函数的参数传递是通过值传递的。这意味着当你调用一个函数时,传递给函数的参数的副本将会被创建。在你的代码中,`create_magic_square`函数接收的`n`和`magic_square`参数只是`main`函数中对应变量的副本。

因此,在`create_magic_square`函数中对`magic_square`进行的赋值不会影响`main`函数中的`magic_square`变量。这也就解释了为什么在`print_magic_square`函数中,打印出来的`magic_square`都是0。

要解决这个问题,您可以将`create_magic_square`函数修改为接收指向`magic_square`变量的指针,并通过修改指针所指向的值来改变`magic_square`变量。

下面是修改后的代码示例:
#include <stdio.h>

void create_magic_square(int n, char *magic_square);
void print_magic_square(int n, char magic_square);

int main(void)
{
        int n;
        char magic_square[100];

        printf("Enter size of magic square:");
        scanf(" %d", &n);

        printf("%5d\n", n);
        print_magic_square(n, magic_square);

        create_magic_square(n, magic_square);

        printf("%5d\n", n);

        return 0;
}

void create_magic_square(int n, char *magic_square)
{
        for (int i = 0; i < n; i++)
        {
                for (int j = 0; j < n; j++)
                {
                        *(magic_square + i*n + j) = 0;
                }
        }

        int row = 0, column = n/2;

        for (int i = 1; i < (n*n+1); i++)
        {
                *(magic_square + row*n + column) = i;
                row--, column++;
                if (row < 0) row+=n;
                if (column >= n) column-=n;
                if (*(magic_square + row*n + column)) row++;
        }
}

void print_magic_square(int n, char *magic_square)
{
        for (int row = 0; row < n; row++)
        {
                for (int column = 0; column < n; column++)
                {
                        printf("%5d", *(magic_square + row*n + column));
                }
                putchar('\n');
        }
}

这里,`magic_square`变量被声明为一个字符数组,大小为100。而在`create_magic_square`函数中,我们通过使用指针运算符`*`来访问和修改`magic_square`数组的元素。

这样,你就可以正确地创建和打印魔方阵了。希望能对您有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-2-4 23:00:13 | 显示全部楼层
FishC 发表于 2024-2-4 22:54
在C语言中,函数的参数传递是通过值传递的。这意味着当你调用一个函数时,传递给函数的参数的副本将会被创 ...

但是数组名不就是指向第一个元素的指针吗,我传递数组名,不就是传递了指针?
再者,我调用create函数之前,n确实已经通过scanf赋了值,为什么后面值又发生了改变?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-4 23:00:43 | 显示全部楼层
孤不冷cing 发表于 2024-02-04 23:00
但是数组名不就是指向第一个元素的指针吗,我传递数组 ...


对于数组参数,当传递一个数组名称给函数时,实际上传递的是数组的地址,即指向数组第一个元素的指针。因此,您在`create_magic_square`函数中使用的`magic_square`参数实际上是指向`main`函数中的`magic_square`数组的指针。

那么问题出在哪里呢?问题出在在`create_magic_square`函数中,您没有正确地修改数组中的值。在代码中,您使用了`magic_square = i;`来修改数组元素的值,但事实上,这会将指针`magic_square`指向一个新的地址,而不是修改数组中的元素。

为了解决这个问题,您可以使用指针运算符`*`来访问和修改数组元素的值,就像我在前面的回答中提到的那样。这样,您可以通过修改指针所指向的内存位置来改变数组中的值。下面是修改后的代码示例:
#include <stdio.h>

void create_magic_square(int n, char *magic_square);
void print_magic_square(int n, char *magic_square);

int main(void) {
    int n;
    printf("Enter size of magic square:");
    scanf("%d", &n);
    
    char magic_square[n][n];  // 创建大小为 n*n 的二维数组
    
    print_magic_square(n, &magic_square[0][0]);
    create_magic_square(n, &magic_square[0][0]);
    print_magic_square(n, &magic_square[0][0]);
    
    return 0;
}

void create_magic_square(int n, char *magic_square) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            *(magic_square + i*n + j) = 0;
        }
    }
    
    int row = 0, column = n/2;
    for (int i = 1; i < (n*n+1); i++) {
        *(magic_square + row*n + column) = i;
        row--, column++;
        if (row < 0) row += n;
        if (column >= n) column -= n;
        if (*(magic_square + row*n + column)) row++;
    }
}

void print_magic_square(int n, char *magic_square) {
    for (int row = 0; row < n; row++) {
        for (int column = 0; column < n; column++) {
            printf("%5d", *(magic_square + row*n + column));
        }
        putchar('\n');
    }
}

在`main`函数中,我在调用`create_magic_square`和`print_magic_square`函数时传递了指向`magic_square[0][0]`的指针,这样就可以正确地操作和打印魔方阵了。

希望这次能给您解惑,如果还有问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-2-4 23:03:05 | 显示全部楼层
这是《C语言程序设计现代方法》第九章的一道课后题,他题干给了我函数原型,要求我这么定义形式参数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-4 23:03:23 | 显示全部楼层
孤不冷cing 发表于 2024-02-04 23:03
这是《C语言程序设计现代方法》第九章的一道课后题, ...


对不起,我之前给出的回答有误。根据您给出的题目要求,我们需要按照函数原型定义形式参数。在C语言中,数组作为函数参数时,会自动退化为指针,因此我们可以按照以下方式定义形参:
void create_magic_square(int n, char magic_square[][n]);
void print_magic_square(int n, char magic_square[][n]);

这样,我们就能正确地定义和操作二维数组了。

另外,为了正确访问和修改数组内的元素,请将`create_magic_square`函数和`print_magic_square`函数中的对应部分修改为:
void create_magic_square(int n, char magic_square[][n]) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            magic_square[i][j] = 0;
        }
    }
    //...
}

void print_magic_square(int n, char magic_square[][n]) {
    //...
}

这样,就能正确传递并操作二维数组了。希望这次能解决您的问题,如果还有疑问,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-2-4 23:06:08 | 显示全部楼层
FishC 发表于 2024-2-4 23:00
对于数组参数,当传递一个数组名称给函数时,实际上传递的是数组的地址,即指向数组第一个元素的指针。 ...

为什么第一次和第二次打印的n的值不一样
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-4 23:06:31 | 显示全部楼层
孤不冷cing 发表于 2024-02-04 23:06
为什么第一次和第二次打印的n的值不一样


非常抱歉,我没有在前面的回答中注意到这个问题。在您的代码中,的确存在一个问题导致第一次和第二次打印的`n`值不同。问题出在您在调用`print_magic_square`函数时传递的参数类型不匹配。

在`main`函数中,`n`被声明为一个`int`类型的变量,而在`print_magic_square`函数的参数列表中,`n`被声明为一个`char`类型的变量。这导致在传递`n`给`print_magic_square`函数时发生了类型错误。正因为如此,`print_magic_square`函数中打印出的`n`值是不确定的。

要解决这个问题,您只需将`print_magic_square`函数中的`n`参数从`char`类型更改为`int`类型,以使其与`main`函数中的`n`类型匹配。下面是修改后的代码示例:
#include <stdio.h>

void create_magic_square(int n, char *magic_square);
void print_magic_square(int n, char *magic_square);

int main(void) {
    int n;
    printf("Enter size of magic square:");
    scanf("%d", &n);

    char magic_square[n*n];  // 创建大小为 n*n 的一维数组

    print_magic_square(n, magic_square);
    create_magic_square(n, magic_square);
    print_magic_square(n, magic_square);

    return 0;
}

void create_magic_square(int n, char *magic_square) {
    // 省略部分代码...
}

void print_magic_square(int n, char *magic_square) {
    // 省略部分代码...
}

现在,`print_magic_square`函数接收的参数类型已经与`main`函数中的`n`类型匹配,打印出的`n`值应该是正确的。

非常抱歉给您造成了困扰,并感谢您指出这个问题。如果您还有其他问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-2-4 23:16:30 | 显示全部楼层

噢噢,原来问题在这,为什么这样就好了啊
我的写法,magic_square是不是大的没边了?
这是造成了什么问题?我在create结尾直接用print_magic_square打印可以正常打印
出了create,main里的n和magic_square的值就都变了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-4 23:16:48 | 显示全部楼层
孤不冷cing 发表于 2024-02-04 23:16
噢噢,原来问题在这,为什么这样就好了啊
我的写法, ...


非常抱歉,我给出的解释有误。问题的根源实际上不在于参数的类型不匹配,而是在于您对指针的使用上还存在一些问题。

首先,将`magic_square`声明为一个字符变量,它只能存储一个字符的值,而不是一个二维数组。为了正确表示一个二维数组,您需要将`magic_square`声明为一个指向字符的指针,并且在函数内部动态分配内存来存储真正的二维数组。

另外,在`create_magic_square`函数中,您需要使用指针运算符 `*` 来访问和修改指针所指向的内存位置的值。

下面是修改后的代码示例:
#include <stdio.h>
#include <stdlib.h>

void create_magic_square(int n, int **magic_square);
void print_magic_square(int n, int **magic_square);

int main(void) {
    int n;
    printf("Enter size of magic square:");
    scanf("%d", &n);

    // 动态分配内存以存储二维数组
    int **magic_square = (int **)malloc(n * sizeof(int *));
    for (int i = 0; i < n; i++) {
        magic_square[i] = (int *)malloc(n * sizeof(int));
    }

    // 打印初始的魔方阵
    print_magic_square(n, magic_square);

    // 创建魔方阵
    create_magic_square(n, magic_square);

    // 打印最终的魔方阵
    print_magic_square(n, magic_square);

    // 释放动态分配的内存
    for (int i = 0; i < n; i++) {
        free(magic_square[i]);
    }
    free(magic_square);

    return 0;
}

void create_magic_square(int n, int **magic_square) {
    // 省略部分代码...
}

void print_magic_square(int n, int **magic_square) {
    // 省略部分代码...
}

在这个修改后的代码中,我们使用了双重指针来表示二维数组,并使用动态内存分配函数 `malloc` 来为二维数组分配内存。这样,我们就能够正确地创建和访问二维数组了。

希望这次的解答能帮到您,如果还有疑问,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-4 23:21:08 | 显示全部楼层
孤不冷cing 发表于 2024-2-4 23:16
噢噢,原来问题在这,为什么这样就好了啊
我的写法,magic_square是不是大的没边了?
这是造成了什么问 ...

你在使用变量之前没有初始化么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-2-4 23:22:30 | 显示全部楼层
人造人 发表于 2024-2-4 23:21
你在使用变量之前没有初始化么

scanf不是改变了n的值,为什么create调用结束后,n的值也变了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-4 23:32:56 | 显示全部楼层
孤不冷cing 发表于 2024-2-4 23:22
scanf不是改变了n的值,为什么create调用结束后,n的值也变了

哪变了?
sh-5.2$ cat main.c
#include <stdio.h>

void create_magic_square(int n, char magic_square[n][n]);
void print_magic_square(int n, char magic_square[n][n]);

int main(void)
{
        int n;
        //char magic_square[n][n];    // 提问,这个数组有多少个字节?
        // 换句话说,程序执行到这里的时候,n的值是几?

        printf("Enter size of magic square:");
        scanf(" %d", &n);

        char magic_square[n][n];

        printf("%5d\n", n);
        print_magic_square(n, magic_square);

        create_magic_square(n, magic_square);

        printf("%5d\n", n);

        return 0;
}

void create_magic_square(int n, char magic_square[n][n])
{
        for (int i = 0; i < n; i++)
        {
                for (int j = 0; j < n; j++)
                {
                        magic_square[i][j] = 0;
                }
        }

        int row = 0, column = n/2;

        for (int i = 1; i < (n*n+1); i++)
        {
                magic_square[row][column] = i;
                row--, column++;
                if (row < 0) row+=n;
                if (column >= n) column-=n;
                if (magic_square[row][column]) row++;
        }
}

void print_magic_square(int n, char magic_square[n][n])
{
        for (int row = 0; row < n; row++)
        {
                for (int column = 0; column < n; column++)
                {
                        printf("%5d", magic_square[row][column]);
                }
                putchar('\n');
        }
}
sh-5.2$ ./main
Enter size of magic square:5
    5
   96  -29   63  -59   84
  115    0    0  -56  105
  125  124   -4  127    0
    0  -80  104  125  124
   -4  127    0    0  -50
    5
sh-5.2$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-2-5 00:02:27 From FishC Mobile | 显示全部楼层
人造人 发表于 2024-2-4 23:32
哪变了?

我那样写的话变了,照你这样改了之后不会变
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-5 00:15:27 | 显示全部楼层
孤不冷cing 发表于 2024-2-5 00:02
我那样写的话变了,照你这样改了之后不会变

因为你的变量在使用之前没有初始化么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-2-5 11:23:17 From FishC Mobile | 显示全部楼层
人造人 发表于 2024-2-5 00:15
因为你的变量在使用之前没有初始化么

把n初始化 和 用scanf把数字录入到n的内存地址,两者有什么区别吗
在n被录入值修改后,变长数组的维度还是n被scanf修改前那个没有意义的随机数吗
是变长数组所占内存太大,导致了什么奇怪问题,把scanf修改的n又给挤掉了?
我没明白
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-5 13:55:52 | 显示全部楼层
孤不冷cing 发表于 2024-2-5 11:23
把n初始化 和 用scanf把数字录入到n的内存地址,两者有什么区别吗
在n被录入值修改后,变长数组的维度还 ...

变长数组的元素个数,只在执行这条语句的时候决定
char magic_square[n][n];
后面不管你如何改变n的值,都不会改变数组的大小

如果你后面改变了n的值,这导致了数组的元素个数也发生了变化,这不是很奇怪吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-2-5 15:33:49 From FishC Mobile | 显示全部楼层
人造人 发表于 2024-2-5 13:55
变长数组的元素个数,只在执行这条语句的时候决定
char magic_square[n][n];
后面不管你如何改变n的值 ...

OK
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 22:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表