(另一个)关于C循环和数据结构的问题
我有一个程序(其代码位于底部),它可以按照我想要的方式生成数字列表。该程序按原样运行良好,并且完全符合我的要求。我只是不喜欢我的写作方式。如果我改变一件事,它会返回“分段错误”,我也会在底部说。代码如下:
#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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为您忘记从
dat
的数组索引中减去 1,如下所示:这会导致段错误的原因是因为您循环直到
i <= nrow
,这将在最终循环迭代中超出dat
的范围。I think you forgot to subtract 1 from the array index of
dat
, like this:The reason why this causes a segfault is because you're looping until
i <= nrow
, which will go out of the bounds ofdat
on the final loop iteration.我认为除了雷尔金(正确地)指出的内容之外,您的代码中还有其他内容。
如果我的计算是正确的,
nrow == 81*(500-1)
(== 40419) 所以它是dat[40419]
在以下爆炸性算法上:
每个内部
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.
If my calculations are right,
nrow == 81*(500-1)
(== 40419) so it isdat[40419]
On the following explosive algorithm :
Every internal
for
loop increasesk
by 250 (so both increase it by 500 for everywhile
loop), whilek < 40419
. This means there is a point wherek
reaches 40001, the condition is satisfied and the loop goes one more. At this moment, on the secondfor
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.