首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言實作自動對拍器:競程必備的輸出比對工具

     編輯:關於C語言

核心思路

  1. 準備輸入檔 input.txt、兩個待測程式 main1、main2
  2. 將標準輸入重導向至 input.txt,標準輸出分別重導向至 output1.txt、output2.txt
  3. 逐行比對兩輸出檔,標示差異行號與內容

關鍵系統呼叫

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>

int main() {
    int fd_in = open("stdin.txt", O_RDONLY);
    int fd_out1 = open("stdout1.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
    int fd_out2 = open("stdout2.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
    
    int saved_in = dup(STDIN_FILENO);
    int saved_out = dup(STDOUT_FILENO);
    
    // 執行 main1
    dup2(fd_in, STDIN_FILENO);
    dup2(fd_out1, STDOUT_FILENO);
    system("./main1");
    
    // 執行 main2
    dup2(fd_in, STDIN_FILENO);  // 必須重新導向,因 stdin 可能被消耗
    dup2(fd_out2, STDOUT_FILENO);
    system("./main2");
    
    // 恢復標準輸出
    dup2(saved_out, STDOUT_FILENO);
    
    // 比對輸出檔...
    return 0;
}

輸出比對邏輯

char buf1[4096], buf2[4096];
int line = 1;
lseek(fd_out1, 0, SEEK_SET);
lseek(fd_out2, 0, SEEK_SET);

while (read(fd_out1, buf1, sizeof(buf1)) > 0 && read(fd_out2, buf2, sizeof(buf2)) > 0) {
    for (int i = 0; i < n; i++) {
        if (buf1[i] != buf2[i]) {
            printf("第 %d 行差異:\n", line);
            printf("輸出1: %.*s\n", i, buf1);
            printf("輸出2: %.*s\n", i, buf2);
            goto diff_found;
        }
        if (buf1[i] == '\n') line++;
    }
}
printf("無差異\n");
diff_found: ;

關鍵坑點:緩衝區混用

  • system() 使用標準 I/O(帶緩衝)
  • read()/write() 為無緩衝系統呼叫
  • 重導向後,檔案位置可能異步變化 → 需 lseek() 歸零、重新 open() 輸入檔

已知限制

  • 單行超過 1024 位元組會溢位
  • 行號統計在某些情況下不準
  • Windows 下建議改用批次檔(.bat)更簡單

批次檔替代方案(Windows)

@echo off
main1.exe < input.txt > out1.txt
main2.exe < input.txt > out2.txt
fc out1.txt out2.txt

對拍器是競程提升 AC 率的利器,理解其原理也能加深對 Unix I/O 模型的掌握。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved