[CodeEater와 제로부터 시작하는 C언어] 5장 - 입력과 출력
일반적으로 입력은 우리가 컴퓨터에게 명령어를 줄 수 있는 모든 방식을 말한다.
전통적으로는 키보드, 마우스, 마이크 등이 있고 그 외에도 아주 많다.
가령 카메라, 열전도 센서, 광센서 등도 입력장치라 할 수 있다.
그리고 출력은 우리가 컴퓨터에게 정보를 받을 수 있다면 모두 출력이라고 할 수 있다.
프린터, 플로터, 3D프린터 등도 당연히 출력장치 이며
스피커, 헤드셋등의 사운드 장치, 게임기의 진동등도 당연히 출력장치,
흔히 표시장치라 말하는 모니터 역시 출력장치이다.
물론 우리는 모든 종류의 입력과 출력을 다룰 순 없다.
엄청나게 복잡하고 많은 종류가 있기 때문이다.
그래서 우리는 기본적으로 입출력은 콘솔의 입출력에 대해서 다룬다.
당연히 입력은 키보드로, 출력은 모니터로 하게된다.
그러면 콘솔이라는게 뭔가?
시스템을 물리적으로 조작할 수 있는 체계 - 어떠한 전공 책
저렇게 말하면 알아듣기 힘드니 쉽게 말해서 검은 화면에서 만지작 거린다고 생각하면 된다.
이제 그러면 우리가 지겹도록 봐왔던 출력 예제를 보도록하자.
#include <stdio.h>
int main() {
int num = 28;
printf("내 나이 %d살!\n", num);
return 0;
}
추가적인 설명이 필요할까?
너무 많이 봐서 지겨운 예시이다.
그러면 이러한 지겨운 예제는 넘어가고 입력에 대해서 알아보도록 하자.
#include <stdio.h>
#pragma warning(disable:4996)
int main() {
int num;
scanf("%d", &num);
printf("내 나이 %d살!\n", num);
return 0;
}
앞으로 지겹게 볼 코드가 하나 더 추가되었다.
입력을 할때 눈여겨 볼 것은 3가지가 있다.
1. scanf라는 완전 새로운 함수를 사용한다는 것
2. 변수에 &를 사용한다는 것이다
3. 상단에 #pragma~로 시작되는 무언가가 존재한다는 것
여기서 하나씩 보도록 해보자.
scanf는 입력을 받는 함수이다.
정말 역사가 유려하게 깊은 함수이지만 살짝 문제점이 있다.
&는 뭔지는 아직 알 필요가 없다.
다만 아직은 간단하게 scanf를 사용할때는 &를 쓴다고 생각하면 된다.
추후에는 &를 쓰지 않는 예시도 나오지만 그건 그때가서 알아보도록 하자.
마지막으로 pragma에 대해서 간략하게 설명하자면 저건 윈도우에서만 사용하는건데
전처리 명령어...인데 이렇게 이야기하면 좀 길고
간단히 말하면 scanf를 일반적으로는 사용할 수 없지만 강제로 사용하겠어!!
라고 생각하면된다.
scanf는 사실 보안문제가 있는 함수라서 사용자가 꽤 신경써줘야하는 함수인데
그래서 윈도우에서는 일반적으로느 사용못하게 막는다.
그걸 해제하는 방법이 저 pragma이다.
다만 리눅스나 맥에서는 저 구문이 없어도 동작을 잘한다.
&num을 사용해서 지정하게 되면 값을 입력받는 상태가 된다.
scanf를 맞닥트리게 되면 프로그램은 종료되지 않고 사용자의 입력을 무한정 기다린다.
입력의 끝은 엔터로 판단하는데 중요한건 엔터를 친다고 끝난게 아니라,
값을 입력하고 엔터를 쳐야 입력의 종료로 인식한다.
여튼 허점이 많기 때문에 입력할때도 조심히 사용해야한다.
입력이 끝나고나면 초기화 되지 않았던 num이 내가 입력한 값으로 초기화 된다.
여기서 scanf를 사용할때도 우리는 서식 지정자를 사용했다.
scanf의 서식지정자는 어떤의미에서는 printf의 서식지정자보다 훨씬 중요하다.
그 이유는 출력을 잘못한다고 변수가 바뀌지 않지만
scanf의 경우 입력을 잘못하면 변수 자체가 바뀌기 때문이다.
그래서 입력될값의 서식지정자를 명확히 해야한다.
아직 문자를 배우진 않았지만 문자를 입력할때도 서식을 정확히 지켜줘야한다.
#include <stdio.h>
#pragma warning(disable:4996)
int main() {
char ch;
scanf("%c", &ch);
printf("내 형액형 %c형!\n", ch);
return 0;
}
문자에 대해서 아직 우리는 배우지 않았지만 그래도 맛보기로 보도록하자.
사용하는 방식은 똑같다.
scanf에서 주의해야할 점이 있다.
바로 입력 타입을 맞게 해줘야한다는 점이다.
입력 타입을 맞춰서 입력하지 않으면 프로그램이 원하지 않게 동작하게 된다.
이건 버그나 에러가 아니라 scanf의 동작로직 때문에 어쩔수 없는 것이다.
설명하려면 아주아주아주 길고 어렵기 때문에 타입을 지켜야한다는것만 알아두자.
그 이유는 몇가지 예제를 통해서 실험할 수 있다.
정수를 받을려고 했지만 문자를 받는 경우
#include <stdio.h>
#pragma warning(disable:4996)
int main() {
int num;
printf("입력 하세요 : ");
scanf("%d", &num);
printf("뭐가 출력이 될까 : %d\n", num);
return 0;
}
가령 위와 같은 코드가 존재한다고 하자.
그러면 우리는 num에 입력한 숫자를 출력하게 될 것이다.
만약 정수를 받으려고 했지만 문자를 받게되면 어떻게 될까?
결과는 받아지지 않는다이다.
비주얼 스튜디오에어서(윈도우)는 변수가 자동으로 0으로 초기화되는데
사실은 초기화 자체를 실행하지 않는다고 생각하면된다.
정수를 받을려고 했지만 실수를 받는 경우
#include <stdio.h>
#pragma warning(disable:4996)
int main() {
int num;
printf("입력 하세요 : ");
scanf("%d", &num);
printf("뭐가 출력이 될까 : %d\n", num);
printf("입력 하세요 : ");
scanf("%d", &num);
printf("뭐가 출력이 될까 : %d\n", num);
return 0;
}
가령 위와 같은 코드가 있다고 가정하자.
일반적으로 생각하면 입력 한번 출력 한번 입력 한번 출력 한번일 것이다.
그리고 뭐 틀린말은 아니다.
하지만 이 때 실수가 들어가는 경우 어떻게 될까?
보면알겠지만 입력은 단 한번만 받고,
출력은 계속 된다. 그리고 입력을 추가적으로 받지 않는다.
이 이유를 설명... 하고 싶긴한데 사실 공수에 비해서 얻는게 별로 없다.
그리고 이 때까지 배우지 않은 개념을 들어서 설명해야하기 때문에 조금 어렵다.
그래서 일단은 이 궁금증을 띄어 넘고 6장으로 넘어가는 것을 권한다.
다만 여기에 대해서 심도깊은 이해를 필요로 하는 사람이 존재하기에
부득이 하게 5-1장을 만들어서 설명하려고하니 이해가 필요한 사람들은 봐주기를 바란다.
C언어는 오래되다보니 scanf를 아주 오랜기간동안 써왔다.
그러나 scanf는 보안 문제가 있다고 이야기하였다.
사실 문자나 정수등의 변수들을 사용할때는 scanf_s가 별 의미가 없다.
문자열을 사용할 때나 의미가 있다.
C언어 표준에서 보면 2011년에 포함된 표준이라는걸 알 수 있다.
즉 따끈따끈한 녀석이다. (그런데 지금은 2019...)
#include <stdio.h>
int main() {
int num;
char ch[100];
printf("입력 하세요 : ");
scanf_s("%d",&num);
printf("%d 이지롱!\n",num);
return 0;
}
사용예제를 보아도 scanf랑 똑같다.
다만 사라진 점이 pragma를 더이상 쓰지 않아도 된다는 점이다.
그 이유는 scanf가 위험한 함수라고 쓰지말라고 했는데 그걸 안써서 이제 에러가 안나는 것이다.
그리고 현재는 C언어의 표준으로 지정된 상태이므로 사실 scanf_s를 쓰는게 더 나을것이다.
#include <stdio.h>
int main() {
int num;
char ch[100];
printf("입력 하세요 : ");
scanf_s("%d %s",&num ,ch, sizeof(ch));
printf("%d %s\n",num, ch);
return 0;
}
scanf_s는 문자열과 함께 쓸 때 문제가 된다.
scanf와 scanf_s의 차이점은 문자열에서 크기를 넘겨주느냐 마느냐이다.
그런데 우리는 아직 문자열에 대해서 배우지 않았으므로 이는 추후에 언급하도록 하겠다.
'제로부터 시작하는 프로그래밍 > C' 카테고리의 다른 글
[CodeEater와 제로부터 시작하는 C언어] 6장 - 연산자 (0) | 2019.12.08 |
---|---|
[CodeEater와 제로부터 시작하는 C언어] 5.1장 - scanf (0) | 2019.12.03 |
[CodeEater와 제로부터 시작하는 C언어] 4.2장 - 서식 지정자 (0) | 2019.11.30 |
[CodeEater와 제로부터 시작하는 C언어] 4.1장 - 변수는 어떻게 표현되는가 (0) | 2019.11.23 |
[CodeEater와 제로부터 시작하는 C언어] 4장 - 변수와 자료형과 포맷 (0) | 2019.11.20 |