【问题标题】:(Another) question regarding C loops and data structures(另一个)关于 C 循环和数据结构的问题
【发布时间】:2011-01-22 03:43:37
【问题描述】:

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

#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 还是很陌生。

非常感谢! 阿米特

【问题讨论】:

  • 我的朋友有很多代码。
  • 我知道。我道歉,真的。我认为您不必阅读所有内容。也许只关注最后一点?

标签: c segmentation-fault


【解决方案1】:

我想你忘了从 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 &lt;= nrow,这将在最后一次循环迭代中超出dat 的范围。

【讨论】:

  • +1。在旁注@Amit:你做dat2[i][j] = 0;这不是真的必要,因为calloc()无论如何都会这样做。您也不会检查文件是否已成功打开
  • @Muggen:我知道 calloc 初始化,但它并不总是做得很好。 @Jacob:dat[] 从 1 到 nrow(包括),而不是从 0 到 nrow(不包括)
  • @Amit 真的吗?嗯,如果我在这里错了,请纠正我 - dat 的索引从 0 开始,到 nrow - 1 结束。
  • @Amit C 中的数组是零索引的。 dat 的索引范围从 0 到 nrow-1。
  • 呃...好吧,也许你们是对的。是的,我知道 C 中从零开始的索引。dat[] 不是这里的问题,它报告了正确的值...当我在其中包含 dat2[][] 时,它会失败。
【解决方案2】:

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

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 &lt; 40419。这意味着有一个点k 达到 40001,条件得到满足,循环再进行一次。此时,在第二个for 循环中,您超过了 40419 并且不应该写入内存。看看那个并再次检查我的数学。

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

【讨论】:

  • 啊,你确实是对的。 dat 应该是 40419,我认为你对 while 循环的事情肯定是正确的。我想知道为什么这有效......它肯定应该报告一个段错误。我将添加一个 if 语句来中断循环。也许这会解决所有问题
  • @Amit,这是Undefined Behaviour。任何事情都可能发生,要么工作,要么SegFault,要么正如其他人在SO Get your girlfriend pregnant中所说的那样
  • @Muggen:哈哈。我还没有听说过,但谢谢你让我的朋友。夜晚愉快而可笑:) +1
  • @Amit 为什么不尝试整合我的解决方案和@Muggen 的解决方案,看看哪一个真正解决了问题?
  • @Muggen:@#$@#4 仍然是段错误。算了,现在不是看这些东西的时候
猜你喜欢
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-28
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
相关资源
最近更新 更多