コマンドラインの取得
(起動時にファイル名をコマンドラインから取得して作業する)

Copyright(C) 18May2003 coskx

UNIXでコンパイルする時
>gcc myprog.c
のように書く。(「gcc myprog.c」と書いた場所のことをコマンドラインと呼ぶ。)gccはコンパイラ(実はパーザ)と呼ばれるプログラムであるが,このプログラムを書いたプログラマは,将来自分の書いたプログラムが,どのような名前のCソースファイルをコンパイルすることになるのか知らない。プログラム起動時にgccの後にどんなことが書いてあるかわかれば,その位置に書かれたファイル名にもとづいてコンパイル作業ができる。
このようにコマンドラインの取得の仕方を解説する

内容は以下を含んでいる。
1 コマンドラインにいくつの単語が並んでいるかを知る
2 コマンドラインにどのような単語が並んでいるのか知る
3 コマンドラインに書かれたファイル名による作業のプログラム例(1)
4 コマンドラインに書かれたファイル名による作業のプログラム例(2)

 1 コマンドラインの単語数を取得する

次のプログラムの実行ファイル名はgetArgcとする。これまでプログラムの始まりは「int main()」であったが「int main(int argc)」としてある。

List 1.1 getArgc.c
#include <stdio.h>

int main(int argc)
{
    printf("argc=%d\n",argc);
    return 0;
}

コマンドラインで実行してみると次のようになる。

実行時のコンソール画面

>getArgc
argc=1

>getArgc abc
argc=2

>getArgc abc def
argc=3

>getArgc abc def ghijklmn
argc=4

このようにargcにはコマンドラインで,スペースによって分けられた文字列(単語)の数が保存されている変数となっている。なお変数名はargcである必要はないが,慣例でこれを使うことになっている。

 

 2 コマンドラインから単語を取得する

次のプログラムの実行ファイル名はgetArgvとする。これまでプログラムの始まりは「int main()」であったが「int main(int argc,char *argv[])」としてある。

List 2.1 getArgv.c
#include <stdio.h>

int main(int argc,char *argv[])
{
    int i;
    printf("argc=%d\n",argc);
    for (i=0;i<argc;i++) {
        printf("i=%d argv[i]=%s\n",i,argv[i]);
    }
    return 0;
}

コマンドラインで実行してみると次のようになる。

実行時のコンソール画面

>getArgv
argc=1
i=0 argv[i]=getArgv

>getArgv abc
argc=2
i=0 argv[i]=getArgv
i=1 argv[i]=abc

>getArgv abc def
argc=3
i=0 argv[i]=getArgv
i=1 argv[i]=abc
i=2 argv[i]=def

>getArgv abc def ghijklmn
argc=4
i=0 argv[i]=getArgv
i=1 argv[i]=abc
i=2 argv[i]=def
i=3 argv[i]=ghijklmn

このようにargvを使うとコマンドラインにどのような単語があるかを取得できる。ただし「char *argv[]」などという表現は中級の学習内容(ポインタ変数の配列)になるので,ここを学ぶ時点ではこの例を見ながら使えるようになっていればよい。

「int main(int argc,char *argv[])」と書くと第1引数文字列がargv[1]にあり,第2引数文字列がargv[2]にあり,以下同様に並ぶ。
(argv[1]は文字列char argv[]の第1要素の文字をあらわすのではなく,第1文字列を表すことに注意。)


 3 コマンドラインからファイル名を取得して作業(1)

コマンドラインから新規ファイル名を取得して新規ファイルを作成するプログラムを作ってみる。
プログラムの実行形式ファイルがmakeNewである時,実行させたいときに
>makeNew test.txt
と書いて,ファイルtest.txtを作らせてみよう。また単に
>makeNew
と書いたら,使い方が違うと言って終了してしまうように作ろう。

List 3.1 makeNew.c コマンドラインで与えられたファイル名のファイルを作る

#include <stdio.h>
#include <stdlib.h>/*for exit(1)*/

int main(int argc, char *argv[])
{
    FILE *fout;
    int i,j;
    /*書き出しファイル名:argv[1]*/
    if (argc<2) {
        printf("no filename\n");
        exit(1);
    }
    fout=fopen(argv[1],"w");
    if (fout==NULL){
        printf("can't open %s\n",argv[1]);
        exit(1);
    }
    fprintf(fout,"test test test\n");
    fclose(fout);
    return 0;
}

 4 コマンドラインからファイル名を取得して作業(2)

Cソースファイルを読み込んで,各行に行番号をつけて,別のファイルに保存するプログラムを作ろう。
ただし,次の仕様を満たすように作ろう。

(1)プログラムの実行ファイル名は「putln」(putLineNumber)とする。
(2)入力するCソースファイルの名前,出力するファイル名はコマンドラインにこの順で並べて書くことにする。
(3)2つのファイル名がコマンドラインに書いてなかったら,エラー処理をする。
(4)与えられたCソース名に対応するファイルが存在しなかったら,エラー処理をする。
(5)行番号は4桁で0001 0002 0003 ....とする。

ここでも「char *argv[]」の記述に対し,あまり細かいところは考えずに,argv[1]に第1文字列,argv[2]に第2文字列が得られ,
    printf("%s\n",argv[1]);

    fopen(argv[1],"r");
    fopen(argv[2],"w");
などの表現が使えることだけを修得しよう。

List 4.1 putln.c

#include <stdio.h>
#include <stdlib.h> /*exit()のため必要*/

int main(int argc,char *argv[])
{
    FILE *fin;
    FILE *fout;
    /*読み込みファイル名:argv[1]*/
    /*書き出しファイル名:argv[2]*/
    char textbuffer[512]; /*テキストを読み込む作業用文字列*/
    int lineNumber=1;
    if (argc!=3) {
        printf("incorrect command line\n");
        printf("usage : >putln prog.c prog.txt\n");
        exit(1);
    }
    printf("InputFileName=%s\n",argv[1]);
    printf("OutputFileName=%s\n",argv[2]);
    fin=fopen(argv[1],"r");
    if (fin==NULL) {
        printf("can't open file <%s>\n",argv[1]);
        exit(1);/*ファイルオープンエラーで緊急停止*/
    }
    fout=fopen(argv[2],"w");
    if (fout==NULL) {
        printf("can't open file <%s>\n",argv[2]);
        exit(1);/*ファイルオープンエラーで緊急停止*/
    }
    while (fgets(textbuffer,512,fin)!=NULL) { /*ファイル読み込みエラーでない限り*/
        fprintf(fout,"%04d %s",lineNumber,textbuffer);
        lineNumber++;
    }
    fclose(fin);
    fclose(fout);
    return 0;
}

実行時のコンソール画面は次のようになる。
1回目は成功した時
2回目はCソースファイル名を誤ったために,ファイルのオープンに失敗したところ
3回目は出力ファイル名を書き忘れたために,不正なコマンドラインだとしかられたところ

実行時のコンソール画面

>putln putln.c putln.txt
InputFileName=putln.c
OutputFileName=putln.txt

>putln putlm.c putln.txt
InputFileName=putlm.c
OutputFileName=putln.txt
can't open file <putlm.c>

>putln putln.c
incorrect command line
usage : >putln a.c a.txt

成功した時に出来たファイル「putln.txt」
0001 #include <stdio.h>
0002 #include <stdlib.h> /*exit()のため必要*/
0003
0004 int main(int argc,char *argv[])
0005 {
0006     FILE *fin;
0007     FILE *fout;
0008     /*読み込みファイル名:argv[1]*/
0009     /*書き出しファイル名:argv[2]*/
0010     char textbuffer[512]; /*テキストを読み込む作業用文字列*/
0011     int lineNumber=1;
0012     if (argc!=3) {
0013         printf("incorrect command line\n");
0014         printf("usage : >putln prog.c prog.txt\n");
0015         exit(1);
0016     }
0017     printf("InputFileName=%s\n",argv[1]);
0018     printf("OutputFileName=%s\n",argv[2]);
0019     fin=fopen(argv[1],"r");
0020     if (fin==NULL) {
0021         printf("can't open file <%s>\n",argv[1]);
0022         exit(1);/*ファイルオープンエラーで緊急停止*/
0023     }
0024     fout=fopen(argv[2],"w");
0025     if (fout==NULL) {
0026         printf("can't open file <%s>\n",argv[2]);
0027         exit(1);/*ファイルオープンエラーで緊急停止*/
0028     }
0029     while (fgets(textbuffer,512,fin)!=NULL) { /*ファイル読み込みエラーでない限り*/
0030         fprintf(fout,"%04d %s",lineNumber,textbuffer);
0031         lineNumber++;
0032     }
0033     fclose(fin);
0034     fclose(fout);
0035     return 0;
0036 }