次のプログラムがあります(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
私はすべての引数が渡された後にのみ何が必要かを知りたい。どうすればいいですか?
記述したとおりに、ファイル自体ではなく、ファイルの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
Terdonが既に指摘したように、これを行うには、ファイルからstdin
をリダイレクトする(およびprogram <inputfile.txt
などを使用してプログラムを呼び出す)か、コマンドラインから渡された引数を解析するようにプログラムを変更します( program 1 2
などを使用してプログラムを呼び出します。
最初のケースでは、cout
が端末に接続されていない場合は最初の2つのstdin
sを抑制し、2番目の場合では最初の2つのcout
sを抑制します、たとえば、コマンドラインから渡された引数が十分ではありません。
最初の方法と言えば、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
そのため、できることがいくつかあります。
cout << "Enter...
行を削除して、プログラムの唯一の出力がファイルに入るようにすることができます。xargs program.cc < file.txt 2> outputresult.txt
を実行します(>ではなく2>を使用)。ファイル内でcerrを表示してcoutを使用する場合は、>で上記のように実行します。cat outputresult.txt | grep Sum > tempfile && mv tempfile outputresult.txt
次のようなコードでこれを実装できます。
./program.cc < file.txt | grep Sum > outputresult.txt
ただし、この方法では改行を記述する必要があります。そのため、改行をそれぞれ出力する必要があります。
個人的には、プログラムの使用に応じて、C++内のファイル管理またはcoutおよびcerrハックの使用をお勧めします。