[C언어]#5 입력받기 scanf, scanf_s 문
드디어 외울게 많은 힘든 파트들이 끝났네요
이번에 배울것은 입력을 받아서 저장할수 있게해주는 함수 scanf, scanf_s 를 배워볼건데요.
scanf는 Visual 2015때 저가 공부했는데 scanf_s를 쓰는걸 마이크로소프트에서 추진할때였습니다.
확인해보니 2017에서는 scanf가 특별한 설정이 없는이상 쓰지 오류가 뜨면서 쓰지 못하는것 같네요!
scanf와 scanf_s와의 차이 점은 별거없습니다. scanf_s에 값을 하나더 적어줘야 하는건데요.
바로 "나는 여기에 x만큼 적어서 저장하겠어! 그이상은 필요없어!" 라고 미리 말을 해주는겁니다.
scanf는 이제 쓸일은 없을것 같지만 그래도 일단은 사용법에 대해 적어 놓겠습니다.(별차이 없습니다.)
scanf_s를 쓰는이유에 대해 더 자세히 알고 싶으신분을 보시면 되겠습니다.
https://msdn.microsoft.com/ko-kr/library/w40768et(v=vs.110).aspx
요약: 오버플로우 공격을 방지하기 위해서
1. scanf 사용법(scanf_s 을 사용해주세요!)
1
2
3
4
5
6
7
8
9
10
11
|
#include <stdio.h>
#define _CRT_SECUER_NO_WARNINGS
int main()
{
int a;
scanf("%d". &a);//정수형으로 입력받을거야!
//& 꼭 써주세요! 자주 실수합니다.
return 0;
}
|
변수를 선언하고 그 변수에 입력을 받는 방식인데요.
scanf("입력받을 형태", &변수이름); 을 써주시면 입력받을수 있습니다.
**scanf하나만쓰고 여러개를 입력받고 싶다면 scanf("%d %d",&a,&b); 이런식으로 써주실수 있습니다.
이걸 쓰고싶다면 #define _CRT_NO_SECURE_WARNINGS 을 #include <stdio.h> 밑에 써주셔야합니다.
컴파일러가 경고를 보내는데 경고하지 말라고 말해주는 행위이죠!
참고로 Visual 2015유저시면 _CRT_NO_SECURE_WARNINGS옆에 세미콜론(;)을 쓰시면 오류로 컴파일러 꺼집니다.
2.scanf_s 사용법
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <stdio.h>
int main()
{
int a;
scanf_s("%d", &a);
printf("%d\n", a);
return 0;
}
|
cs |
scanf랑 별차이가 없습니다. scanf_s의 차별점은 오버플로우 공격을 방지 위해서라고 했었습니다.
int, float, double 같은 자료형은 자료형 크기가 일정하기 때문에 자료형을 입력받는데 문제가 없지만,
char, char[]형태인 문자, 문자열에서는 입력받을 크기를 반드시 뒤에 입력해주어야 합니다.
scanf_s("%s", 문자열변수명, sizeof(문자열변수명)); 을 써주시면 입력받을수 있습니다.
이전에 sizeof를 한번 써본적이 있는데요. 이녀석은 크기를 측정해주는 녀석이였죠!
sizeof(변수명) 입력해주셔서 입력받을 크기를 입력해주시면 되겠습니다.
scanf_s하나만 쓰고 여러변수를 입력받고 싶다면 scanf_s("%d %s %d %c", &a, b, sizeof(b), &c, &d, sizeof(d)); 이런식으로 써주면 되겠죠?
예제1
정수입력 받아서 출력해보기.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <stdio.h>
int main()
{
int a;
printf("숫자를 입력해주세요 : ");
scanf_s("%d", &a);
printf("당신이 입력한 값은 %d 입니다.\n", a);
return 0;
}
|
cmd창에 숫자를 입력하니 입력한 값이 출력이 되네요! 신기하죠?
예제2
정수, 실수, 문자 입력받아서 출력받아 보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <stdio.h>
int main()
{
int a;
double b;
char c;
printf("정수입력 : ");
scanf_s("%d", &a);
printf("실수입력 : ");
scanf_s("%lf", &b);//실수형은 %lf 써주셔야됩니다. %f아니에요!
printf("문자입력 : ");
scanf_s("%c", &c, sizeof(c));//어라 입력도 안했는데 넘어가네?!
printf("내가 좋아하는 정수는 %d 이다 \n", a);
printf("내가 좋아하는 실수는 %f 이다 \n", b);
printf("내가 좋아하는 학점은 %c 이다 \n", c);
return 0;
}
|
어라? 내가 좋아하는 학점 A를 입력하려 했는데 입력하지도 않고 넘어가버립니다!! 왜그럴까요?
문제는 바로 엔터 혹은 스페이스바의 값이 %c에 입력받아져서 그런건데요.
제가 1004.1004를 입력하고 엔터를 누를때 1004.1004와 엔터가 각각 저장되버리게 된겁니다!
악!! 그럼 이걸 어떻게 해결하냐고요? 지금 수준으로 완벽한 해결법을 제시해드리긴 어렵고요.
문자입력을 맨처음 받을때만 쓸수 있는방법입니다. 문자입력을 제일 먼저 해주는겁니다.
저 예제의 경우 정수->실수->문자 순으로 입력받았는데 문자->정수->실수 순으로 입력받을수 있게 수정해주시면 잘될겁니다!(13,14줄을 위로 올려주면되겠죠?)
또 다른 방법은 fflush()를 사용하는 방법입니다. 입력버퍼를 지워주는 아이인데요. 혹시 궁금하시면 인터넷에 쳐보시길 바래요.
또 다른 방법이 있는데요 바로 scanf(" %c",&a); 이렇게 %c 앞에 스페이스바로 하나를 띄워주시면 엔터버퍼를 그부분이 먹어줍니다! 초기에는 이방법이 가장 적절할것 같네요.
그리고 실수의경우 %f가 아닌 %lf를 쓰셔야된다는것도 유의해주세요!(이거 몰라서 시험 틀렸었음)
예제3
%d인 경우에도 크기를 준다면 작동할까?
#include <stdio.h>
int main()
{
int b;
char a[20], c[20];
scanf_s("%s %d %s", a, sizeof(a), &b, sizeof(b), c, sizeof(c));
printf("%s %d %s\n", a, b, c);
return 0;
}
이 예제는 일부로 정수형 변수 b의 크기도 scanf_s를 사용할 때 예시입니다.
위와 같이 에러코드를 내면서 작동이 하지않습니다.
그럼 정수형만 입력받을때 b의 크기를 인자로 던져주면 어떻게 될까요?
에러가 나지 않고 정상작동 합니다. 왜 그런걸까요?
scanf_s("%s %d %s", a, sizeof(a), &b, sizeof(b), c, sizeof(c));
위 코드에서 제가 입력한 "안녕 1234 잘가"를 읽는데 있어서
먼저 맨처음에 %s와 a, sizeof(a)가 안녕을 읽는데 사용됩니다.
두번째로 %d와 &b가 1234를 읽는데 사용되는데요.
세번째로는 %s와 sizeof(b), c가 잘가를 읽는데 사용 됩니다.
세번째에서 미스매치가 발생되게 되면서 에러가 나게 되는것이죠
scanf("%d", &b, sizeof(b));
위 코드의 경우 "1234"를 읽는데 있어서
%d와 &b가 1234를 읽는데 사용됩니다.
더이상 읽을게 없기 때문에 나머지 인자인 sizeof(b)에 대한 처리는 하지않고 scanf가 종료가 되게됩니다.
따라서 에러가 나지 않게 되는것이죠.
응용문제
두 정수를 입력받아 '+' , '*' , '-' , '/' , '%' 의 계산결과가 출력되게 해주세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <stdio.h>
int main()
{
int a, b;
printf("두 정수를 입력 해주세요\n");
scanf_s("%d", &a);
scanf_s("%d", &b);
printf("%d + %d= %d\n", a, b, (a + b));
printf("%d - %d= %d\n", a, b, (a - b));
printf("%d * %d= %d\n", a, b, (a * b));
printf("%d / %d= %d\n", a, b, (a / b));
printf("%d %% %d= %d\n", a, b, (a % b));
return 0;
}
|