프로그래밍/C

7.4 형식화된 입력:scanf(Formatted Input - Scanf)

피노리코 2014. 11. 9. 01:12

함수 scanf는 printf와 사용방법에 유사한 함수인데,출력함수가 아니고 입력함수이다.


int scanf(char *format,...)


scanf는 표준 입력으로 부터 문자를 읽어 들여서 format의 변환 형식에 따라 그들을 해석하고 매개변수에 결과를 저장한다.

변환형식 지정 매개변수가 아닌 보통의 매개변수는 입력되는 문자가 위치해야 하는 곳을 가리키는 포인터여야한다. scanf는 변환형식 지정 문자열을 다 사용했거나 형식에 맞지않게 입력이 들어왔을 때 멈추게된다. scanf는 성공리에 대응된 것들의 개수와 할당된입력 항목의 개수를 리턴한다.리턴값은 항목이 몇개나 발견되었는지를 알아내는데 사용된다.파일의 끝에 가면 EOF를 리턴한다. EOF는 다음 입력 문자가 변환형식 지정 문자열과 대응 되지 않는 입력이 들어왔을떄 나타나는 0과는 다르다. 표준 입력 대신 문자열로부터 읽어들이는 함수 sscanf도 있다.


int sscanf(char *string,char *format,arg1,arg2, ...)


이것은 format에 있는 형식을 따라 문자열을 조사하고 arg1,arg2등에 결과 값을 저장한다. 이들 매개변수는 포인터여야 한다. 변환 형식을 나타내는 문자열은 입력결과의 해석을 위해 사용된다. 변환형식 지정 문자열은 다음 항목을 포함한다.


-공백 또는 탭 이는 부시 된다.

-%를 제외한 보통 문자들

-%변환문자,변환이 없음을 알리는 * ,최대 자릿수를 표시하는 숫자,short 이냐 long이냐를 정해주는 h,l,L


문자

입력DATA:매개변수 TYPE

 d

 10진수 정수 :INT *

 i

 정수:INT *.정수는 8진수(숫자 앞에 0)또는 16진수(앞에 0x,0X)가 될 수도 있다

 o

 8진수 정수(앞에 0이 있거나 없는:int *

 u

 부호 없는 10진수 정수:unsigned int *

 x

 16진수(앞에 0x,0X가 있거나 없는):int *

 c

 문자열:char *.white space의 뛰어넘기는 하지 않는다. 다음의 non-white space 문자를 읽어 들이려면 %1s를 사용한다

 s

 문자열:char *,문자열을 위한 충분한 크기의 문자 배열을 가리킨다.문자열 끝에는 '\0'을 붙인다.

 e,f,g

 부호 10진포인터(decinal point)와 지수를 선택적으로 가질 수있는 부동소수점수:float *

 %

 문자 %:지정은 이루어지지 않는다.


보통 결과는 대응되는 매개변수가 가리키는 변수에 저장되지만 ,반환 형식 *문자에 의해 지정된다면 입력 항목은 건너 뛰게 된다. 즉 지정은 이루어지지 않는다.입력필드는 non-white space문자(공백,탭 등이 아닌 문자)의 문자열로 정의되고 다음의 white space문자까지 또는 필드 너비가 명시 되었을 경우에는 필드 폭까지 필드가 된다. 행바꿈 문자는 white-space이므로 scanf입력을 찾기 위해 행의 경계를 뛰어넘어 읽을 것 임을 의미한다 [white space문자는 공백 탭 행바꿈(newline),캐리지 리턴(carriage return)수직 탭,formfeed이다] 변환 문자는 입력 필드를 읽는 형식을 지정한다. C에서 매개변수 전달은 call by value이므로 매개변수는 반드시 포인터 여야 한다

변환운자 d,i,o,u와 x의 앞에는 h나 l을 붙일수 있는데 h는 short을 의미하고 l long을 의미한다 마찬가지로 변환문자 e,f와 g 앞에 매개 l을 붙여 double임을 나타낼 수 있다. 첫번째 예로 제 4장의 초보적인 계산기 프로그램을 scanf를 사용하도록 다시 작성한 것을 보인다


#include <stdio.h>


int main() /* rudimentary calculator */

{

    double sum, v;

    sum = 0;

    while (scanf("%lf", &v) == 1)

        printf("\t%.2f\n", sum += v); return 0;

}


다음과 같은 형태의 날짜 데이터를 읽기 원한다면


25 DEC 1988


scanf 명령문을 다음과 같이 쓴다.


int day, year;

char monthname[20];

scanf("%d %s %d", &day, monthname, &year)


&는 monthname에 사용하지 않는다 왜냐하면 배열 이름은 그 자체가 포인터 이기 때문이다. 변환형식 지정 문자열에 보통의 문자가 올 수도 있는데 ,입력에서 같은 문자가 들어와야 한다 그러므로 scanf 함수로 날짜를 mm/dd/yy 형태로 읽을수 있다.


int day, month, year;

scanf("%d/%d/%d", &month, &day, &year);


scanf는 변환형식 지정 문자열에 있는 공백과 탭을 무시한다. 또 scanf는 white space(공백,탭,newline)를 무시한다 여러가지 형태의 입력을 읽기 위해서는 한번에 한줄을 모두 읽는 것이 가장 좋다 다음에 sscanf에 의해 분해해서 읽어 들인다. 예를들어 위의 두 형태중 어떤 날짜 형태라도 읽을수 있는것을 원한다면 다음과 같이 쓸수 있다


while (getline(line, sizeof(line)) > 0)

{

    if (sscanf(line, "%d %s %d", &day, monthname, &year) == 3)

        printf("valid: %s\n", line); /* 25 Dec 1988 form */

    else if (sscanf(line, "%d/%d/%d", &month, &day, &year) == 3)

        printf("valid: %s\n", line); /* mm/dd/yy form */

    else

        printf("invalid: %s\n", line); /* invalid form */

}


scanf 함수로 읽은 다음 다른 입력 함수를 호출하면 그 함수는 scanf가 읽은 바로 다음부터 읽게 된다.

한번더 강조하는데 scanf와 sscanf의 매개변수는 반드시 포인터여야 한다. 즉


scanf("%d",n);


가 아니라


scanf("%d",&n);


로 쓰는 것이다 . 이실수는 컴파일 할 때도 일반적으로 발견되지 않는다.


예제 7-4 앞절에서의 minprint와 비슷한 scanf의 기본적인 프로그램을 작성하라.


예제 7-5 4.3절의 계산기 프로그램을 scanf,sscanf를 사용하여 다시 작성하라.