쉽게 풀어쓴 C 언어 Express

47
© 2012 생생생생생 All rights reserved 쉽쉽 쉽쉽쉽 C 쉽쉽 Express C Express 생 16 생 생생 생생생

description

제 16 장 파일 입출력. 쉽게 풀어쓴 C 언어 Express. C Express. 이번 장에서 학습할 내용. 입출력에 관련된 개념들과 함수들에 대하여 학습한다. 입출력 형식 스트림의 개념 파일 입출력 입출력 관련 함수. 출력 형식 지정자. 출력 형식 지정자 (format specification) 변환 지정자 (conversion specification). 문자 , 정수 , 실수 등 출력 타입 명시 ( 변환 문자 ). 출력 필드의 크기 명시. - PowerPoint PPT Presentation

Transcript of 쉽게 풀어쓴 C 언어 Express

Page 1: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

쉽게 풀어쓴 C 언어 Express쉽게 풀어쓴 C 언어 Express

C Express제 16 장 파일 입출력

Page 2: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

이번 장에서 학습할 내용

• 입출력 형식• 스트림의 개념• 파일 입출력• 입출력 관련 함수

입출력에 관련된

개념들과 함수들에 대하여

학습한다 .

Page 3: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

출력 형식 지정자· 출력 형식 지정자 (format specification)

· 변환 지정자 (conversion specification)

%[ 플래그 ][ 필드폭 ][. 정밀도 ]형식문자

정렬 방식 , 부호 출력 , 공백 문자 출력 , 소수점 , 8/16 진수 접두사 출력 등 명시

출력 필드의크기 명시

소수점 이하 자릿수 명시

문자 , 정수 , 실수 등출력 타입 명시( 변환 문자 )

Page 4: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

출력 형식 지정자

1.23e+0021.230000E+001

1.230000e+001

123.456000

Page 5: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

필드폭과 정밀도

Page 6: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

필드폭과 정밀도

Page 7: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

형식 플래그 (format flag)플래그 기능 기본 값

- 왼쪽 정렬 오른쪽 정렬

+ 항상 +/- 부호 출력(0 인 경우에도 + 부호 출력 )

음수만 - 부호 출력

0오른쪽 정렬 방식의 숫자 출력에서왼쪽 빈 부분을 공백 문자 대신 0 으로 채움 0 을 채우지 않음

space(' ') 0 이나 양수 출력에서 부호 대신 공백 출력 공백을 출력하지 않음

#8 진수 출력에서 앞에 0 출력16 진수 출력에서 앞에 0x/0X 출력 0/0x/0X 를 출력하지 않음

Page 8: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

#include <stdio.h>

int main( ) {int a, b;

printf("5 자리 정수 입력 : ");scanf("%3d %3d", &a, &b);// 최대 3 문자씩 입력printf("a = %d, b = %d\n", a,

b);        

return 0;}

5 자리 정수 입력 : 12345a = 123, b = 45

입력 형식· 필드폭을 지정하여 입력 · 8 진수 , 16 진수 입력

#include <stdio.h>

int main() {int d, o, x;

sscanf("10 10 10", "%d %o %x", &d, &o, &x);

printf("d = %d, o = %d, x = %d\n", d, o, x);        

return 0;} d = 10, o = 8, x = 16

Page 9: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

문자와 문자열 입력형식 지정자 설명

%c char 형으로 문자 입력

%s 공백 문자가 아닌 문자부터 공백 문자가 올 때까지 문자열 입력

%[…]

괄호 안에 속한 문자로 이루어진 문자열 입력괄호 안에 0-9 같이 범위 표현 허용예 ) %[_a-zA-Z] : 밑줄 문자 , 영문자예 ) %[-+0-9.eE] : 부호 (-+), 숫자 , 소수점 (.), 지수 문자(eE)

%[^…]괄호 안에 속하지 않는 문자로 이루어진 문자열 입력범위 표현 허용

scan set( 문자 집합 )

Page 10: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

문자 입력과 공백 문자

Page 11: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

예제 : 문자열 입력#include <stdio.h>

int main(void) {char c, s[80], t[80];

printf(" 공백으로 분리된 문자열 입력 : ");scanf("%s%c%s", s, &c, t);

printf(" 첫번째 문자열 =%s\n", s);printf(" 중간 공백 문자 =%c\n", c);printf(" 두번째 문자열 =%s\n", t);

return 0;}

공백으로 분리된 문자열 입력 : Hello World첫번째 문자열 =Hello중간 공백 문자 =두번째 문자열 =World

Page 12: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

예제 : 문자 집합 입력#include <stdio.h>

int main(void) {char s[80];

printf(" 문자열 입력 : ");scanf("%[abc]", s);

printf(" 입력된 문자열 = %s\n", s);

return 0;}

문자열 입력 : abacadae입력된 문자열 = abaca

Page 13: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

예제 : scanf 반환 값#include <stdio.h>

int main(void) {int x, y, z;

if (scanf("%d %d %d", &x, &y, &z) == 3)printf(" 정수들의 합 = %d\n", x + y + z);

elseprintf(" 입력 오류 \n");

return 0;}

10 20 30정수들의 합 = 60

10 20 a입력 오류

Page 14: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

scanf 사용시 주의점· 입력 값을 저장할 변수의 주소 전달

· int i; scanf("%d", &i); // OK· scanf("%d", i); // ERROR

· 배열의 이름은 배열을 가리키는 포인터· char str[80]; scanf("%s", str); //

OK· scanf("%s", &str); //

ERROR

· 충분한 공간 확보· char str[80];· scanf("%s", str);

// 입력된 문자가 80 개 이상이면 오류

· 형식 문자열 끝에 '\n' 을 사용하지 말 것· int i;· scanf("%d\n", &i);

12 ↵↵↵↵312

scanf("%d\n", &i);printf("%d\n", i);

Page 15: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

스트림의 개념· 스트림 (stream): 입력과 출력을 바이트의 흐름으로 생각하는 것

Page 16: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

스트림과 버퍼· 스트림에는 일반적으로 버퍼 (buffer) 가 사용됨

Page 17: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

FILE 과 표준 스트림· 스트림은 C 에서 FILE 구조체로 표현

· typedef struct { … } FILE; // <stdio.h>

· 표준 스트림 (standard stream) 은 자동으로 생성됨· FILE *stdin, *stdout, *stderr; // <stdio.h>

변수 스트림 기본 연결 장치

stdin 표준 입력 스트림 키보드

stdout 표준 출력 스트림 모니터 화면

stderr 표준 오류 스트림 모니터 화면

Page 18: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

입출력 함수의 분류· 사용하는 스트림에 따른 분류

· 표준 입출력 스트림을 사용하는 함수· 스트림을 구체적으로 명시해야 하는 함수

· 입출력 형식 사용 여부에 따른 분류· 입출력 형식을 사용하지 않는 함수 : unformatted I/O· 입출력 형식을 사용하는 함수 : formatted I/O

입출력 형식 표준 스트림 일반 스트림 기능

형식이 없는 입출력( 문자 / 문자열 )

getchar( ) fgetc( ), getc( )

문자 입력

putchar( ) fputc( ), putc( )

문자 출력

gets( ) fgets( ) 문자열 입력

puts( ) fputs( ) 문자열 출력

형식이 있는 입출력( 정수 , 실수 , …)

scanf( ) fscanf( ) 형식화된 입력

printf( ) fprintf ( ) 형식화된 출력

Page 19: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

파일· 파일에 저장된 데이터는 프로그램 실행이 끝나도 보존됨· C 에서 파일은 일련의 연속된 바이트

· 모든 파일 데이터는 결국 바이트들로 파일에 저장· 파일 데이터에 대한 해석은 프로그래머에게 달려 있음

· 예 : 파일의 4 개 바이트 int, float, 픽셀 , …

0x36

0x34

0x31

0x0

하나의 정수 ?하나의 실수 ?4 개의 문자 ?

Page 20: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

텍스트 파일 (text file)· 사람이 읽을 수 있는 텍스트가 들어 있는 파일

· 예 : C 프로그램 소스 파일 , 메모장 파일· 아스키 코드 , 한글 코드 , 유니코드 등을 사용하여 저장

· 라인들로 구분됨 : 운영체제에 따라 라인 끝 표지가 다름

‘W’

‘O’

‘R’

‘L’‘D’

‘\r’

‘\n’

윈도우 , MS_DOS

‘W’

‘O’

‘R’

‘L’‘D’

‘\n’

유닉스 , 리눅스‘

W’

‘O’

‘R’

‘L’‘D’

‘\r’

매킨토시

‘W’

‘O’

‘R’

‘L’‘D’

‘\n’

C 언어

Page 21: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

이진 파일 (binary file)· 사람이 직접 읽을 수는 없고 컴퓨터가 처리하기 위한 파일

· 예 : C 프로그램 실행 파일 , 사운드 파일 , 이미지 파일· 이진 데이터를 직접 저장

· 문자열로 변환하지 않고 입출력· 라인들로 구분되지 않음

텍스트 파일: 문자로 구성된 파일

#include <stdio.h>#include <stdlib.h>

int main(void){...p=(int *)malloc(100);...}

#include <stdio.h>#include <stdlib.h>

int main(void){...p=(int *)malloc(100);...}

이진 파일: 데이터로 구성된 파일

Page 22: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

파일 처리 개요· 파일 처리 순서

· FILE 구조체를 이용· FILE *: 파일 포인터 (file pointer)

파일 열기(open)

파일 읽기 / 쓰기(read/write)

파일 닫기(close)

Page 23: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

파일 열기와 닫기

· 파일 열기 함수· name: 파일 이름· mode: 파일 모드 (file mode)· 열기 실패의 경우 NULL 포인터 반환

FILE *fopen(const char *name, const char *mode);

FILE *fp;fp = fopen("test.txt", "r");if (fp == NULL) // if (!fp) printf("test.txt: open fail\n"), exit(1);…fclose(fp);

int fclose(FILE *stream);

· 파일 닫기 함수· 반환 값 : 성공 0, 실패 EOF

FILE *fp;if (!(fp = fopen("test.txt", "r"))) printf("test.txt: open fail\n"), exit(1);…fclose(fp);

Page 24: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

파일 모드모드 설명"r" 읽기 (read), 파일이 없으면 열기 실패

"w" 쓰기 (write), 파일이 없으면 새로 생성 , 이미 존재하면 기존 내용 삭제

"a" 추가 (append), 파일이 없으면 새로 생성 , 이미 존재하면 기존 내용 보존 ,항상 파일 끝에 쓰기

"r+" 수정 (update: read/write), 파일이 없으면 열기 실패"w+

" 수정 , 파일이 없으면 새로 생성 , 이미 존재하면 기존 내용 삭제

"a+" 수정 , 파일이 없으면 새로 생성 , 이미 존재하면 기존 내용 보존 ,항상 파일 끝에 쓰기

· 이진 파일이면 끝에 b 추가 "rb", "wb", "ab", "r+b", "w+b", "a+b"

· 텍스트 파일이면 끝에 t 추가 또는 생략 "r", "w", "a", "r+", "w+", "a+", "rt", "wt", "at", "r+t", "w+t", "a+t"

· 수정 모드에서 읽기쓰기 , 쓰기읽기 전환 시 ,반드시 fflush(), fseek(), fsetpos(), rewind() 중 하나를 먼저 호출해야 함

Page 25: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

파일 삭제

· 파일 삭제 함수· 반환 값 : 성공 0, 실패 0 이 아닌 값· 파일 포인터를 사용하지 않는 함수

int remove(const char *path);

if (remove("test.txt")) printf("test.txt: 삭제 실패 \n");

Page 26: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

파일 입출력 함수설명 입력 함수 출력 함수

문자 입출력 fgetc( ), getc( ) fputc( ), putc( )

문자열 입출력 fgets() fputs( )

형식화된 입출력 fscanf( ) fprintf( )

이진 데이터 입출력 fread( ) fwrite( )

크게 텍스트 입출력과

이진 데이터 입출력으로 구분할 수 있습니다 .

Page 27: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

문자 입출력int fgetc(FILE *fp);

int fputc(int c, FILE *fp);

int getc(FILE *fp);

int putc(int c, FILE *fp);

· 문자 입력· fgetc 함수 ; getc 일반적으로 매크로· 반환 값 : 성공 입력된 문자 , 실패 ( 파일 끝 , 에러 ) EOF· #define getchar( ) getc(stdin)

· 문자 출력· fputc 함수 ; putc 일반적으로 매크로· 반환 값 : 성공 출력된 문자 (c), 실패 ( 에러 ) EOF· #define putchar(c) putc((c), stdout)

Page 28: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

문자 입출력#include <stdio.h>int main(void) {

FILE *fp;

fp = fopen("sample.txt", "w");if (fp == NULL)

return printf(" 파일 열기 실패 \n"), 1;else

printf(" 파일 열기 성공 \n");

putc('a', fp); putc('b', fp); putc('c', fp);// fputc('a', fp); fputc('b', fp); fputc('c', fp);

fclose(fp);return 0;

}

파일 열기 성공

sam-ple.txtabc

 

Page 29: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

문자 입출력#include <stdio.h>int main(void) {

FILE *fp;int c;

if (!(fp = fopen("sample.txt", "r"))) return printf(" 파일 열기 실패 \n"), 1;

while ((c = getc(fp)) != EOF) // c = fgetc(fp)

putchar(c);

fclose(fp);return 0;

}

 

sam-ple.txtabc

abc

Page 30: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

문자열 입출력char *fgets(char *s, int n, FILE *fp);

int fputs(const char *s, FILE *fp);

· s 에 한 라인의 문자열 입력· 최대 n-1 문자만 입력 안전함 , 공백 문자들도 입력 , '\n' 도 저장· 반환 값 : 성공 s, 실패 ( 파일 끝 , 에러 ) NULL· char *gets(char *s): stdin 에서 입력

· 무조건 한 라인 입력 위험함· '\n' 을 읽어들이지만 저장하지는 않음

· 문자열 s 출력· 반환 값 : 성공 음수가 아닌 값 , 실패 ( 에러 ) EOF· int puts(const char *s): stdout 에 출력

· s 를 출력한 후 '\n' 출력

Page 31: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

문자열 입출력

ab cde\nab cd

char s[100];fputs(fgets(s, 6, stdin), stdout);

s ab cd\0

ab cde\nab cde\n

char s[100];fputs(fgets(s, 10, stdin), stdout);

s ab cde\n\0

ab cde\nab cde\n

char s[100];puts(gets(s));

s ab cde\0

Page 32: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

문자열 입출력#include <stdio.h>#include <stdlib.h> int main(void) {

FILE *fp1, *fp2;char file1[100], file2[100];char buffer[100];

printf(" 원본 파일 : "); scanf("%s",

file1);printf(" 복사 파일 : "); scanf("%s",

file2);if (!(fp1 = fopen(file1, "r"))) {

fprintf(stderr,"%s: 열기 실패 \n", file1);

exit(1);}if (!(fp2 = fopen(file2, "w"))) {

fprintf(stderr,"%s: 열기 실패 \n", file2);

exit(1);}

while (fgets(buffer, 100, fp1) != NULL)

fputs(buffer, fp2);

fclose(fp1); fclose(fp2); return 0;}

원본 파일 : a.txt복사 파일 : b.txt

a.txtC 프로그래밍C Programming

b.txtC 프로그래밍C Programming

Page 33: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

문자열 입출력#include <stdio.h>#include <stdlib.h>#include <string.h>

int main(void) {char *fname = "proverb.txt";FILE *fp; int line_num = 0;char line[256], word[256];

printf(" 탐색할 단어 : "); scanf("%s", word);if (!(fp = fopen(fname, "r")))

fprintf(stderr,"%s: 열기 실패 \n", fname), exit(1);

while (fgets(line, 256, fp)) {line_num++;if (strstr(line, word))

printf("%s:%d -- %s 발견 \n", fname, line_num, word);

}fclose(fp); return 0;

}

탐색할 단어 : houseproverb.txt:1 -- house 발견proverb.txt:3 -- house 발견

proverb.txtA house divided against itself cannot stand.A good man is hard to find.A house is not a home.A friend in need is a friend indeed.

Page 34: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

형식화된 입출력int fscanf(FILE *fp, const char *for-mat, ...);

FILE *fp;int i = 123;float f = 1.23F; if ((fp = fopen("sample.txt", "w"))) { fprintf(fp, "%d %.2f\n", i, f); fclose(fp);}

int fprintf(FILE *fp, const char *for-mat, ...);

FILE *fp;int i;float f; if ((fp = fopen("sample.txt", "r"))) { fscanf(fp, "%d %f", &i, &f); printf("%d %.2f", i, f); fclose(fp);}

123 1.23sample.txt123 1.23

· printf("...", …): fprintf(stdout, "...", …)

· scanf("...", …): fscanf(stdin, "...", …)

Page 35: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

예제#include <stdio.h>

typedef struct {int number;char name[20];float score;

} Student;

int main(void) {FILE *fp;char fname[100];int count = 0;float total = 0.0F;Student s;

printf(" 성적 파일 : ");

scanf("%s", fname);

if (!(fp = fopen(fname, "w")))return fprintf(stderr,"%s: 열기 실패 \n", fname), 1;

while (1) {printf(" 학번 , 이름 , 성적 입력 : ");if (scanf("%d %s %f", &s.number, s.name, &s.score) !=

3) break;fprintf(fp, "%d %s %g\n", s.number, s.name, s.score);

}fclose(fp);

if (!(fp = fopen(fname, "r")))return fprintf(stderr,"%s: 열기 실패 \n", fname), 1;

while (fscanf(fp, "%d %s %f", &s.number, s.name, &s.score) == 3)

total += s.score, count++;

printf(" 평균 = %g\n", total / count);fclose(fp);return 0;

}

성적 파일 : score.txt학 번 , 이 름 , 성 적 입 력 : 1 KIM 90.2학번 , 이름 , 성적 입력 : 2 PARK 30.5학 번 , 이 름 , 성 적 입 력 : 3 MIN 56.8학번 , 이름 , 성적 입력 : ^Z평균 = 59.1667

score.txt 1 KIM 90.22 PARK 30.53 MIN 56.8

Page 36: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

버퍼링 (buffering)· fopen() 을 사용하여 파일을 열면 자동으로 버퍼 (buffer) 할당· 버퍼는 입출력 데이터의 임시 저장 장소로 이용되는 메모리 블록· 디스크 장치는 블록 단위로 입출력할 경우 효율적으로 동작

· 블록의 크기는 일반적으로 512 바이트의 배수· 예 : 512, 1024, 4096, 8192

· flush: 버퍼의 내용을 비우는 동작· fclose(): flush 버퍼 반납· buffered I/O: 버퍼를 이용하는 입출력

File Buffer Program

물리적 입출력(Physical I/O)

논리적 입출력(Logical I/O)

Page 37: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

fflush, feof, ferrorint fflush(FILE *fp);· 출력 스트림의 경우 ,

버퍼의 내용을 실제 파일에 저장하고 버퍼를 비움· 입력 스트림에 대한 동작은 OS 에 따라 다름· 반환 값 : 성공 0, 실패 EOF

int feof(FILE *fp);· 현재 파일 끝 상태이면 참 (0 이 아닌 값 ) 반환

int ferror(FILE *fp);· 현재 파일이 에러 상태이면 참 (0 이 아닌 값 ) 반환

Page 38: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

이진 데이터 파일· 메모리의 내부 데이터 표현 형식 그대로 저장

00000001000000010000000000000000 1110001011100010 0100000001000000

00110010001100100011000100110001 0011001100110011 0011010000110100 0011010100110101 0011011000110110

정수 123456

‘1’ ‘2’ ‘3’ ‘4’ ‘5’ ‘6’텍스트 파일

이진 파일

Page 39: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

이진 데이터 출력 size_t fwrite(const void *buffer, size_t size, size_t count, FILE *fp);· buffer 에서 크기가 size 인 항목을 count 개수만큼 출력

· 반환 값 : 출력된 항목 개수· 반환 값이 count 가 아니면 에러

FILE *fp;int a[ ] = { 10, 20, 30, 40, 50 };size_t size = sizeof a[0];size_t n = sizeof a / sizeof a[0];

if ((fp = fopen("data.bin", "wb"))) { if (fwrite(a, size, n, fp) != n) fprintf(stderr, " 출력 실패 \n"); fclose(fp);}

int a[5] = { 10, 20, 30, 40, 50 };

if (fwrite(a, sizeof a, 1, fp) != 1) // er-rorif (fwrite(a, sizeof a[0], 5, fp) != 5) // error

Page 40: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

이진 데이터 입력 size_t fread(void *buffer, size_t size, size_t count, FILE *fp);

· buffer 에 크기가 size 인 항목을 최대 count 개수만큼 입력· 반환 값 : 입력된 항목 개수· 반환 값이 count 보다 작으면 파일 끝이나 에러

#define SIZE 100

FILE *fp;int a[SIZE];size_t n;

if ((fp = fopen("data.bin", "rb"))) { n = fread(a, sizeof a[0], SIZE, fp); if (n < SIZE) fprintf(stderr, " 파일 끝 또는 입력 실패 \n"); fclose(fp);}

Page 41: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

예제 : 파일 복사#include <stdio.h>#include <stdlib.h>

#define USAGE "Usage: fcopy from to\n"#define BUF_SIZE 1024

int main(int argc, char *argv[ ]) {    FILE *fpi, *fpo;    char buf[BUF_SIZE];    size_t n;

    if (argc != 3)        fprintf(stderr, "%s", USAGE), exit(1);

    if (!(fpi = fopen(argv[1], "rb")))        fprintf(stderr, "%s: fail to open\n", argv[1]), exit(1);    if (!(fpo = fopen(argv[2], "wb")))        fprintf(stderr, "%s: fail to open\n", argv[2]), exit(1);

    while ((n = fread(buf, 1, BUF_SIZE, fpi)) > 0)        if (fwrite(buf, 1, n, fpo) != n) break;        if (ferror(fpi))        fprintf(stderr, "%s: fail to read\n", argv[1]), exit(1);    if (ferror(fpo))        fprintf(stderr, "%s: fail to write\n", argv[2]), exit(1);    fprintf(stderr, "copied: %s => %s\n", argv[1], argv[2]);

    fclose(fpi); fclose(fpo);    return 0;} C> fcopy fcopy.exe

fcopy2.execopied: fcopy.exe => fcopy2.exe

Page 42: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

예제 : 파일 추가// 첫 번째 파일을 두 번째 파일 끝에 추가#include <stdio.h>#include <stdlib.h>#define BUF_SIZE 1024

int main(void) {FILE *fp1, *fp2;char file1[100], file2[100];char buffer[BUF_SIZE];int n;

printf(" 입력 파일 : "); scanf("%s", file1);printf(" 추가할 파일 : "); scanf("%s", file2);

if (!(fp1 = fopen(file1, "rb")))fprintf(stderr," 입력 파일 열기 실패 \n"),

exit(1);if (!(fp2 = fopen(file2, "ab")))

fprintf(stderr," 추가할 파일 열기 실패 \n"), exit(1);

while ((n = fread(buffer, 1, BUF_SIZE, fp1)) > 0)

fwrite(buffer, 1, n, fp2);

fclose(fp1); fclose(fp2);return 0;

}

입력 파일 : a.dat추가할 파일 : b.dat

Page 43: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

예제 : 이진 데이터 입출력#include <stdio.h>#include <stdlib.h>

#define SIZE 3typedef struct {

int number;char name[20];double gpa;

} Student;

int main(void) {Student table[SIZE] =

{{ 1, "Kim", 3.99 },{ 2, "Min", 2.68 },{ 3, "Lee", 4.01 }

};Student s;FILE *fp;int i;

if (!(fp = fopen("student.dat", "wb")))fprintf(stderr," 출력 파일 열기 실패 \n"), exit(1);

if (fwrite(table, sizeof(Student), SIZE, fp) != SIZE)

fprintf(stderr," 파일 출력 실패 \n"), exit(1);fclose(fp);

if (!(fp = fopen("student.dat", "rb")))fprintf(stderr," 입력 파일 열기 실패 \n"),

exit(1);for (i = 0; i < SIZE; i++) {

if (fread(&s, sizeof s, 1, fp) != 1)fprintf(stderr," 파일 입력 실패 \n"), exit(1);

printf("%d, %s, %g\n", s.number, s.name, s.gpa);

}

fclose(fp); return 0;}

1, Kim, 3.992, Min, 2.683, Lee, 4.01

Page 44: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

예제 : Hexa Dump// 16 진수로 파일 내용 출력#include <stdio.h>#include <stdlib.h>#include <ctype.h>

int main(void) {FILE *fp;char fname[100];unsigned char

buffer[16];int address = 0;int i, bytes;

printf(" 파일 이름 : "); scanf("%s", fname);if (!(fp = fopen(fname, "rb")))

fprintf(stderr,"%s: 열기 실패 \n", fname), exit(1);

while ((bytes = fread(buffer, 1, 16, fp)) > 0) {printf("%08X: ", address);address += bytes;for (i = 0; i < bytes; i++) printf("%02X ",

buffer[i]);for ( ; i < 16; i++) printf(" ");for (i = 0; i < bytes; i++)

putchar(isprint(buffer[i]) ? buffer[i] : '.');putchar('\n');

}

fclose(fp); return 0;} 파일 이름 : in.html

00000000: 3C 68 74 6D 6C 3E 0D 0A 3C 62 6F 64 79 3E 0D 0A <html>..<body>..00000010: 3C 70 72 65 3E 0D 0A 3C 68 31 3E 42 75 69 6C 64 <pre>..<h1>Build00000020: 20 4C 6F 67 3C 2F 68 31 3E 0D 0A Log</h1>..

in.html<html><body><pre><h1>Build Log</h1>

Page 45: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

임의 접근· 순차 접근 (sequential access): 파일의 처음부터 차례대로 입출력· 임의 접근 (random access): 파일의 임의 위치에서 직접 입출력

직접 접근 (direct access)

· 파일 위치 (file position) 표시자· 바이트 단위로 현재 입출력 위치 정보 유지

· 첫 번째 바이트 : 0 번째 바이트· 파일 위치를 이동시키면 임의 접근 가능

순차 접근

임의 접근

0 1 2 3 4 5 6 7

파일 위치 표시자

Page 46: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

fseek(fp, 0L, SEEK_SET); // 파일 시작으로 이동 (SEEK_SET 이면 offset 은 절대 위치 )fseek(fp, 100L, SEEK_SET); // 100 번째 바이트로 이동fseek(fp, 0L, SEEK_END); // 파일 끝으로 이동fseek(fp, -20L, SEEK_END); // 파일 끝에서 시작 쪽으로 20 바이트 이동fseek(fp, 50L, SEEK_CUR); // 현재 위치에서 끝 쪽으로 50 바이트 이동fseek(fp, sizeof(struct element), SEEK_CUR); // 구조체 크기만큼 파일 위치 증가

임의 접근 관련 함수

origin 값 기준 위치SEEK_SET 0 파일 시작

SEEK_CUR 1 현재 위치

SEEK_END 2 파일 끝

int fseek(FILE *fp, long offset, int origin);

· origin 기준으로 offset 만큼 떨어진 바이트로 파일 위치 변경· offset 이 음수 : 파일 시작 쪽으로 이동· offset 이 양수 : 파일 끝 쪽으로 이동 · 반환 값 : 성공 0, 실패 0 이 아닌 값

long ftell(FILE *fp);· 현재 파일 위치 반환

· 에러 -1 반환

void rewind(FILE *fp);· 파일 위치를 0 으로 변경

· 파일 시작 위치로 이동

Page 47: 쉽게 풀어쓴  C 언어  Express

© 2012 생능출판사 All rights reserved

예제#include <stdio.h>#include <stdlib.h>

#define SIZE 1000

int main(void) {FILE *fp;int table[SIZE], data, n;long pos;

for (n = 0; n < SIZE; n++)table[n] = n * n;

fp = fopen("sample.dat", "wb");

fwrite(table, sizeof table, 1, fp);

fclose(fp);

fp = fopen("sample.dat", "rb");while (1) {

printf(" 데이터 위치 (0 ~ %d): ", SIZE - 1);

scanf("%d", &n);if (n < 0 || n >= SIZE) break;pos = (long)(n * sizeof(int));if (fseek(fp, pos, SEEK_SET))

fprintf(stderr, "fseek 실패 \n"), exit(1);

fread(&data, sizeof(int), 1, fp);printf("%d: %d\n", n, data);

}fclose(fp);

return 0;} 데이터 위치 (0 ~ 999): 3

3: 9데이터 위치 (0 ~ 999): 99: 81데이터 위치 (0 ~ 999): -1