實現思路:
一、需要一個輸入文件(input.txt),兩個對拍程序(main1.txt,main2.txt)
二、將標准輸入重定向為input.txt。將標准輸出分別重定向為output1.txt,output2.txt。
三、對兩個輸出文件進行比較,輸出結果。
具體實現:
一、所需頭文件
1: #include <stdio.h>
2: #include <stdlib.h>
3: #include <sys/file.h>
4: #include <unistd.h>
5: #include <sys/types.h>
二、文件重定向並進行系統調用執行main1.exe main2.txt
1: int fdout1 = open("stdout1.txt", O_RDWR|O_TRUNC|O_CREAT, 0);
2: int fdout2 = open("stdout2.txt", O_RDWR|O_TRUNC|O_CREAT, 0);
//以每次打開文件清零和如不存在便創建就打開兩個輸出文件
3: int fdin = open("stdin.txt", O_RDWR, 0);
4: int tempin = dup(STDIN_FILENO);
5: int tempout = dup(STDOUT_FILENO), line = 1;
//對標准輸出輸入描述符表進行拷貝,防止系統清除其指向的文件表
6: char buf1[4096], buf2[4096];
7:
8: dup2(fdin, STDIN_FILENO);
9: dup2(fdout1, STDOUT_FILENO);
//重定向
10: if (system("main1.exe") == 127)
11: write(tempout, "NO EXE", 7);
12: fdin = open("stdin.txt", O_RDWR, 0);
13: dup2(fdin, STDIN_FILENO);
//可能有些同學要問了這裡問什麼要對標准輸入重定向兩次,具體解釋略長參見後文。
14: dup2(fdout2, STDOUT_FILENO);
15: if (system("main2.exe") == 127)
16: write(tempout, "NO EXE", 7);
17: dup2(tempout, STDOUT_FILENO);
//恢復標准輸出
18: lseek(fdout1, 0, SEEK_SET);
19: lseek(fdout2, 0, SEEK_SET);
//重置文件讀取位置,具體解釋同十三行後。
三、對輸出文件的處理
復制代碼
1 for(;;)
2 {
3 int n;
4
5 if ((n = read(fdout1, buf1, 4096)) > 0 && read(fdout2, buf2, 4096) > 0)
6 {
7 int i, j = 0;
8 char buffer[1024];
9
10 for (i = 0; i < n; i++)
11 {
12 buffer[j++] = buf1[i];
13 if (buf1[i] == buf2[i])
14 {
15 if (buf1[i] == '\n')
16 {
17 j = 0;
18 line++;
19 }
20 }
21 else
22 {
23 printf("The difference in line %d between stdout1.txt and stdout2.txt\n", line);
24 buffer[j] = '\0';
25 printf("%s\n", buffer);
26 buffer[--j] = buf2[i];
27 printf("%s\n", buffer);
28 break;
29
30 }
31 }
32 if (i != n)
33 break;
34
35 }
36 else
37 {
38 printf("Can't find difference in this instance\n");
39 break;
40 }
41 }
復制代碼
四、對上文問題的解釋
以上的兩個問題都是由於帶緩沖區的文件讀寫和不帶緩沖區的文件讀寫混用產生的問題。標准輸出和標准輸入是帶緩沖區的,而read和write函數不帶緩沖區,所以進行重定向時,一旦將不帶緩沖區的用read打開的輸入文件stdin.txt重定向到標准輸入,則輸入文件中的內容會被輸入到緩沖區中,引起當前讀寫文件位置的變化,下次程序main2.exe引用的時候就會出現錯誤。同理在輸出文件操作的時候也要進行當前讀寫位置的復原。
五、警告
本程序bug多多,但基本能用,尤其是本人原先不熟悉windows下的一下編程,完成後才發現用windows寫一個bat程序要簡單的多,這就造成了在windows環境下以linux系統命令編寫的一個不倫不類的對拍程序。
由於程序寫的確實有點爛,主要目的原來是想救一救我被學校評測網站虐的慘不忍睹的C語言習題,順便熟悉一下進來學習的知識,所以想順便放上來分享一下,歡迎各位園友指出錯誤,一定虛心受教。
目前的bug有:如果一行超出1024b,就會發生溢出;有些情況可能行號不太准確。
六、小感
第一次寫文章,排版各方面不太熟悉,希望各位諒解。