2009年12月17日 星期四

格式化輸出

今天在寫Shell script時,需要用到格式化輸出,例如要串接001~100,可以用for迴圈加上printf達成:

for number in $(seq 1 100)
do
format=`printf %.03d $number`
# Do something else
done

2009年12月12日 星期六

Pipe

當兩個不同的Process要溝通時,我們可以用pipe來達成。簡單來說,pipe就像是一條水管,連接兩個Process,其中一端寫入資料到水管,另一端便可從水管中讀出此資料。

建立pipe:
#include <unistd.h>
int pipe(int pipefd[2]);

呼叫pipe()來建立pipe,其參數int pipefd[2]是用來回傳兩個file descriptors,pipefd[0]代表的是pipe的讀取端,pipefd[1]則是pipe的寫入端。

簡單範例:
#include <stdio.h>
#include <string.h>

int main() {
int pipefd[2];
pipe(pipefd);

char writeBuf[] = "Hello pipe!";
write(pipefd[1], writeBuf, strlen(writeBuf));

char readBuf[20];
int n = read(pipefd[0], readBuf, 20);
readBuf[n] = 0;
printf("%s\n", readBuf);

return 0;
}

接下來就將單一Process擴展到不同的Process,寫出ls | wc -l,也就是計算當前目錄下有幾個檔案。
先利用fork產生Child Process,再叫用execlp()執行外部指令。

#include <stdio.h>
#include <unistd.h>

int main() {
int pipefd[2];
pipe(pipefd);

pid_t pid = fork();
if(pid != 0) {
close(pipefd[1]);
dup2(pipefd[0], 0);
close(pipefd[0]);
execlp("wc", "wc", "-l", NULL);
}
else {
close(pipefd[0]);
dup2(pipefd[1], 1);
close(pipefd[1]);

execlp("ls", "ls", NULL);
}
return 0;
}

由於fork會使pipefd[0], pipefd[1]產生兩份,記得把不必要的Descriptor關閉,可避免不當的操作。
比較需要注意的便是dup2()的用法,dup2(pipefd[0], 0)可以把它想成複製pipefd[0]且當作是標準輸入(stdin),如此wc -l從stdin讀資料就會從pipe中讀取。
可參考此網頁的說明,便能明白dup2()的用意。

2009年12月9日 星期三

freopen()

當我們想要redirect我們的標準輸出(stdout)或標準輸入(stdin)到某一個檔案,可以使用freopen()來達成。
FILE *freopen(const char *path, const char *mode, FILE *stream);

以下是簡單小範例

#include <iostream>
int main() {
freopen("test.txt", "w", stdout);
std::cout << "Hello freopen()" << std::endl;
return 0;
}


執行時,便不會看到任何輸出,而是會出現在test.txt檔案裡。