在c中调用函数时出现分段错误

Segmentation fault when calling a function in c

代码是以螺旋方式打印给定的数字,例如,

1 2 3
8 9 4
7 6 5

我在调用函数 godown() 时遇到段错误。

#include<stdio.h>

int o[100][100],c[100][100],p=0,q=0,m=0,n=0,a,i,j,r,d,l,u;
void goright(int r);
void goleft(int l);
void goup(int u);
void godown(int d);

int main()
{
    int r;
    printf("\nenter the no. of rows\n");
    scanf("%d",&a);
    printf("\nenter the elements u want to print in a spiral fashion\n");
    for(i=0;i<a;i++)
    {
        for(j=0;j<a;j++)
        {
            scanf("%d",&o[i][j]);
            getchar();
        }
    }
    for(i=0;i<a;i++)
    {
        for(j=0;j<a;j++)
        {
            printf("%d ",o[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    r=a;
    goright(r);
    for(i=0;i<a;i++)
    {
        for(j=0;j<a;j++)
        {
            printf("%d ",c[i][j]);
        }
        printf("\n");
    }
    return 0;
}

void goright(int r)
{
    for(i=0;i<r;i++)
    {
        c[m][n]=o[p][q];
        q++;
        n++;
    }
    if(q>a)
    {
        q=0;
        p++;
    }
    else
    {
        q--;
        p++;
    }
    n--;
    m++;
    d=r-1;
    godown(d);
}

void godown(int d)
{
    for(i=0;i<d;i++)
    {
        c[m][n]=o[p][q];
        q++;
        m++;
    }
    if(q>a)
    {
        q=0;
        p++;
    }
    else
    {
        q--;
        p++;
    }
    m--;
    n--;
    l=d;
    goleft(l);
}

void goleft(int l)
{
    for(i=0;i<l;i++)
    {
        c[m][n]=o[p][q];
        q++;
        n--;
    }
    if(q>a)
    {
        q=0;
        p++;
    }
    else
    {
        q--;
        p++;
    }
    n++;
    m--;
    u=l-1;
    goup(u);
}

void goup(int u)
{
    for(i=0;i<u;i++)
    {
        c[m][n]=o[p][q];
        q++;
        m--;
    }
    if(q>a)
    {
        q=0;
        p++;
    }
    else
    {
        q--;
        p++;
    }
    m++;
    n++;
    r=u;
    goright(r);
}

我不明白为什么会出现段错误。调试时,goright() 函数似乎正常工作,因为我尝试打印螺旋形数组 'c' 的元素。我试过更改变量的名称和所有的名称,但似乎没有任何帮助。

您的递归代码大致如下所示:

void goright(int r)
{
    ...
    godown(d);
}

void godown(int d)
{
    ...
    goleft(l);
}

void goleft(int l)
{
    ...
    goup(u);
}

void goup(int u)
{
    ...
    goright(r);
}

我省略的内容 (...) 不包含任何 return 语句,因此一旦开始,此设置将永远递归。您可以通过在第一行中打印 goxxx 函数的参数来验证这一点:它们将随着幅度的增加而变为负值。

所以你需要一个 rcursion 的终止标准。您的 go 函数可能如下所示:

void goright(int r)
{
    if (r > 0) {
        ...
        godown(d);
    }
}

或者像这样:

void goright(int r)
{
    if (r == 0) return;

    ...
    godown(d);
}

您的代码仍然存在问题,主要是因为您将要插入的值存储在二维数组中。将这些存储在大小为 a*a 的线性数组中会更容易 - 您只需要跟踪一个以可预测方式移动的索引。

而且,请不要将所有变量都定义为全局变量。他们中的许多人不需要,特别是 goxxx 函数参数的同名。像 ij 这样的迭代器应该是本地的。

您仍然可以使用递归方法。这是一个例子。它只是用从 1 开始向上计数的数字填充螺旋线。请注意,打印循环不会走完整个路,它们会停在 1 处,因此将像这样打印一个正方形:

r r r d
u     d
u     d
l l l d

这意味着您不必在走得太远后调整变量 mn。仅当您转完一圈时才需要进行此调整,即在您再次开始右转之后。这种情况下还有一个额外的检查来打印奇数边长的最后一个中心值。

#include<stdio.h>

int c[100][100], p=0, m=0, n=0;

void goright(int r);
void goleft(int l);
void goup(int u);
void godown(int d);

int main()
{
    int a;

    printf("\nenter the no. of rows\n");
    scanf("%d",&a);

    goright(a);

    for(int i = 0; i < a; i++) {
        for(int j = 0; j < a; j++) {
            printf("%3d",c[i][j]);
        }
        printf("\n");
    }

    return 0;
}

void goright(int x)
{
    if (x == 1) c[m][n] = ++p;
    if (x <= 1) return;

    for(int i = 1; i < x; i++) {
        c[m][n++] = ++p;
    }

    godown(x);
}

void godown(int x)
{
    for(int i = 1; i < x; i++) {
        c[m++][n] = ++p;
    }

    goleft(x);
}

void goleft(int x)
{
    for(int i = 1; i < x; i++) {
        c[m][n--] = ++p;
    }

    goup(x);
}

void goup(int x)
{
    for(int i = 1; i < x; i++) {
        c[m--][n] = ++p;
    }

    m++;
    n++;

    goright(x - 2);
}