第2回 ほかのソフトにまかせよう



ある機能を実現したいと思ったとき、すべて内部で処理するのではなく、ほかのソフトに制御を移してやってもらうという方法があります。うまく使えば、プログラミングの労力が減らせます。


[トップページ] / [CによるMS-DOSプログラミング]


【system()関数を使う】

system()関数は、引数として受け取った文字列をそのまま実行します。COMMAND.COMをロードするので、

system( "DIR /W" );
system( "MORE < HOGE.TXT" );

のように、MS-DOSの内部コマンドを実行したり、リダイレクトが可能です。

/* SAMPLE04.C */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main( int argc, char *argv[] )
{
    char buf[ 256 ] = "type ";
    
    strcat( buf, argv[ 1 ] );
    printf( "%sを実行します。\n", buf );
    system( "PAUSE" );
    system( buf );
    return 0;
}

A>SAMPLE04 HOGE.TXT

とすることにより、TYPE HOGE.TXTを実行するプログラムです。はっきり言ってこのプログラムは意味がないので、有効な利用法を考えてみてください。


【spawn()関数を使う】

system()関数は、何でも実行できて便利なのですが、COMMAND.COMをロードするためメモリを消費してしまいます。直接プログラムを実行したいときには、spawn()を使います。

実際には、spawnl,spawnlp,spawnv,spawnvp,spawnle,spawnlpe,spawnve,spawnvpeというように、さまざまな関数が用意されています(LSI Cの場合)。spawnに続く文字で動作が微妙に異なります。

l 引数をリスト形式で渡す
v 引数を配列で渡す
p 環境変数PATHを使って実行ファイルを探す
e 子プロセスに環境変数の配列を渡す

pは大変ありがたいので、よく使うのはspawnlpとspawnvpでしょう。

int spawnlp( int mode, char *name, char *arg0, char *arg1, ..., NULL );
int spawnvp( int mode, char *name, char *argv[] );

modeには、P_WAITと記述します。子プロセス実行中は、親プロセスは停止するという意味です。P_OVERLAYと書くと制御が戻ってこないので、あまり使い道はありません。ちなみにP_OVERLAYは、exec()という関数と同じ働きをします。

nameには、実行したいプログラム名を書きます。次の引数であるarg0やargv[ 0 ]にもプログラム名が入ることに注意してください。また、最後は必ずNULLで終わらせなければなりません。

では、2つの違いをプログラムで見てみましょう。

/* SAMPLE05.C */

#include <stdio.h>
#include <stdlib.h>
#include <process.h>

int main( void )
{
    char *argv[ 3 ];
    
    spawnlp( P_WAIT, "TREE.COM", "TREE.COM", "/A", NULL );
    
    argv[ 0 ] = "TREE.COM";
    argv[ 1 ] = "/A";
    argv[ 2 ] = NULL;
    spawnvp( P_WAIT, "TREE.COM", argv );
    return 0;
}

どちらを使っても処理は同じなので、都合の良いほうを選びましょう。

このようにしてほかのソフトを実行させると、楽ができるというわけです。P_WAITとしてあるので、そのソフトが終了すれば、制御は戻ってきます。関数を呼び出すのと同じ感覚ですね。

ほかのソフトを実行中は、自分のプログラムはメモリに常駐したままなので、メモリを圧迫していることを頭に入れておかねばなりません。system()では、COMMAND.COMの分も余計に使います。ですから、少しでもメモリ消費を抑えるよう工夫しましょう(メモリモデル、コンパイル方法、配列の大きさなど)。


[トップページ] / [CによるMS-DOSプログラミング]