C++ Chapter 18.1 : istream으로 입력받기

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!


chapter 18. 입력과 출력

istream으로 입력받기

#include <iostream>

#include <iomanip>

🔔 iostream.h

#include <iostream>
#include <string>
#include <iomanip>	// input/output manipulators

using namespace std;

int main()   
{
	cout << "Enter a number" << endl;
	
	int i;
	cin >> i;  // 입력

	cout << i << endl;  // 출력

	return 0;
}
  • std::cin
    • C++ 표준인 istream타입의 객체이다.
    • 👉 공백 단위로 입력을 받는다.
    • >> 연산자가 istream 객체와 어떤 변수를 인수로 받으면 입력된 데이터가 변수에 저장되게끔 오버로딩이 되어 있기 때문에 >>와 함께 사용된다.


🔔 iomanip.h

iomaip.h 을 사용하면 도움될 때

#include <iostream>
#include <string>
#include <iomanip>	// input/output manipulators

using namespace std;

int main()   
{
	char buf[10];

	cin >> buf;   // 엔터치면 콘솔창에 입력한 것들이 buf에 저장된다. 
	cout << buf << endl;

	return 0;
}
  • 콘솔창에 입력하고 엔터치면 입력한 내용이 스트림 버퍼에 들어가고 그리고 다시 여기로부터 해당 변수로 입력이 들어간다.
  • char buf[10] 에 문자들을 입력받아 하나의 문자열을 넣고 싶다면 cin >> buf 을 실행하면 된다.
    • 단, 이 경우 buf 크기인 10 보다 1 작은 9 글자를 넘게 입력하면 런타임 에러가 발생하게 된다. (1글자는 \0에 써야 함)
    • 항상 이렇게 사용자가 조심하면서 입력하기엔 너무 불편하다. 👉 iomanip.hsetw 함수를 사용하여 해결!


setw

#include <iomanip>

setw(N) 최대 N - 1 글자만 입력 받도록 방지해준다. (나머지 하나는 \0)

  • 10 글자 넘게 입력하고 엔터를 치더라도 런타임 에러 없이 딱 9 글자 + '\0'만 buf 에 들어가게 된다
    #include <iostream>
    #include <string>
    #include <iomanip>	// input/output manipulators
    
    using namespace std;
    
    int main()   
    {
      char buf[10];
    
      cin >> setw(10) >> buf;   // 9글자를 초과해서 입력해도 런타임 에러가 발생하지 않는다. 
      cout << buf << endl;  // 딱 입력한 것의 9글자 + '\0'까지만 출력되는 것을 볼 수 있음
    
      return 0;
    }
    
  • 다만 setw(N)으로 N글자를 넘어 잘리게 된 입력 문자들은 스트림 버퍼에 그대로 남아있게 된다.
    • “abcdefghijk” 입력 후 cin 입력을 2번 받으면 두번째 입력에선 콘솔 입력을 받지 않고 스트림 버퍼에 남아있는 "efghijk" 에서 입력을 바로 받게 된다.
      #include <iostream>
      #include <string>
      #include <iomanip>	// input/output manipulators
      
      using namespace std;
      
      int main()   
      {
          char buf[5]; 
      
          cin >> setw(5) >> buf;   // 콘솔창에 abcdefghijk 입력,  buf에 abcd 들어감
          cout << buf << endl;    // buf = "abcd\0" 출력
      
          cin >> setw(5) >> buf;// 콘솔창 입력 X. 버퍼에 남아있는 efghijk 에서 4글자 buf에 대입
          cout << buf << endl; // buf = "efgh\0" 출력
      
          return 0;
      }
      
    • “abcdefghij” 입력 후 cin 입력을 3번 받으면
      #include <iostream>
      #include <string>
      #include <iomanip>	// input/output manipulators
      
      using namespace std;
      
      int main()   
      {
          char buf[5]; 
      
          cin >> setw(5) >> buf;   // 콘솔창에 abcdefghij 입력,  buf에 abcd 들어감
          cout << buf << endl;    // buf = "abcd\0" 출력
      
          cin >> setw(5) >> buf;// 콘솔창 입력 X 버퍼에 남아있는 efghij 에서 4글자 buf에 대입
          cout << buf << endl; // buf = "efgh\0" 출력
      
          cin >> setw(5) >> buf;   // 콘솔창 입력 X 버퍼에 남아있는 ij 에서 남은 2글자 buf에 대입
          cout << buf << endl;    // buf = "ij\0\0\0" 출력
      
          return 0;
      }
      


🔔 cin 의 여러 함수들

#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char ch;

	while (cin >> ch)
		cout << ch;

	return 0;
}
💎입력💎
Hello World

💎출력💎
HelloWorld
  • 콘솔창에 Hello World 입력 후 엔터
  • chchar 문자 타입이다.
  • char타입인 ch에 입력 받는 것이므로 스트림 버퍼에 ‘H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘W’ ‘o’ ‘r’ ‘l’ ‘d’ 이렇게 한 글자씩 char로서 들어간다. cin은 공백은 무시하므로 공백은 문자로 들어가지 않는다.
  • 이제 while (cin >> ch) 에서 나와 cout << ch 스트림 버퍼로부터 한 글자씩 HelloWorld 를 출력한다.
  • while문 이므로 다시 while (cin >> ch) 로 돌아가 입력을 기다린다. 깜빡깜빡
#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	int i;
	float f;

	cin >> i >> f;

	cout << i << " " << f << endl;

	return 0;
}
💎입력💎
1024 3.14

💎출력💎
1024 3.14
  • cin >> i >> f
    • 1024 3.14 를 콘솔창에 입력하면 스트림 버퍼에 1024, 3.14 이렇게 들어가게 되고 공백을 기준으로 구분되어 1024는 i에, 3.14는 f에 저장된다.
    • 공백은 입력되지 않는다.


cin.get

cin.get공백도 하나의 char 문자로 인식하여 입력 받는다.

#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char ch;

	while (cin.get(ch))
		cout << ch;

	return 0;
}
💎입력💎
Hello World

💎출력💎
Hello World
  • 공백도 잘 출력 된 것을 볼 수 있다.
#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[5];

	cin.get(buf, 5);
	cout << buf << endl;

	cin.get(buf, 5);
	cout << buf << endl;	

	return 0;
}
💎입력💎
Hello, World!!!

💎출력💎
Hell
o, W
  • cin.get(buf, 5)
    • 인수를 2 개 받으면
      • buf 에 입력받되 최대 4 글자까지만 받기. (런타임 에러 방지)
    • 공백까지 잘 받을 수 있다.
      • 콘솔창에 Hello, World!!! 입력
      • 4글자를 받아 buf에 대입한다. buf = “Hell\0”
      • 스트림 버퍼에 남아있는 4글자를 buf에 공백까지 포함해서 대입한다. buf = “o, W\0”


cin.gcount

cin.gcount()\0을 제외하고 총 몇 글자를 읽어 들였는지를 세고 리턴한다.

#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[5];

	cin.get(buf, 5);
	cout << cin.gcount() << " " << buf << endl;

	cin.get(buf, 5);
	cout << cin.gcount() << " " << buf << endl;

	return 0;
}
💎입력💎
Hello, World!!!

💎출력💎
4 Hell
4 o, W


cin.getline

cin.getline은 엔터(개행 문자) 전까지 한 줄을 싹 다 읽는다. 그러므로 공백도 포함하여 읽어들인다.

  • 줄 바꿈 문자 \n 까지 읽어들이기 때문에 \n을 스트림 버퍼에 남기지 않는다.
  • \n은 스트림 버퍼로부터 읽어들인 후 버린다.
#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[5];

	cin.getline(buf, 5);
	cout << cin.gcount() << " " << buf << endl;

	cin.getline(buf, 5);
	cout << cin.gcount() << " " << buf << endl;

	return 0;
}
💎입력💎
Hello, World!!!

💎출력💎
4 Hell
0
  • 콘솔창에 사용자가 입력한 한 줄을 싹 다 바로 읽어들이는데 4글자만 입력.
  • 애초에 한번에 한 줄을 다 읽어들이기 때문에 스트림 버퍼에 남아있는게 없다.
    • 따라서 get(buf, 5) 하면 4글자를 제외한 나머지 글자들은 스트림 버퍼에 아직 남아 있기 때문에 거기서 또 가져와 읽어들였었지만
    • getline(buf, 5)는 4글자를 제외한 나머지 글자들 또한 스트림 버퍼에서 비워진다.
      • 두번째 getline에선 gcount 값으로 0 이 출력되고 buf에 아무것도 입력되지 않은 것을 확인할 수 있다.
        • 콘솔 입력을 새로 받지 않는다. Hello, World!! 에서 Hell 만 받았기 때문에.
        • 버퍼에 아무것도 없기 때문에 읽어 들일 것이 없어 buf에 빈 문자열이 대입된다.
          • 첫번째 getline에서 한 줄 통째로 읽어들여 버퍼에 남은게 없기 떄문
          • buf = “\0”
      • 첫번째 getline에서 이미 한 줄 전부를 읽어들여서 실제론 4 글자만 저장 했더라도 스트림 버퍼에 남아있는게 없기 때문에!
#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[15];

	cin.getline(buf, 15);
	cout << cin.gcount() << " " << buf << endl;

	cin.getline(buf, 15);
	cout << cin.gcount() << " " << buf << endl;

	return 0;
}
💎입력💎
Hello, World!!
hello

💎출력💎
15 Hello, World!!
6 hello
  • 첫번째 cin.getline(buf, 15);
    • 한 줄을 버퍼에 남기지 않고 싹 읽어들인 후 \0을 포함한 15글자 전부 buf에 대입.
    • buf = “Hello. World!!\0”
  • 두번째 cin.getline(buf, 15);
    • 콘솔 입력을 또 받는다.(커서 깜빡깜빡) Hello, World!! 이 전부 입력으로 잘 들어갔기 때문에 새로운 콘솔 입력을 또 받는 것이다.
    • 새로운 콘솔 입력으로 buf에 들어가게 될 것.


get과 getline의 차이

#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[100];

	cin.get(buf, 100);
	cout << cin.gcount() << " " << buf << endl;

	cin.getline(buf, 100);
	cout << cin.gcount() << " " << buf << endl;

	return 0;
}
💎입력💎
Hello

💎출력💎
5 Hello
1
  • cin.get(buf, 100)
    • get
      • 공백까지 입력받지만 한 줄단위로 받진 않기 때문에 남은건 버퍼에 남긴다.
      • ‘엔터’ 줄바꿈 문자는 읽지 않고 스트림 버퍼에 남긴다.
    • Hello 5글를 읽어들인 후 엔터는 버퍼에 남긴다
  • cin.getline(buf, 100)
    • getline
      • 한 줄 단위로 받기 떄문에 버퍼에 남기지 않고 싹 읽는다.
      • ‘엔터’ 줄바꿈 글자도 읽는다 (스트림 버퍼에 남기지 않음)
      • 1이 출력된건 get이 버퍼에 남겨둔 엔터 줄바꿈 글자를 getline이 읽었기 때문


cin.ignore()

cin.ignore(N)N개의 문자를 입력시 무시한다. 디폴트로는 1글자 무시.

#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[1024];

	cin.ignore();
    cin >> buf;
    cout << buf << endl;

	return 0;
}
💎입력💎
Hello

💎출력💎
ello
  • 한글자가 무시되어 H가 무시되고 ellobuf에 들어간 것을 확인할 수 있다.
#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[1024];

	cin.ignore(3);
    cin >> buf;
    cout << buf << endl;

	return 0;
}
💎입력💎
Hello

💎출력💎
ello
  • 3글자가 무시되어 Hel가 무시되고 lobuf에 들어간 것을 확인할 수 있다.


cin.peek

cin.peek을 사용하면 스트림 버퍼 속을 들여다 보기만 하고 실제로 스트림 버퍼로부터 꺼내진 않는다.

  • 1개의 문자를 정수의 형태로 들여다 보기 때문에 (char)로 문자 형변환을 해주어야 한다.
#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[1024];

    cout << (char)cin.peek() << endl;
    cin >> buf;
    cout << buf << endl;

	return 0;
}
💎입력💎
Hello

💎출력💎
H
Hello
  • 스트림 버퍼에 담겨 있는 “Hello”에서 첫문자인 ‘H’를 정수의 형태로 들여다 본다.
    • (char) 형변환 안했으면 H의 아스키 코드인 72를 출력했을 것이다.
  • 들여다 보기만 하고 스트림버퍼에서 꺼내진 않았기 때문에 cout << buf << endl; 하더라도 H 까지 붙어 그대로 Hello가 출력된다.
    • 버퍼에서 꺼냈었다면 ello가 출력 됐었을 것이다.


cin.unget

cin.unget 마지막에 읽은 것을 버퍼에 도로 넣는다.

#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[1024];

    cin >> buf;
    cout << buf << endl;

    cin.unget();

    cin >> buf;
    cout << buf << endl;

	return 0;
}
💎입력💎
Hello

💎출력💎
Hello
o
  • 첫번째 cin에서 마지막으로 읽어들인 문자 o를 다시 버퍼에 도로 넣었기 때문에 두번째 cin에서 이 o를 스트림버퍼로부터 읽어들여 buf에 대입하게 된 것이다.


cin.putback(‘A’)

cin.putback('A') A 문자를 다시 도로 버퍼에 넣는다. unget과 비슷하되 원하는 문자를 버퍼에 도로 넣음

#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	char buf[1024];

    cin >> buf;
    cout << buf << endl;

    cin.putback('A');

    cin >> buf;
    cout << buf << endl;

	return 0;
}
💎입력💎
Hello
Hello

💎출력💎
A
  • 문자 A를 다시 버퍼에 도로 넣었기 때문에 두번째 cin에서 이 A를 스트림버퍼로부터 읽어들여 buf에 대입하게 된 것이다.


🔔 동적 버퍼(string)에 입력하기

  • std::stringchar[]와 같이 크기가 정해져 있는 정적 버퍼가 아닌, vector 처럼 실행 중에 크기가 알맞게 변하는 동적 버퍼를 가진다.

stringstd::getline Vs. iostreamcinstd::cin.getline

  • stringstd::getline
    • std::getline (입력받을파일, 어느string에받을지)
      • std::getline(cin, buf)
        • 콘솔로 string buf에 입력 한다.
  • std::cin.getline
    • std::cin.getline(받을 char 배열, 몇 글자받을지)
      • cin.getline(buf, 100)
#include <iostream>
#include <string>
#include <iomanip>	

using namespace std;

int main()   
{
	string buf;

	getline(cin, buf);   // string 의 getline 이다.
	cout << cin.gcount() << " " << buf << endl;

	return 0;
}
💎입력💎
Hello, World

💎출력💎
0 Hello, World
  • cin.gcount() 값으로 0 이 나오는 이유는 cin.getline으로 입력 받은건 아니기 때문에.


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

댓글 남기기