C ++에서 cin에서 EOF까지 읽는 방법


80

사용자 입력에서 직접 데이터를 읽는 프로그램을 코딩하고 있으며 표준 입력에서 EOF까지 모든 데이터를 (루프없이) 어떻게 읽을 수 있는지 궁금합니다. 나는 사용을 고려하고 cin.get( input, '\0' )있었지만 '\0'실제로는 EOF 문자가 아니며 EOF 또는 '\0'.

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

답변:


78

가변적 인 양의 데이터를 읽을 수있는 유일한 방법 stdin은 루프를 사용하는 것입니다. 나는 항상 std::getline()기능이 매우 잘 작동 한다는 것을 발견했습니다 .

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

기본적 getline()으로 개행까지 읽습니다. 대체 종료 문자를 지정할 수 있지만 EOF 자체는 문자가 아니므로를 한 번만 호출 할 수는 없습니다 getline().


8
여기서주의해야 할 점은 stdin을 통해 파이프 된 파일에서 읽을 때 이것과 대부분의 답변이 입력 끝에 추가 줄 바꿈을 추가한다는 것입니다. 모든 파일이 줄 바꿈으로 끝나는 것은 아니지만 루프를 반복 할 때마다 스트림에 "std :: endl"이 추가됩니다. 이것은 대부분의 경우 문제가되지 않을 수 있지만 파일 무결성이 문제인 경우이 문제가 다시 발생할 수 있습니다.
Zoccadoum

1
이것은 가장 찬성 된 답변이 아니어야합니다. 아래 커뮤니티 위키 답변을 참조하십시오. 또한 다음 질문을 참조하십시오. stackoverflow.com/questions/3203452/…
loxaxs aug

52

루프 사용 :

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

자원


50

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

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

3
좋은. "내부적으로 어떤 종류의 루프를 사용한다고 확신합니다."에 관해서는-모든 솔루션이 가능합니다.
Michael Burr

이것은 중간에 발생하더라도 입력에서 개행 문자를 제거하는 것처럼 보입니다.
Multisync

28

사용 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;
}

7
이것은 아마도 정식 대답이 될 것입니다.
Kerrek SB

2
반대 투표. 그렇다면 KeithB의 솔루션과 비교할 때 장단점은 무엇입니까? 예, std::istreambuf_iterator대신을 사용하고 있습니다 std::istream_iterator.하지만 무엇을 위해?
Multisync

std :: istreambuf_iterator는 기본적으로 공백을 건너 뛰고 더 빠를 수 있습니다.
Sopel

5

가장 간단하고 일반적으로 효율적일 수 있습니다.

#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입력이 너무 크면 조심하세요 )
ribamar dec


2

슬픈 메모 : 부스트 기반 코드와 일치하도록 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보다 큰 입력에 대해 차이를 만듭니다.


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

0
while(std::cin) {
 // do something
}

8
이것은 잘못된 코드로 이어질 것이 사실상 보장되기 때문에 대답의 끔찍한 재앙입니다.
Kerrek SB

@KerrekSB 왜 잘못된 코드가 발생하는 것이 사실상 보장됩니까?
matusf

1
@ MatúšFerech : // do somethingI / O 작업의 반환 값에 대한 추가 검사가 포함되지 않았 음을 강력히 제안하기 때문에 포함 된 검사는 의미가 없습니다.
Kerrek SB

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시스템 메모리가 부족할 때 예외가 발생합니다. 이러한 문제를 해결하기 위해 고정 된 양 의 요소를 예약 하고 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();
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.