简体   繁体   English

如何从2个输入文件中按升序将整数排序到新文件中?

[英]How do you sort integers into a new file in ascending order from 2 input files?

I'm trying to create a program which takes integer input from two files. 我正在尝试创建一个从两个文件中获取整数输入的程序。 I have two files with integers in ascending order, and the output file should merge those two into one file, kept in ascending order. 我有两个整数升序的文件,输出文件应该将这两个文件合并为一个文件,保持升序。

while((fscanf(inputFile1, "%d", &temp1) == 1) && (fscanf(inputFile2, "%d", &temp2) == 1))
{
  printf("temp1: %d\n", temp1);
  printf("temp2: %d\n", temp2);

  if (temp1 > temp2)
  {
     fprintf(outputFile, "%d\n", temp2);
     fprintf(outputFile, "%d\n", temp1);
  }
  else if (temp1 < temp2)
  {
     fprintf(outputFile, "%d\n", temp1);
     fprintf(outputFile, "%d\n", temp2);
  }
  else if (temp1 == temp2)
  {
     fprintf(outputFile, "%d\n", temp1);
     fprintf(outputFile, "%d\n", temp2);
  }
}

File 1    File 2
5         1
10        43
30        55
50        98
345       500

Output
1
5
10
43
30
55
50
98
345 
500

It's almost complete but there's an issue when one of the files has a number smaller/larger than a previous line in another file (like 30 > 43). 它几乎完成但是当其中一个文件的数字小于/大于另一个文件中的前一行(如30> 43)时会出现问题。 How can I fix this issue, so that the output is completely sorted? 如何解决此问题,以便输出完全排序?

You're reading one number from each file, which will fail when you would have to take two consecutive numbers from the same file. 您正在从每个文件中读取一个数字,当您必须从同一个文件中取两个连续的数字时,这个数字将会失败。

Instead, you should read numbers from file #1 and #2, and keep reading from the file which number is smaller until it's greater that the last number read from the other file. 相反,您应该从文件#1和#2读取数字,并继续读取文件中哪个数字较小,直到它大于从另一个文件读取的最后一个数字。

Your code has two issues - first, you assume that both files have the same number of entries, and second, you assume that numbers in the output would come in pairs first file/second file or vice versa. 您的代码有两个问题 - 首先,您假设两个文件具有相同数量的条目,其次,您假设输出中的数字将成对出现第一个文件/第二个文件,反之亦然。

You can fix this by reading one number at a time. 您可以通过一次读取一个数字来解决此问题。 Set a flag to indicate that you have a number from one side or from the other side, read the number from the side that is missing, and write one number into the output. 设置一个标志以指示您从一侧或另一侧有一个数字,从缺少的一侧读取数字,并在输出中写入一个数字。 Then mark the side from which you took the number for next read, and repeat the process. 然后标记您从中获取下次读取的数字的一侧,并重复该过程。

The main loop would look like this: 主循环看起来像这样:

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

Consider a practical case, where you had two columns of numbers in ascending order, and you wanted to read them out in ascending order. 考虑一个实际情况,你有两列数字按升序排列,你想按升序读出它们。 You would most likely keep one finger on each column, pointing to the next value in that column. 您最有可能在每列上保留一根手指,指向该列中的下一个值。 You choose the smaller, read it aloud, and move that finger down. 你选择较小的,大声朗读,并将手指向下移动。 This is the algorithm your code should implement. 这是您的代码应该实现的算法。

Let's look at the algorithm in pseudocode. 让我们看看伪代码中的算法。

First, we need to read the first value from both files. 首先,我们需要从两个文件中读取第一个值。 It may happen that one of the source files is empty, in which case we need to just output the contents of the other file: 可能会发生其中一个源文件为空,在这种情况下我们只需要输出另一个文件的内容:

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

That takes care of the initial condition, and now we have value1 from the first file, and value2 from the second file, and can enter into our main loop. 这将处理初始条件,现在我们从第一个文件中获取value1 ,从第二个文件中获取value2 ,并且可以进入我们的主循环。

On each iteration, we output the smaller value, and read the next number from that source file -- just as if we moved our finger down in the column we read aloud. 在每次迭代中,我们输出较小的值,并从该源文件中读取下一个数字 - 就像我们在我们朗读的列中向下移动手指一样。

Again, if we run out of data, we output the contents of the other file. 同样,如果我们用完了数据,我们输出另一个文件的内容。

Note that I've chosen a logic where all equal values are output from the first file first (ie, if both columns have an equal value, we read (all the equal values in) the first column first, and from the second column afterwards). 请注意,我选择了一个逻辑,其中所有相等的值首先从第一个文件输出(即,如果两个列具有相等的值,我们首先读取(所有相等的值)第一个列,然后从第二个列读取) )。 This should make this a 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

In C, this should be very straightforward to implement as a function; 在C中,这应该非常简单地作为一个函数实现; perhaps void interleave_ints(FILE *in1, FILE *in2, FILE *out) . 也许void interleave_ints(FILE *in1, FILE *in2, FILE *out)

Note that all the loops above are infinite (ie, while (1) { ... } or do { ... } while(1); or for (;;) { ... } ), and in the function, you can use return; 请注意,上面的所有循环都是无限的(即, while (1) { ... }do { ... } while(1);for (;;) { ... } ),并且在函数中,你可以用return; to return back to the caller. 返回给来电者。

You need not read from both of them everytime. 你不需要每次都阅读它们。 If the current values in one of the files is say 3,6,8... and the other is 7,9,10... . 如果其中一个文件中的当前值是3,6,8...而另一个是7,9,10... You need to skip reading next value from 2nd file as you will lose 7 . 您需要跳过从第二个文件中读取下一个值,因为您将丢失7 You need to run the loop to read all values smaller than 7 in 1st file and only then, read the next value from the 2nd file. 您需要运行循环以在第一个文件中读取小于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;
    }
}

Small, tricky solution. 小巧,棘手的解决方案。 Tell me, if you are interested, I will add comments. 告诉我,如果你有兴趣,我会添加评论。

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

Input: 输入:

file_1.txt file_1.txt

5
10
30
50
345

file_2.txt file_2.txt

1
43
55
98
500

Output: 输出:

1
5
10
30
43
50
55
98
345
500

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM