C++ Chapter 18.1 : istream으로 입력받기
카테고리: Cpp
태그: Cpp Programming
인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 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객체와 어떤 변수를 인수로 받으면 입력된 데이터가 변수에 저장되게끔 오버로딩이 되어 있기 때문에- >>와 함께 사용된다.
 
- C++ 표준인 
🔔 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.h의setw함수를 사용하여 해결!
 
- 단, 이 경우 buf 크기인 10 보다 1 작은 9 글자를 넘게 입력하면 런타임 에러가 발생하게 된다. (1글자는 
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; }
 
- “abcdefghijk” 입력 후 
🔔 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 입력 후 엔터
- ch는- char문자 타입이다.
- 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에 저장된다.
- 공백은 입력되지 않는다.
 
- 1024  3.14  를 콘솔창에 입력하면 스트림 버퍼에 1024, 3.14 이렇게 들어가게 되고 공백을 기준으로 구분되어 1024는 
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”
 
 
- 인수를 2 개 받으면
        
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가 무시되고ello만buf에 들어간 것을 확인할 수 있다.
#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가 무시되고lo만buf에 들어간 것을 확인할 수 있다.
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::string은- char[]와 같이 크기가 정해져 있는 정적 버퍼가 아닌, vector 처럼 실행 중에 크기가 알맞게 변하는 동적 버퍼를 가진다.
string의std::getlineVs.iostream의cin의std::cin.getline
- string의- std::getline- std::getline (입력받을파일, 어느string에받을지)
        - std::getline(cin, buf)- 콘솔로 string buf에 입력 한다.
 
- 콘솔로 
 
 
- std::getline (입력받을파일, 어느string에받을지)
        
- std::cin.getline- std::cin.getline(받을 char 배열, 몇 글자받을지)
        - cin.getline(buf, 100)
 
 
- std::cin.getline(받을 char 배열, 몇 글자받을지)
        
#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으로 입력 받은건 아니기 때문에.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
 
      
    
댓글남기기