c-使用带数组的嵌套循环的分段故障11



我不确定为什么会收到这个错误。我想知道这可能是因为我的终端无法读取与该程序一起运行的txt文件。让我知道这是否可能是该信息的原因。

我主要是在找语法错误。我的文件只包含一大堆数字,我应该从第三个值开始工作(前两个有另一个用途(

#include <stdlib.h> 
#define N 1000000
int main(void)
{
int n;  /* The number of lengths */
int x; /* The target length */
int lengths[N]; /* The array of available lengths */
int i, j;
int whichfile=1;
FILE *fp;
scanf("%d", &whichfile);
switch (whichfile) {
case 1:
fp = fopen("testcase_small_sorted.txt", "r");
break;
case 2:
fp = fopen("testcase_large_sorted.txt", "r");
break;
case 3:
fp = fopen("testcase_small_nomatch_sorted.txt","r");
break;
case 4:
fp = fopen("hidden_small_sorted.txt","r");
break;
case 5:
fp = fopen("hidden_large_sorted.txt","r");
break;
}
fscanf(fp, "%d", &x);
fscanf(fp, "%d", &n);
for (i=0;i<n;i++)
fscanf(fp, "%d", &lengths[i]);

fclose(fp);
/* Now all the input data has been read in
search for the required pair of lengths... */
x = lengths[0];
n = lengths[1];
for(i = 2; i < n; i++)
{
for(j = 2; i < n; j++)
{
if(lengths[i] + lengths[j] == x)
{
printf("Found: %d + %d == %dn", lengths[i], lengths[j], x);
}
}
}
return 0;
} ```

我主要是在查找语法错误

语法错误只是开始。C不会帮你检查任何东西。您必须检查文件是否打开,输入扫描是否有效,值是否在数组边界内。如果你不这样做,那就是你会犯segfault的原因。

对于文件,通常的模式是尝试打开文件,检查其返回值,然后处理错误。CCD_ 1在出错时返回CCD_ 2并设置CCD_。CCD_ 4是全局的;如果"找不到文件";,但这是一个数字。strerror可以方便地将其转换为错误消息。最后,fprintfprintf类似,但可以打印到stdout以外的内容。在这种情况下,stderrfopen0和stderr通常都出现在屏幕上,但它们可以分开。

FILE *fp = fopen(path, mode);
if( fp == NULL ) {
// This will print something like "Could not open testcase_small_sorted.txt: No such file or directory"
fprintf(stderr, "Could not open file %s: %s", path, strerror(errno));
exit(1);
}

但现在我们需要复制五次,因为代码重复fopen。与其每次打开文件,不如选择一个文件名?由于每个文件名都有一个数字,如果它们只是在一个数组中呢?

const char *files[] = {
NULL, // 0 is not used
"testcase_small_sorted.txt",
"testcase_large_sorted.txt",
"testcase_small_nomatch_sorted.txt",
"hidden_small_sorted.txt",
"hidden_large_sorted.txt"
};
const char *path = files[whichfile];

如果他们输入了不是数字的东西怎么办?或者如果数字超出范围怎么办?这些也需要检查。scanf将返回匹配的项目数。我们期望1。如果我们得到了其他东西,那就没用了。

// Check that we read an integer.
if( scanf("%d", &whichfile) != 1 ) {
fprintf(stderr, "Please enter 1-5.n");
exit(1);
}
// Check that it's in range.
if( (whichfile < 1) || (5 < whichfile) ) {
fprintf(stderr, "Please enter 1-5.n");
exit(1);
}

请注意,scanf有很多问题,一旦您学习了fgetssscanf之类的东西,就应该立即放弃。


int lengths[1000000]为4到8兆字节(100万个整数,每个整数4个或可能为8个字节(,可能会导致同名堆栈溢出。你的算法是O(n^2(,这意味着如果真的有1000000个项目,那么需要1000000000000次迭代才能找到所有的配对,你的课程可能会在程序完成之前完成。

(一个改进算法的小提示:如果数字是排序的,并且你正在寻找其中两个数字来求和X,你需要检查每个数字吗?(

我想你应该相信文件中的n可以读取多少。通常你没有这个,它是一个拐杖,让你在不使用动态记忆的情况下阅读输入(稍后会教你(。即使您拥有它,在生产代码中也不会信任它;如果它说谎,你就会走出你的数组边界。但对于这个练习来说,这没关系。

// Read the first two lines, the sum and the number of remaining lines.
// Note that `fscanf` can also fail and needs to be error checked.
// I'll leave that as an exercise.
fscanf(fp, "%d", &x);
fscanf(fp, "%d", &n);
// Use `n` to allocate just enough space on the stack.
int lengths[n];
// Read the rest.
// Use braces, even for one line.
// They avoid a very silly and hard to debug mistake.
for (i=0;i<n;i++) {
fscanf(fp, "%d", &lengths[i]);
}
fclose(fp);

不需要将x和n放入CCD_ 19中。它们不是要求和的,无论如何,你都可以从2开始循环,跳过它们。

固定后,循环可以从0开始。内部循环中存在错误,应检查NULL0而不是i < n

for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)  // <<--- j < n, not i < n.
{
if(lengths[i] + lengths[j] == x)
{
printf("Found: %d + %d == %dn", lengths[i], lengths[j], x);
}
}
}

最新更新