(Другой) вопрос, касающийся циклов C и структур данных - PullRequest
0 голосов
/ 22 января 2011

У меня есть программа (чей код доступен внизу), которая генерирует список чисел так, как я хочу.Программа отлично работает как есть и делает именно то, что я хочу.Я просто не фанат того, как я это написал.Он возвращает «Ошибка сегментации», если я изменю одну вещь, о которой я также скажу внизу.Вот код:

#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.

Спасибо большое!Amit

Ответы [ 2 ]

4 голосов
/ 22 января 2011

Я думаю, что вы забыли вычесть 1 из индекса массива dat, например:

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);
}

Причина, по которой это вызывает segfault, заключается в том, что вы выполняете цикл до i <= nrow, чтовыйдет за пределы dat на последней итерации цикла.

2 голосов
/ 22 января 2011

Я думаю, что в вашем коде есть что-то еще, кроме того, на что указал Релкин (правильно).

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 (поэтому оба увеличивают его на 500 для каждого цикла while), в то время какk < 40419.Это означает, что есть точка, где k достигает 40001, условие выполняется, и цикл повторяется еще раз.В этот момент во втором цикле for вы превысили 40419 и не должны записывать в память.Взгляните на это и проверьте мою математику еще раз, плз.

Как только вы окажетесь внутри цикла while, и условие искажается, это не означает, что цикл автоматически завершится.

...