상세 컨텐츠

본문 제목

[TIL] 3 - 2. 표준 입출력 함수 - scanf( )

언어/C

by 민:하 2022. 3. 3. 23:33

본문

 

1. scanf( ) 함수의 형식

  • scanf("입력양식", 입력대상처의 시작주소);    → ex) scanf("%d", &a);
  • scanf( )함수의 type : int (입력에 성공한 출력한 문자열의 바이트)

 

< 입력양식의 구성요소 >

① 형식변환문자 (%d)

② 구분자 : 여러 개의 데이터 입력 시 데이터 사이를 구분하기 위한 문자 → space, tab, enter

    (단, 마지막 형식변환문자 뒤에는 구분자를 쓰지 않는다.)

 

< 입력 대상처의 시작주소 >

반드시 주소를 지정 (주소 추출 연산자 & 사용)

(단, 배열명의 경우는 배열명 자신이 그 배열의 시작주소를 의미하기 때문에 주소 추출 연산자 사용하지 않음)

 

< 주소 추출 연산자 &를 사용하지 않는다면 >

#include <stdio.h>
int main() {
    int a;
    scanf("%d", a);
    return 0;
}
  • a는 초기화를 하지 않았으므로 77같이 쓰레기 값이 저장되어 있는 상태
  • &a가 아닌 a를 입력했으므로 a에 저장된 값인 77번지에 %d에 올 값을 저장한 것으로 이해
  • 미예약 영역에 데이터를 입력하려고 시도하여 오류 발생

 

< 미예약 영역 vs 예약 영역 >

  • 미예약 영역 : Read는 일부 가능, Write는 무조건 불가능
  • 예약 영역 : Read와 Write 전부 가능
  • MMU가 RAM을 감시하고 있다가 미예약 영역을 건드리고 있는 것을 발견하면 OS에 알리고 OS는 process kill하여 Runtime Error가 발생한다.

2. scanf( ) 함수의 버퍼

< stdin buffer (입력 버퍼) >

  • queue 구조 = FIFO
  • start up code가 할당 = main 실행 이전에 잡아둠
  • char형 배열이라고 생각하면 편함 (사이즈는 넉넉)
  • scanf 함수때문에 실행 = scanf의 역할이 stdin buffer에서 가져오는 것

① scanf는 데이터를 가져가려고 stdin buffer를 확인

② 비어있는 stdin buffer는 줄 수 있는 게 없음

③ stdin buffer가 모니터의 커서를 보여주어 입력값을 달라고 요구

④ 사용자가 적절한 값 입력

⑤ scanf는 stdin buffer에 있는 값을 가져가 저장

 

#include <stdio.h>
int main() {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    return 0;
}

① 사용자가 구분자와 함께 10, 20, 30을 입력

② 각각의 값이 하나의 문자로 stdin buffer에 저장 (숫자도 ASCII 코드 값이 들어감)

③ scanf의 첫번째 %d가 구분자(여기서는 공백)전까지 데이터를 꺼내 숫자로 변환시켜 저장

      %d : '0' ~ '9', '+', '-' 만 가져갈 수 있음.

      %f : '0' ~ '9', '+', '-', '.'만 가져갈 수 있음.

④ 두번째 %d는 보자마자 구분자(공백)를 만남 → 여기서는 공백을 buffer에서 날려버리고 다음부터 데이터를 읽어 저장

⑤ ④와 같은 방식으로 데이터 저장

모든 입력이 끝나면 개행문자만 buffer에 남게 된다.

 

< buffer 입력함수 >

  • scanf( ), getchar( ), gets( ), ....
  • stdin buffer(입력버퍼) 사용

 

< 공백 있는 문자열 입력받기 >

  • fgets(char 배열명, 최대입력문자수, stdin)

 

< buffer 입력 실패 >

  • 읽기 실패 시 값을 읽어오지 못해 기존값 유지 (= 쓰레기 값 유지)
  • 읽기 실패한 경우 뒤에 있는 형식변환문자는 읽기를 시도하지도 않음 (계속 쭉 오류) → 입력버퍼 clear하기

 

< 입력버퍼 clear 방법 >

void myflush() {
    char ch;
    ch = getchar();
    while(ch != '\n') { ch = getchar(); }
    return 0;
}

scanf( )의 변경자

변경자 의  미
* 값을 입력은 받으나 그 값을 변수에 저장하지 않는다    ex) %*d
10진수 최대필드 폭, 문자열 입력 시 첫번째 여백 문자를 만나거나
최대 필드 폭에 도달하면 입력을 중지한다    ex) %5s, %3d
h, l, ll 또는 L short, long, long long, long double형으로 입력 받을 때 사용
ex) %hd, %ld, %lld, %lf, %Lf

< 예시 >

ex) scanf ("%d %*d %d", &a, &b);  // 10 20 30 입력 : 10은 첫번째 %d로, 20은 저장x, 30은 두번째 %d로 저장

ex) scanf("%5s", str);  // strawberry 입력 : straw까지 저장

 

< 사용자 지정 구분자 >

사용자가 직접 구분자를 정해서 사용하고 싶을 때 사용

#include <stdio.h>
int main() {
    int a, b, c;
    int res;
    res = scanf("%d:%d:%d", &a, &b, %c);
    printf("res = %d, a = %d, b = %d, c = %d\n", res, a, b, c);
    return 0;
}
  • 입력시 10  32  50 (enter) : 오동작
  • 입력시 10 : 32 : 50 (enter) : 올바른 입력

 

< EOF >

  • EOF = End of File (파일의 끝 표시)
  • stdio 헤더파일에 EOF 매크로 상수 선언 → #define EOF (-1)
  • 입력시 Ctrl + Z (^Z) 입력시 입력이 실패되기 때문에 EOF 리턴
  • 단, EOF 입력 시 반드시 새로운 줄 선두에 입력해야 함.
#include <stdio.h>
int main() {
    char ch;
    while ((ch = getchar()) != EOF) {
        if(ch >= 'a' && ch <= 'z') { ch -= 'a' - 'A'; }
        else if (ch >= 'A' && ch <= 'Z') { ch += 'a' - 'A'; }
        putchar(ch);
    }
    return 0;
}

 

관련글 더보기

댓글 영역