2008-10-14 2 views
65

사용자 입력에서 직접 데이터를 읽는 프로그램을 코딩 중이며 표준 입력에서 EOF까지 모든 데이터를 읽을 수있는 방법이 궁금합니다. 나는 cin.get(input, '\0')을 사용하려고했지만 '\0'은 실제로는 EOF 문자가 아니며 EOF 또는 '\0'까지 읽습니다. 둘 중 빠른 날짜가됩니다.C++의 cin에서 EOF까지 읽는 방법

또는 루프를 사용하는 유일한 방법은 무엇입니까? 그렇다면 가장 좋은 방법은 무엇입니까?

답변

57

stdin에서 다양한 양의 데이터를 읽을 수있는 유일한 방법은 루프를 사용하는 것입니다. 난 항상 std::getline() 기능은 아주 잘 작동 것으로 나타났습니다 : 기본의 getline()에 의해

std::string line; 
while (std::getline(std::cin, line)) 
{ 
    std::cout << line << std::endl; 
} 

는 줄 바꿈 할 때까지 읽습니다. 대체 종료 문자를 지정할 수 있지만 EOF 자체는 문자가 아니므로 getline()을 한 번만 호출 할 수는 없습니다.

+5

뭔가 여기서 조심해야한다 당신은 표준 입력을 통해에서 파이프 된 파일에서 읽는 때, 이 답변과 대부분의 답변은 입력이 끝날 때 추가 라인 피드를 추가합니다. 모든 파일이 줄 바꿈으로 끝나는 것은 아니지만 루프의 각 반복은 "std :: endl"을 스트림에 추가합니다. 이것은 대부분의 경우 문제가되지 않을 수 있지만 파일 무결성이 문제가되면 다시 물러날 수 있습니다. – Zoccadoum

+0

이것은 upvoted 대답이되어서는 안됩니다. 아래 커뮤니티 Wiki 답변을 참조하십시오. 또한이 질문을 참조하십시오. https://stackoverflow.com/questions/3203452/how-to-read-entire-stream-into-a-stststring – loxaxs

40

스트림 반복기를 사용하여 명시 적 루프없이 수행 할 수 있습니다. 나는 내부적으로 어떤 종류의 루프를 사용한다고 확신한다.

#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; 
} 
+2

Nice. "내부적으로 어떤 종류의 루프를 사용한다고 확신합니다"- 모든 솔루션이 그렇습니다. –

+0

이것은 가운데에서 오른쪽 줄이 생기더라도 줄 바꿈 문자를 입력에서 제거하는 것 같습니다. – Multisync

36

사용 루프 :

#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)) 
{ 
    ... 
} 

resource

1
while(std::cin) { 
// do something 
} 
+7

사실상 잘못된 코드가 생성 될 수 있기 때문에 이것은 심각한 재앙입니다. –

2

슬픈 옆의 노트 : 나는 부스트 기반의 코드와 일치하는 C++ IO를 사용하기로 결정했다. 이 질문에 대한 답변에서 while (std::getline(std::cin, line))을 선택했습니다. cygwin (mintty)에서 g ++ 버전 4.5.3 (-O3)을 사용하면 2 MB/s 처리량이 있습니다. Microsoft Visual C++ 2010 (/ O2)은 동일한 코드에서 40MB/s로 만들었습니다.

IO를 순수 C while (fgets(buf, 100, stdin))으로 다시 작성한 후에 테스트 된 컴파일러 모두에서 처리량이 90 MB/s로 뛰었습니다. 10MB보다 큰 입력에 차이가 있습니다 ...

+0

코드를 순수한 C로 다시 작성할 필요가 없습니다. while 루프 앞에 'std :: ios :: sync_with_stdio (false);'를 추가하면됩니다. 'cin.tie (NULL); '는 읽기와 쓰기를 인터리빙 할 때도 도움이 될 수 있습니다. –

0

잠깐만 요, 올바르게 이해하고 있습니까? 키보드 입력에 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(); 
    } 
0

하나의 옵션은 예를 들어,

std::vector<char> data; 

EOF까지 컬렉션에 모든 입력이 수신 될 때, 즉 리디렉션

std::copy(std::istream_iterator<char>(std::cin), 
    std::istream_iterator<char>(), 
    std::back_inserter(data)); 

그러나, 사용 된 컨테이너는 너무 자주 메모리를 재 할당해야하거나 시스템의 메모리가 부족 얻을 때 당신은 std::bad_alloc 예외로 끝납니다. 필요한 경우

#include <iostream> 
int main() 
{ 
    std::cout << std::cin.rdbuf(); 
} 

: 이러한 문제를 해결하기 위해, 당신은 예비 고정 금액 요소의 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(); 
} 
3

가능성있는 간단하고 일반적으로 효율적으로 처리 할 수 여기에는 표준 출력 스트림 대신 버퍼로 std::ostringstream과 같은 다른 유형의 스트림을 사용하십시오.

+0

너희들은 이미 알고 있지만 어떤 사람들에게는 도움이 될 것이다.'std :: ostringstream std_input; std_input << std :: cin.rdbuf(); std :: string s = std_input.str()'. 당신은's'에 모든 입력 값을 가지고 있습니다. (입력 값이 너무 크면'std :: string'과 조심해야합니다.) – ribamar

14

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; 
} 
+2

이것은 정규 응답이어야합니다. –

+0

Downvoted. 그렇다면 KeithB의 솔루션과 비교하여 장단점은 무엇입니까? 예, 당신은'std :: istreambuilder_iterator' 대신에'std :: istreambuf_iterator'를 사용하고 있습니다. – Multisync