web-dev-qa-db-ja.com

C ++プログラムのコマンドラインでファイルの内容を渡す

次のプログラムがあります(program.ccと呼びましょう):

int main() {
  int x, y, sum;
  std::cout << "A program which adds two integers\n";
  std::cout << "Enter 1st integer: ";
  std::cin >> x;
  std::cout << "Enter 2nd integer: ";
  std::cin >> y;
  sum = x + y;
  std::cout << "Sum is " << sum << std::endl;
  return 0;
}

現在、ファイルを取得し、このcppプログラムに渡される引数としてコマンドラインを介してプッシュするbashスクリプトを作成しています。ご覧のとおり、上記のプログラムは2つの入力を要求しています。

Stdinの入力として使用するファイルの内容を渡す方法を知っています。しかし、コマンドラインを介してファイルの内容を引数として渡したい場合、どうすればよいでしょうか?

詳しく説明すると、file.txtが興味のあるファイルであり、別々の行に2つの整数が含まれているだけだとします。

編集:xargsコマンドを試しました:

       xargs program.cc < file.txt > outputresult.txt

しかし、これは最終的に私が持っているものを印刷することになります、例えば:

     A program which adds two integers
     Enter 1st integer: Enter 2nd integer: Sum is 2

私はすべての引数が渡された後にのみ何が必要かを知りたい。どうすればいいですか?

1
E 4 6

記述したとおりに、ファイル自体ではなく、ファイルのcontentsをプログラムに渡す必要があります(xargsは不要です。ところで)。そのための1つの方法は、 入力リダイレクト を使用することです。

a.out < file

例えば:

$ cat file
4 
7
$ ./a.out < file
A program which adds two integers
Enter 1st integer: Enter 2nd integer: Sum is 11

同じことを行う別の方法は、ファイルの内容を出力し、パイプを使用してプログラムに渡すことです。

$ cat file | ./a.out 
A program which adds two integers
Enter 1st integer: Enter 2nd integer: Sum is 11

もちろん、はるかにクリーンなアプローチは、標準入力を読み取る代わりに引数を取ることができるようにプログラムを作成することです。

./a.out 4 7

または、ファイルを内部で開き、入力データを解析できるように記述します。

./a.out file

とにかく、出力の最後の行のみを取得するには、残りを標準エラーに出力します。

#include <iostream>

int main() {
  int x, y, sum;
  std::cerr << "A program which adds two integers\n";
  std::cerr << "Enter 1st integer: ";
  std::cin >> x;
  std::cerr << "Enter 2nd integer: ";
  std::cin >> y;
  std::cerr << "\n";
  sum = x + y;
  std::cout << "Sum is " << sum << std::endl;
  return 0;
}

次に、実行します:

$ ./a.out < file > output.txt
A program which adds two integers
Enter 1st integer: Enter 2nd integer: 
$ cat output.txt
Sum is 11

または、値を手動で指定するには:

$ ./a.out > output.txt 
A program which adds two integers
Enter 1st integer: 4
Enter 2nd integer: 7

$ cat output.txt 
Sum is 11
2
terdon

Terdonが既に指摘したように、これを行うには、ファイルからstdinをリダイレクトする(およびprogram <inputfile.txtなどを使用してプログラムを呼び出す)か、コマンドラインから渡された引数を解析するようにプログラムを変更します( program 1 2などを使用してプログラムを呼び出します。

最初のケースでは、coutが端末に接続されていない場合は最初の2つのstdinsを抑制し、2番目の場合では最初の2つのcoutsを抑制します、たとえば、コマンドラインから渡された引数が十分ではありません。

最初の方法と言えば、isatty()関数(unistd.hで定義されたPOSIX関数)を使用して、ファイル記述子が端末に接続されているかどうかを確認できます。

int isatty(int fd);

fdが端末に接続された開かれたファイル記述子である場合、関数は1を返します。 fdが開いているファイル記述子ではない場合、または端末に接続されていない場合、関数は0を返します。

#include <iostream>
#include <unistd.h>

int main() {
    int x, y, sum;
    std::cout << "A program which adds two integers\n";
    if(isatty(0)) {
        std::cout << "Enter 1st integer: ";
    }
    std::cin >> x;
    if(isatty(0)) {
        std::cout << "Enter 2nd integer: ";
    }
    std::cin >> y;
    sum = x + y;
    std::cout << "Sum is " << sum << std::endl;
    return 0;
}

この方法では、stdinがリダイレクトされていない場合にのみ、ユーザーは数字を挿入するように求められます。

user@user-X550CL ~/tmp % ./a.out               
A program which adds two integers
Enter 1st integer: 1
Enter 2nd integer: 2
Sum is 3
user@user-X550CL ~/tmp % cat inputfile.txt 
3
4
user@user-X550CL ~/tmp % ./a.out <inputfile.txt 
A program which adds two integers
Sum is 7

2番目の方法について言えば、コマンドラインから渡された引数を解析する方法の非常に大まかな例です(コマンドラインから渡された引数は、文字へのポインターの配列であるargvに格納されます。各引数を整数にキャストする必要がありますが、atoi()を使用しないでください!引数が数値かどうかを確認できるものを使用してください。単純にするためにatoi()を使用しました) :

#include <iostream>
#include <cstdlib>

int main(int argc, char *argv[]) {
    int x, y, sum;
    std::cout << "A program which adds two integers\n";
    if(argc == 3) {
        x = atoi(argv[1]);
        y = atoi(argv[2]);
    }
    else {
        std::cout << "Enter 1st integer: ";
        std::cin >> x;
        std::cout << "Enter 2nd integer: ";
        std::cin >> y;
    }
    sum = x + y;
    std::cout << "Sum is " << sum << std::endl;
    return 0;
}

この方法では、コマンドラインから十分な引数が渡されていない場合にのみ、数字を挿入するように求められます。

user@user-X550CL ~/tmp % ./a.out
A program which adds two integers      
Enter 1st integer: 1
Enter 2nd integer: 2
Sum is 3
user@user-X550CL ~/tmp % ./a.out 3
A program which adds two integers
Enter 1st integer: ^C
user@user-X550CL ~/tmp % ./a.out 3 4
A program which adds two integers
Sum is 7
1
kos

そのため、できることがいくつかあります。

  1. this のようなものを使用して、C++内のファイルに出力できます。
  2. コードのcout << "Enter...行を削除して、プログラムの唯一の出力がファイルに入るようにすることができます。
  3. エラー出力ストリーム(coutではなくcer)を使用して回避し、それに応じて出力を操作できます。 coutを表示してファイル内でcerrを使用する場合は、xargs program.cc < file.txt 2> outputresult.txtを実行します(>ではなく2>を使用)。ファイル内でcerrを表示してcoutを使用する場合は、>で上記のように実行します。
  4. 現在の出力を保持しますが、コードから不要な行を削除する実行をさらに2回実行します。

cat outputresult.txt | grep Sum > tempfile && mv tempfile outputresult.txt

次のようなコードでこれを実装できます。

./program.cc < file.txt | grep Sum > outputresult.txt

ただし、この方法では改行を記述する必要があります。そのため、改行をそれぞれ出力する必要があります。

個人的には、プログラムの使用に応じて、C++内のファイル管理またはcoutおよびcerrハックの使用をお勧めします。

0
Zzzach...