質問
【C言語】コマンドライン引数の標準入出力
- 投稿日時:2010/07/30 14:38

【C言語】コマンドライン引数の標準入出力
コマンドライン引数で、ファイル名を3つ渡します。-aの次のコマンドライン引数が、出力ファイル名です。
<<例>>
・実行モジュール -a 出力ファイル名 -b ファイル名 -c ファイル名
・実行モジュール -c ファイル名 -a 出力ファイル名 -b ファイル名
もし出力ファイルが指定されなかった場合に、標準入出力を使いたいのですが、どうしたらいいかわかりません。
下記がソースの一部です。これをどう改造したらよいでしょうか。
分かる方いらっしゃいましたらご回答いただけると幸いです。
宜しくお願いします。
//出力ファイルを取得、書き込みモードでオープン
for(j=1;j<argc-1;j++){
if(strcmp(argv[j],"-o")==0){
if((fo = fopen(argv[j+1],"w"))==NULL){
printf("open error!!\n");
exit(1);
}
}
}
while(fgets(buf,sizeof(buf),fp)!= NULL){
if(strstr(buf,"keyword")!= NULL){
//出力ファイルに出力
fprintf(fo,"%d:%s",line,buf);
}
}
回答 (4件)
- 最新から表示
- 回答順に表示
- ベストアンサーのみ表示
No.4
- 回答日時:2010/07/31 09:47
> -aの次のコマンドライン引数が、出力ファイル名です。
コードでは -o となってるけど?
別の回答者さんの言うように、fopen() は後回しにした方がいいでしょう。
> for(j=1;j<argc-1;j++){
これだと最後の引数を評価してませんよ?
全てが -o file みたいならいいですが、file が必要ないスイッチがあるとまずくありませんか?
FILE * fo = stdout;
char * outf = NULL;
for(j=1;j<argc;j++){
if(strcmp(argv[j],"-o")==0){
if (++j < argc) {
if (outf) {
fprintf(stderr, "duplicate -o option\n");
exit(1);
}
outf = argv[j];
} else {
fprintf(stderr, "-o option requires a output filename\n");
exit(1);
}
}
}
if (outf && (fo = fopen(outf, "w"))==NULL){
printf("open error!!\n");
exit(1);
}
この回答へのお礼
おかげ様で解決できました。
ご回答ありがとうございました。
No.3ベストアンサー20pt
- 回答日時:2010/07/30 15:21
追記。
>本来「すべてのコマンドライン引数を評価し終わるまで、fopenなどの実質的な処理を開始しない方が良い」でしょう。
回答の前半に書いた「引数を評価しながらfopenしちゃうプログラム」で
実行モジュール -o 出力ファイル名1 -b ファイル名 -c ファイル名 -o 出力ファイル名2 -o 出力ファイル名3
って実行したら「中身が空の『出力ファイル名1』が作成されてしまってから、duplicate -o switch!ってエラーが表示されて停止してしまう」と思います。
質問者さんも「エラー表示して止まるんだったら、中身が空の『出力ファイル名1』が作成されない方が良い」と思いませんか?
なので「すべてのコマンドライン引数を評価し終わるまで、fopenなどの実質的な処理を開始してはいけない」のです。
この回答へのお礼
なるほど、fopenを後回しにするとできました。
非常に参考になりました。ご回答ありがとうございました。
No.2
- 回答日時:2010/07/30 15:14
#include <stdio.h>
fo = NULL;
for(j=1;j<argc-1;j++){
if(strcmp(argv[j],"-o")==0){
if(fo != NULL){
fclose(fo);
printf("duplicate -o switch!!\n");
exit(1);
}
if((fo = fopen(argv[j+1],"w"))==NULL){
printf("open error!!\n");
exit(1);
}
}
}
if(fo == NULL){
fo=stdout;
}
while(fgets(buf,sizeof(buf),fp)!= NULL){
if(strstr(buf,"keyword")!= NULL){
//出力ファイルに出力
fprintf(fo,"%d:%s",line,buf);
}
}
if(fo != stdout){
fclose(fo);
}
本来「すべてのコマンドライン引数を評価し終わるまで、fopenなどの実質的な処理を開始しない方が良い」でしょう。
つまり
#include <stdio.h>
#undef FIRST_SWITCH_ENABLED
FILE *fo;
char *fo_name;
fo = NULL;
fo_name = NULL;
for(j=1;j<argc-1;j++){
if(strcmp(argv[j],"-o")==0)){
#ifdef FIRST_SWITCH_ENABLED
if(fo_name == NULL) //このif文があると「最初の-oが有効」で、if文が無いと「最後の-oが有効」になる
#endif
fo_name = argv[j+1];
}
}
if(fo_name != NULL){
if((fo = fopen(fo_name,"w"))==NULL){
printf("open error!!\n");
exit(1);
}
}else{
fo=stdout;
}
while(fgets(buf,sizeof(buf),fp)!= NULL){
if(strstr(buf,"keyword")!= NULL){
//出力ファイルに出力
fprintf(fo,"%d:%s",line,buf);
}
}
if((fo_name != NULL)&&(fo != NULL)){
fclose(fo);
}
とします。
これで、
実行モジュール -o 出力ファイル名1 -b ファイル名 -c ファイル名 -o 出力ファイル名2 -o 出力ファイル名3
と書かれた場合も、引数の解析の途中でエラーで止めずに済みます。
「最初の-o」か「最後の-o」のどちらを有効にするかは、コメントを付けたif文の有無で決まります。
if文の有無は、識別子「FIRST_SWITCH_ENABLED」を定義するか未定義にするかで決まります。
- 質問者のみ
- この回答にお礼をつける
No.1
- 回答日時:2010/07/30 14:43
起動後の処理に
コマンドライン引数の内容をチェックする処理を加えればいいのよ。
指定があれば変数fileOutputFlg=trueにして、ファイルを開く。
なければfalseにしておいて。
出力は、例えばwriteLog("",,,)という関数で行い
その中で
fileOutputFlgがtrueならファイルハンドラ、
falseなら標準出力に出力
こんな感じね。
この回答へのお礼
なるほど、参考にさせていただきます。
ご回答ありがとうございました。
このQ&Aを見た人はこんなQ&Aも見ています
注目の記事
えっ!こんな仕事があるの?
思わず「えっ!こんな仕事があるの?」と言いたくなる世間的に知られていない特殊な職業について迫ります。
このQ&Aを見た人がよく見るQ&A
このカテゴリで人気のQ&Aランキング
- 4int型からchar型への変換
- 5初心者におすすめのC言語開発環境を...
- 6C言語とC++ の違いについて(オブジ...
- 7sleep()関数について
- 8プロ野球の結果を教えてください
- 9C言語で簡単なゲームを作る方法
- 10ファイルやディレクトリの存在確認...
- 11配列の要素数に変数を入れたいときには
- 12C++とVC++の違いについて
- 13セマフォとmutexの違いは?
- 14int main()、void main()、void mai...
- 15C言語のおすすめ本を教えてください。
- 16stdin,stdoutについて
- 17C言語でゲーム作り テトリス
- 18getterとsetterについて
- 19クロック周波数
- 20printf で二進表示を行いたい。





