我试图创建一个从两个文件中获取整数输入的程序。我有两个整数升序的文件,输出文件应该将这两个文件合并为一个文件,保持升序。
{{1}}
它几乎已经完成但是当其中一个文件的数字小于/大于另一个文件中的前一行(例如30> 43)时会出现问题。如何解决此问题,以便输出完全排序?
答案 0 :(得分:3)
您正在从每个文件中读取一个数字,当您必须从同一个文件中取两个连续数字时,这个数字会失败。
相反,您应该从文件#1和#2中读取数字,并继续从文件中读取哪个数字较小,直到它比从另一个文件读取的最后一个数字大。
答案 1 :(得分:3)
您的代码有两个问题 - 首先,您假设两个文件具有相同数量的条目,其次,您假设输出中的数字将成对出现在第一个文件/第二个文件中,反之亦然。
您可以通过一次读取一个数字来解决此问题。设置一个标志以指示您从一侧或另一侧有一个数字,从缺少的一侧读取数字,并在输出中写入一个数字。然后标记您从中获取下一个读数的一侧,并重复该过程。
主循环看起来像这样:
int have1 = 0, have2 = 0;
for ( ; ; ) {
int temp1, temp2;
have1 = have1 || 1==fscanf(inputFile1, "%d", &temp1);
have2 = have2 || 1==fscanf(inputFile2, "%d", &temp2);
// We ran out of numbers in both files - exit
if (!have1 && !have2) {
break;
}
if (!have2 || (have1 && temp1 < temp2)) {
fprintf(outputFile, "%d\n", temp1);
have1 = 0;
} else if (!have1 || (have2 && temp2 < temp1)) {
fprintf(outputFile, "%d\n", temp2);
have2 = 0;
} else {
fprintf(outputFile, "%d\n", temp1);
have1 = 0;
fprintf(outputFile, "%d\n", temp2);
have2 = 0;
}
}
答案 2 :(得分:3)
考虑一个实际案例,你有两列数字按升序排列,你想按升序读出它们。您最有可能在每列上保留一根手指,指向该列中的下一个值。你选择较小的,大声朗读,并将手指向下移动。这是您的代码应该实现的算法。
让我们看看伪代码中的算法。
首先,我们需要从两个文件中读取第一个值。可能会发生其中一个源文件为空,在这种情况下我们只需要输出另一个文件的内容:
Read value1 from the first file.
If we cannot, then:
Loop:
Read value2 from the second file.
If we cannot: Return.
Output value2
End loop
End if
Read value2 from the second file.
If we cannot, then:
Loop:
Output value1
Read value1 from the first file.
If we cannot: Return.
End loop
End if
它负责初始条件,现在我们从第一个文件中获得value1
,从第二个文件中获得value2
,并且可以进入我们的主循环。
在每次迭代中,我们输出较小的值,并从该源文件中读取下一个数字 - 就像我们在我们朗读的列中向下移动手指一样。
同样,如果我们用完了数据,我们会输出另一个文件的内容。
请注意,我选择了一个逻辑,其中所有相等的值首先从第一个文件输出(即,如果两个列具有相等的值,我们首先读取(所有相等的值)第一列,并从之后的第二栏)。这应该是stable sort。
Loop:
If value1 <= value2, then:
Output value1
Read value1 from the first file.
If we cannot, then:
Loop:
Output value2
Read value2 from the second file.
If we cannot: Return.
End loop
End if
Else:
Output value2
Read value2 from the second file.
If we cannot, then:
Loop:
Output value1
Read value1 from the second file.
If we cannot: Return.
End loop
End if
End if
End loop
在C中,这应该非常简单地作为一个函数实现;也许void interleave_ints(FILE *in1, FILE *in2, FILE *out)
。
请注意,上面的所有循环都是无限的(即while (1) { ... }
或do { ... } while(1);
或for (;;) { ... }
),在函数中,您可以使用return;
返回来电者。
答案 3 :(得分:1)
您无需每次都阅读它们。如果其中一个文件中的当前值为3,6,8...
,另一个为7,9,10...
。您需要跳过从第二个文件中读取下一个值,因为您将丢失7
。
您需要运行循环以读取第一个文件中小于7的所有值,然后才读取第二个文件中的下一个值。
int last = 1; // Initializing last to 1 so that it is read in the 1st cycle
int in1, in2, temp1, temp2;
fscanf(inputFile2, "%d", &in2); //Initializing in2 for valid 1st comparison
while(1)
{
if(last == 1 && fscanf(inputFile1, "%d", &temp1) == 1){
in1 = temp1;
} else last = 0;
if(last == 2 && fscanf(inputFile2, "%d", &temp2) == 1){
in2 = temp2;
} else last = 0;
if( last == 0 ) break; // Will be 0 only if both reads fail
printf("temp1: %d\n", in1);
printf("temp2: %d\n", in2);
if (in1 < in2)
{
fprintf(outputFile, "%d\n", in1);
last = 1;
}
else
{
fprintf(outputFile, "%d\n", in2);
last = 2;
}
}
答案 4 :(得分:0)
小巧,棘手的解决方案。告诉我,如果你有兴趣,我会添加评论。
#include <stdio.h>
int main() {
FILE *file_1 = fopen("file_1.txt", "r");
FILE *file_2 = fopen("file_2.txt", "r");
int num;
int tmp;
int max = 0;
int i = 0;
FILE *stream[2] = {file_1, file_2};
while(fscanf(stream[i], "%d", &num) == 1) {
if(! max) {
max = num;
i = i ^ 1;
continue;
}
if(max < num) {
i = i ^ 1;
tmp = max;
max = num;
num = tmp;
}
printf("%d\n", num);
}
printf("%d\n", max);
fclose(file_1);
fclose(file_2);
return 0;
}
<强>输入:强>
file_1.txt
5
10
30
50
345
file_2.txt
1
43
55
98
500
<强>输出:强>
1
5
10
30
43
50
55
98
345
500