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::getline
Vs.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
으로 입력 받은건 아니기 때문에.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글남기기