사용자 입력에서 직접 데이터를 읽는 프로그램을 코딩하고 있으며 표준 입력에서 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()
.
스트림 반복기를 사용하여 명시 적 루프없이이를 수행 할 수 있습니다. 내부적으로 일종의 루프를 사용한다고 확신합니다.
#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;
}
사용 KeithB의 솔루션을 조사한 후 std::istream_iterator
, 나는 발견 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;
}
std::istreambuf_iterator
대신을 사용하고 있습니다 std::istream_iterator
.하지만 무엇을 위해?
가장 간단하고 일반적으로 효율적일 수 있습니다.
#include <iostream>
int main()
{
std::cout << std::cin.rdbuf();
}
필요한 경우 std::ostringstream
여기에서 표준 출력 스트림 대신 버퍼 와 같은 다른 유형의 스트림을 사용 하십시오.
std::ostringstream std_input; std_input << std::cin.rdbuf(); std::string s = std_input.str()
. 모든 입력이 있습니다 s
( std::string
입력이 너무 크면 조심하세요 )
당신이 사용할 수있는 표준 : : IStream을 ::의 getline () (또는 바람직하게는 표준 : : 문자열에 작품이 버전 ) 기능은 전체 라인을 얻을 수 있습니다. 둘 다 구분 기호 (줄 끝 문자)를 지정할 수있는 버전이 있습니다. 문자열 버전의 기본값은 '\ n'입니다.
슬픈 메모 : 부스트 기반 코드와 일치하도록 C ++ IO를 사용하기로 결정했습니다. 이 질문에 대한 답변에서 나는 선택했다 while (std::getline(std::cin, line))
. cygwin (mintty)에서 g ++ 버전 4.5.3 (-O3)을 사용하여 2MB / s 처리량을 얻었습니다. Microsoft Visual C ++ 2010 (/ O2)은 동일한 코드에 대해 40MB / s로 만들었습니다.
IO를 순수 C로 다시 작성한 후 while (fgets(buf, 100, stdin))
테스트 된 두 컴파일러 모두에서 처리량이 90MB / s로 뛰어 올랐습니다. 이는 10MB보다 큰 입력에 대해 차이를 만듭니다.
std::ios::sync_with_stdio(false);
. while 루프 앞에를 추가하면 됩니다. cin.tie(NULL);
읽기와 쓰기를 인터리브하는 경우에도 도움이 될 수 있습니다.
잠깐, 내가 당신을 올바르게 이해하고 있습니까? 키보드 입력에 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();
}
한 가지 옵션은 컨테이너를 사용하는 것입니다.
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();
}