用C实现一个简单的对拍器——致每个曾经为求AC披星戴月的程序员们
大一新生,首次创作,虚心受教。
实现思路:
一、需要一个输入文件(input.txt),两个对拍程序(main1.exe,main2.exe)
二、将标准输入重定向为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,就会发生溢出;有些情况可能行号不太准确。
六、小感
第一次写文章,排版各方面不太熟悉,希望各位谅解。
源代码https://files.cnblogs.com/Bright-Star/main.zip