ユーザー入力から直接データを読み取るプログラムをコーディングしていますが、標準入力からEOFまですべてのデータを(ループなしで)読み取ることができるのか疑問に思っていました。 cin.get( input, '\0' )
を使用することを検討していましたが、'\0'
は実際にはEOF文字ではなく、EOFまたは'\0'
のいずれか早い方まで読み取ります。
または、それを行う唯一の方法はループを使用していますか?もしそうなら、最良の方法は何ですか?
Stdinから可変量のデータを読み取ることができる唯一の方法は、ループを使用することです。 std::getline()
関数が非常にうまく機能することが常にわかっています。
std::string line;
while (std::getline(std::cin, line))
{
std::cout << line << std::endl;
}
デフォルトでは、getline()は改行まで読み取ります。別の終了文字を指定できますが、EOFはそれ自体が文字ではないため、getline()を1回呼び出すことはできません。
ストリームイテレータを使用すると、明示的なループなしで実行できます。内部で何らかのループを使用していると確信しています。
#include <string>
#include <iostream>
#include <istream>
#include <ostream>
#include <iterator>
int main()
{
// don't skip the whitespace while reading
std::cin >> std::noskipws;
// use stream iterators to copy the stream to a string
std::istream_iterator<char> it(std::cin);
std::istream_iterator<char> end;
std::string results(it, end);
std::cout << results;
}
ループの使用:
#include <iostream>
using namespace std;
...
// numbers
int n;
while (cin >> n)
{
...
}
// lines
string line;
while (getline(cin, line))
{
...
}
// characters
char c;
while (cin.get(c))
{
...
}
std::istream_iterator
を使用してKeithBのソリューションを調査した後、 std:istreambuf_iterator
を発見しました。
パイプ処理されたすべての入力を文字列に読み取り、再度書き込むテストプログラム:
#include <iostream>
#include <iterator>
#include <string>
int main()
{
std::istreambuf_iterator<char> begin(std::cin), end;
std::string s(begin, end);
std::cout << s;
}
おそらく最も単純で一般的に効率的:
#include <iostream>
int main()
{
std::cout << std::cin.rdbuf();
}
必要に応じて、ここでは標準出力ストリームの代わりにstd::ostringstream
などの他のタイプのストリームをバッファーとして使用します。
std :: istream :: getline() (または、できれば std :: stringで動作するバージョン )関数を使用して、行全体を取得できます。どちらにも、区切り文字(行末文字)を指定できるバージョンがあります。文字列バージョンのデフォルトは「\ n」です。
悲しいことに、ブーストベースのコードとの整合性を保つために、C++ IOを使用することにしました。この質問への回答から、while (std::getline(std::cin, line))
を選択しました。 cygwin(mintty)でg ++バージョン4.5.3(-O3)を使用すると、2 MB/sのスループットが得られました。 Microsoft Visual C++ 2010(/ O2)は、同じコードで40 MB/sになりました。
IOを純粋なC while (fgets(buf, 100, stdin))
に書き換えた後、テストされた両方のコンパイラでスループットが90 MB/sに跳ね上がりました。これは、10 MBを超える入力に対して違いをもたらします...
待って、あなたを正しく理解していますか?キーボード入力にcinを使用しており、ユーザーがEOF文字を入力したときに入力の読み取りを停止しますか?ユーザーがEOF文字を入力するのはなぜですか?または、EOFでファイルからの読み取りを停止したいという意味ですか?
実際にcinを使用してEOF文字を読み取ろうとしている場合、区切り文字としてEOFを指定しないのはなぜですか?
// Needed headers: iostream
char buffer[256];
cin.get( buffer, '\x1A' );
EOFでファイルからの読み取りを停止する場合は、getlineを使用して、区切り文字としてEOFを再度指定します。
// Needed headers: iostream, string, and fstream
string buffer;
ifstream fin;
fin.open("test.txt");
if(fin.is_open()) {
getline(fin,buffer,'\x1A');
fin.close();
}
while(std::cin) {
// do something
}
1つのオプションは、コンテナを使用することです。
std::vector<char> data;
およびリダイレクトEOF
が受信されるまで、このコレクションへのすべての入力、つまり.
std::copy(std::istream_iterator<char>(std::cin),
std::istream_iterator<char>(),
std::back_inserter(data));
ただし、使用済みのコンテナはメモリを頻繁に再割り当てする必要がある場合があります。そうしないと、システムがメモリ不足になったときにstd::bad_alloc
例外で終了します。これらの問題を解決するには、予約固定量のN
要素を使用し、これらの量の要素を単独で処理することができます。
data.reserve(N);
while (/*some condition is met*/)
{
std::copy_n(std::istream_iterator<char>(std::cin),
N,
std::back_inserter(data));
/* process data */
data.clear();
}