(另一个)关于C循环和数据结构的问题

发布于 2024-10-14 03:33:56 字数 2495 浏览 1 评论 0原文

我有一个程序(其代码位于底部),它可以按照我想要的方式生成数字列表。该程序按原样运行良好,并且完全符合我的要求。我只是不喜欢我的写作方式。如果我改变一件事,它会返回“分段错误”,我也会在底部说。代码如下:

#include "stdio.h"
#include "stdlib.h"
#define NCH 81

// Generate swap-mode data for bonds for input.conf file

int main() 
{
    int i,j,k;
    int **dat2, *dat;
    //double *dat;

    int ns = 500;

    int nrow = NCH*(ns-1);

    dat = (int*) calloc(nrow, sizeof(int));
    dat2 = (int**) calloc(nrow,sizeof(int*));

    for (i=0; i<nrow; i++) {
        dat2[i] = (int*) calloc(2, sizeof(int));
        for (j=0; j<2; j++)
            dat2[i][j] = 0;
    }

    // Generates the bonds
    k=2;
    for (i=0; i<nrow; i++) {
        k--;
        for (j=0; j<2; j++) {
            dat2[i][j] = k++;
            if ( ((k%501) == 0) ) { 
                k--;
                dat2[i][j] = k++;
                k++;
            }
        }
    }

    FILE *inp2;
    inp2 = fopen("bonds.out", "w");

    for (i=1; i<=nrow; i++)
        fprintf(inp2, "%d %d\n", dat2[i-1][0], dat2[i-1][1]);

    fclose(inp2);

    // Generates the bond ID in the pattern 1 2 3 3 2 1 ... (appropriate for Bond swap!)
    k=1;
    while ( k < nrow ) {
        for (j=0; j<250; j++) {
            dat[k] = (j+1);
            k++;
        }
        for (j=250; j>0; j--) {
            dat[k] = j;
            k++;
        }
    }

    // Scans bonds.out (because just reporting dat2[][] returns segmentation error, not sure why.
    // scans the bonds.out file and stores both values into dm1 and dm2, then reports into 'results.out' file
    int dm1, dm2;

    FILE *inp;
    inp = fopen("input.out", "w");
    inp2 = fopen("bonds.out", "r");

    for (i=1; i<=nrow; i++) {
        fscanf(inp2, "%d %d", &dm1, &dm2);
        fprintf(inp, "%d  %d  %d  %d\n", i, dat[i], dm1, dm2);
    }



    printf("\nDone. All data has been written to \"input.out\"\n");

    fclose(inp2);
    fclose(inp);

    return 0;
}

现在,我不喜欢这样的事实:它首先将 dat2[][] 写入文件,然后扫描该文件以查找值。相反,为什么我不能将 dat2[][] 合并到写入 "results.out" 文件的主循环中?如果我这样做,就会出现分段错误。为了澄清起见,我的意思是更改代码中的这些行:

for (i=1; i<=nrow; i++) {
    fscanf(inp2, "%d %d", &dm1, &dm2);
    fprintf(inp, "%d  %d  %d  %d\n", i, dat[i], dm1, dm2);
}

对于这些:

for (i=1; i<=nrow; i++) {
    fprintf(inp, "%d  %d  %d  %d\n", i, dat[i], dat2[i-1][0], dat2[i-1][1]);
}

我希望得到解释,因为我对 C 仍然很陌生。

非常感谢! 阿米特

I have a program (who's code is available at the bottom) which generates a list of numbers the way that I want it to. The program works fine as is and does exactly what I want. I'm just not a fan of the way I wrote it. It returns "Segmentation fault" if I change one thing, which I'll say at the bottom as well. Here's the code:

#include "stdio.h"
#include "stdlib.h"
#define NCH 81

// Generate swap-mode data for bonds for input.conf file

int main() 
{
    int i,j,k;
    int **dat2, *dat;
    //double *dat;

    int ns = 500;

    int nrow = NCH*(ns-1);

    dat = (int*) calloc(nrow, sizeof(int));
    dat2 = (int**) calloc(nrow,sizeof(int*));

    for (i=0; i<nrow; i++) {
        dat2[i] = (int*) calloc(2, sizeof(int));
        for (j=0; j<2; j++)
            dat2[i][j] = 0;
    }

    // Generates the bonds
    k=2;
    for (i=0; i<nrow; i++) {
        k--;
        for (j=0; j<2; j++) {
            dat2[i][j] = k++;
            if ( ((k%501) == 0) ) { 
                k--;
                dat2[i][j] = k++;
                k++;
            }
        }
    }

    FILE *inp2;
    inp2 = fopen("bonds.out", "w");

    for (i=1; i<=nrow; i++)
        fprintf(inp2, "%d %d\n", dat2[i-1][0], dat2[i-1][1]);

    fclose(inp2);

    // Generates the bond ID in the pattern 1 2 3 3 2 1 ... (appropriate for Bond swap!)
    k=1;
    while ( k < nrow ) {
        for (j=0; j<250; j++) {
            dat[k] = (j+1);
            k++;
        }
        for (j=250; j>0; j--) {
            dat[k] = j;
            k++;
        }
    }

    // Scans bonds.out (because just reporting dat2[][] returns segmentation error, not sure why.
    // scans the bonds.out file and stores both values into dm1 and dm2, then reports into 'results.out' file
    int dm1, dm2;

    FILE *inp;
    inp = fopen("input.out", "w");
    inp2 = fopen("bonds.out", "r");

    for (i=1; i<=nrow; i++) {
        fscanf(inp2, "%d %d", &dm1, &dm2);
        fprintf(inp, "%d  %d  %d  %d\n", i, dat[i], dm1, dm2);
    }



    printf("\nDone. All data has been written to \"input.out\"\n");

    fclose(inp2);
    fclose(inp);

    return 0;
}

Now, I don't like the fact that it's first writing dat2[][] to a file and then scanning that file for the values. Why, instead, can't I incorporate dat2[][] in the main loop that writes the "results.out" file? If I do so, I get Segmentation fault. For clarification, I mean changing these lines in the code:

for (i=1; i<=nrow; i++) {
    fscanf(inp2, "%d %d", &dm1, &dm2);
    fprintf(inp, "%d  %d  %d  %d\n", i, dat[i], dm1, dm2);
}

To these:

for (i=1; i<=nrow; i++) {
    fprintf(inp, "%d  %d  %d  %d\n", i, dat[i], dat2[i-1][0], dat2[i-1][1]);
}

I'd love an explanation as I'm still very new to C.

Thanks a lot!
Amit

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不如归去 2024-10-21 03:33:56

我认为您忘记从 dat 的数组索引中减去 1,如下所示:

for (i=1; i<=nrow; i++) {
  fscanf(inp2, "%d %d", &dm1, &dm2);
  fprintf(inp, "%d  %d  %d  %d\n", i, dat[i-1], dm1, dm2);
}

这会导致段错误的原因是因为您循环直到 i <= nrow ,这将在最终循环迭代中超出 dat 的范围。

I think you forgot to subtract 1 from the array index of dat, like this:

for (i=1; i<=nrow; i++) {
  fscanf(inp2, "%d %d", &dm1, &dm2);
  fprintf(inp, "%d  %d  %d  %d\n", i, dat[i-1], dm1, dm2);
}

The reason why this causes a segfault is because you're looping until i <= nrow, which will go out of the bounds of dat on the final loop iteration.

小镇女孩 2024-10-21 03:33:56

我认为除了雷尔金(正确地)指出的内容之外,您的代码中还有其他内容。

int nrow = NCH*(ns-1);
dat = (int*) calloc(nrow, sizeof(int));

如果我的计算是正确的,nrow == 81*(500-1) (== 40419) 所以它是dat[40419]

在以下爆炸性算法上:

k=1;
while ( k < nrow ) {
    for (j=0; j<250; j++) {
        dat[k] = (j+1);
        k++;
    }
    for (j=250; j>0; j--) {
        dat[k] = j;
        k++;
    }
}

每个内部for 循环将 k 增加 250(因此每个 while 循环都将其增加 500),而 k k 40419。这意味着在 k 达到 40001 时,条件满足并且循环会再进行一次。此时,在第二个 for 循环中,您超过了 40419 并且在内存中写入了不应该的内容。请看一下并再次检查我的数学。

一旦进入 while 循环,并且条件成立,这并不意味着循环将自动退出。

I think there is something else on your code too besides what Relkin (correctly) pointed out.

int nrow = NCH*(ns-1);
dat = (int*) calloc(nrow, sizeof(int));

If my calculations are right, nrow == 81*(500-1) (== 40419) so it is dat[40419]

On the following explosive algorithm :

k=1;
while ( k < nrow ) {
    for (j=0; j<250; j++) {
        dat[k] = (j+1);
        k++;
    }
    for (j=250; j>0; j--) {
        dat[k] = j;
        k++;
    }
}

Every internal for loop increases k by 250 (so both increase it by 500 for every while loop), while k < 40419. This means there is a point where k reaches 40001, the condition is satisfied and the loop goes one more. At this moment, on the second for loop you exceed 40419 and write in memory you shouldn't. Take a look at that and check my maths again plz.

Once you are inside the while loop, and the condition falsifies, this does not mean the loop will automatically exit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文