命令行環境下簡單實用的工具——重定向&管道

如果你對管道和重定向應用自如了,無需繼續往下看。本文雖然以windows上cmd命令行環境演示,但同樣適用於Unix/Linux等平臺。

/*************************************************************************
 * 作者:xusiwei1236([email protected])
 * 出處:http://blog.csdn.net/xusiwei1236
 * 聲明:轉載請註明出處,請勿用於商用.
 *       對本文所涉及的主題如有任何觀點、想法,歡迎交流(email或評論)
 ************************************************************************/

引言

關於管道和重定向,最初是在劉汝佳的《算法競賽入門經典》上看到的,也是從那時開始用gcc(MinGW) & notepad++(在此之前,Linux上用的是Eclipse+CDT,windows上是VC)。一般操作系統的命令行環境下都提供了管道和重定向工具,看了劉汝佳的書才知道用txt代替鍵盤作輸入、測試是多麼的方便!回想起每次點完GO之後一個數字一個數字的按鍵盤(而且筆記本鍵盤的數字鍵按起來沒有獨立鍵盤的數字區按起來那麼爽)還不時按錯的痛苦經歷,決定今日將這一強大的工具與大家分享。

從A+B說起

練過OJ的同學可能對此深有體會(沒練過沒有關係),你的程序可能要先讀10個輸入(或者更多),纔出結果;而你有很難保證這個程序一次編譯就是對的,每次修改後都要重新輸入這一堆數(還時不時的輸錯),實在讓人難以忍受!劉的書中說了兩種方法:

一.利用C標準庫提供的“重定向函數”freopen("input.txt",  "r", stdin);這種方法適合用在IDE上,添加一行代碼,再準備一個文本文件,你不用單獨打開一個cmd窗口,也能夠讓input.txt的文本帶你的所有鍵盤輸入。缺點就是你要在提交之時將這句代碼註釋掉(或者刪掉);相信不少同學在提交的時候因爲忘了註釋這句而WA的。(在有的IDE上找源代碼文件所在目錄也不是很方便。)
下面就以經典的A+B問題爲例。如下是A+B問題的一個解法,其中input.txt是事先已經準備好的測試數據,並且和這個代碼文件放在同一目錄下(VC上是這樣,有的IDE可能要和.exe放到同一目錄):

#include <stdio.h>

int main()
{
    int a,b;
    freopen("input.txt",  "r", stdin); 
    while( scanf("%d%d", &a, &b) == 2 )
    {
        printf( "%d\n", a+b );
    }
    return 0;
}

二.命令行環境下的————重定向。後面重點介紹
使用重定向的代碼不需要做任何手腳(假設保存爲D:\OJ\aplusb.c):

#include <stdio.h>

int main()
{
    int a,b;
    while( scanf("%d%d", &a, &b) == 2 )
    {
        printf( "%d\n", a+b );
    }
    return 0;
}

下面就以編譯、測試位於D:\OJ目錄下的aplusb.c的步驟爲例:

  1. (要使用重定向你必須)先打開一個cmd窗口,並讓cmd窗口的當前目錄爲D:\OJ。
    win7上只需打開D:\OJ文件夾,按住SHIFT鍵,在窗口的空白處右擊鼠標,點“在此處打開窗口”即可。


    win xp上稍顯麻煩,
    step1. WinKey+R彈出運行窗口,鍵入“cmd”回車,
           彈出的cmd窗口顯示當前目錄是C:\Document and Setting\xxx(win7則是C:\Users\xxx);
    step2. 再鍵入“D:”回車,跳轉到D盤;
    step3. 再用cd命令跳轉到當前exe所在目錄(如果目錄名較長,可以從資源管理器的路徑欄上copy)。
    win7上當然也可以這麼做,如下:
  2. 編譯aplusb.c
    假設你已經設置好了環境變量(如果你還沒有安裝配置命令行工具,點擊這裏
    gcc aplusb.c 
    將會有a.exe生成(如果想以其他名稱輸出加上-o選項,如gcc -o OutName.exe aplusb.c);
  3. 測試a.exe
    假設你已經準備好了一份測試數據,並以input.txt保存在相同目錄(D:\OJ)下(如果沒有,創建一個),則可以:
    a.exe < input.txt
    程序a.exe將會直接運行,並且以input.txt爲輸入;
    這裏的<符號叫重定向輸入符(它右邊的文件將替換左邊程序或命令的標準輸入(cmd窗口輸入))
    如input.txt內容如下:
    1 2 
    3 4
    5 6
    7 8
    9 10
    100 200
    200 400
    400 800
    20000 30000
    5000000 6000000
    70000000 80000000
    運行gcc和a.exe後:

升級

A+B問題太簡單?現在換一個問題:
統計問題
一組整數,統計最大值、最小值、平均值
輸入
第一行一個32位整數n表示測試數據個數,接下來的n行每行一個非負32位整數
輸出
一行,最小值、最大值、平均值,空格分開
這個問題也比較簡單;之所以舉這個例子,只是爲了突出重定向和管道的重要作用。
相信只要學過一點編程的都能立刻寫出來:
#include

#define INF 1000000000

int main() {

  int x, n, num, sum = 0, min = INF, max = -INF; 
  
  scanf("%d", &num);
  n = num;
  
  while( n-- ) {
	scanf("%d", &x);
	sum += x;
    if(x < min) min = x;
    if(x > max) max = x;
  }

  printf("%d %d %.3lf\n", min, max, (double)sum/num );
  return 0;
}

(這段程序裏有個小錯誤,稍後現形)
保存爲D:\OJ\Perls\sovle2.cpp
這裏也有一份測試數據input.txt:
10
20
30
40
50
60
70
80
90
編譯:
gcc solve2.cpp -o solve.exe
測試:
solve.exe < input.txt

結果正確!

隨機數生成器

你可能對上面的一組測試數據不夠滿意,太少,太小,太弱?
下面寫一個能夠生成滿足題目輸入格式的隨機數生成器:

#include 
#include 
#include 

int main()
{
	int n;
	srand( time(0) );
	
	scanf( "%d", &n );
	printf("%d\n", n);
	
	while(n--) {
		printf( "%u\n",  rand() << 16 + rand() );
	}
	
	return 0;
}

保存爲rand_gen.c
該程序讀入n,輸出n及n個隨機數(正如題目輸入格式)。
編譯:
gcc rand_gen.c -o randgen.exe
運行:

這時你可使用重定向輸出符(它右邊的文件將替換標準輸出(cmd窗口輸出)):
randgen.exe > rand_data.txt
再用重定向輸入進行測試:
solve.exe < rand_data.txt

管道

在已經有randgen.exe的情況下,使用管道更加方便:
echo 10 | randgen.exe

echo是回顯程序,echo 10將會輸出10
“|”是管道符號,它將會把左邊的程序(或命令)的輸出重定向到右邊程序(或命令)的輸入.
這裏的效果和前面手工輸入10是一樣的。
管道可以連接使用;所以,我們可以這樣:
echo 10 | randgen | solve
(.exe可以不用輸入)
過程是這樣的:
echo 10 ==10==> randgen.exe ==(臨時數據)===> solve.exe -> 屏幕輸出

這次測試出現了問題,最小值和平均值竟然都是負數!
查看一下代碼發現這裏有兩個問題:
i.無符號整數應該用unsigned int;
ii.sum溢出,應該用double;
更正:
#include

#define INF 1000000000

int main() 
{
  unsigned x, n, num, min = INF, max = -INF; // ,s = 0;
  double sum = 0;
  
  scanf("%d", &num);
  n = num;
  
  while( n-- ) {
	scanf("%d", &x);
	sum += x;
    if(x < min) min = x;
    if(x > max) max = x;
  }

  printf("%u %u %.3lf\n", min, max, sum/num );
  return 0;
}

保存爲final_solve.c
再次編譯測試:


附錄

windows官方參考使用命令重定向操作符:

http://technet.microsoft.com/zh-cn/library/cc772622(WS.10).aspx
Unix/Linux平臺,參考文章:

http://man.chinaunix.net/linux/mandrake/101/zh_cn/Command-Line.html/shell-pipes.html

發佈了31 篇原創文章 · 獲贊 40 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章