file I/O
이번 강의를 요약해보자.
#include <stdio.h>에 있는 파일들을 이용하는데,
FILE *variable_name이라는 file 포인터가 있다.
이 구조체는 파일의 상태에 대하여 서술하는 것임
fopen(), fprintf(), fscanf(), fputc(),fgetc(), fclose() 함수로 파일을 조작한다.
fopen(), fclose()
함수부터 시작해보자.
기본적인 골격은 다음과 같다.
step 1. 파일 포인터 선언
FILE *fp;
step 2. 파일 오픈
fp = fopen("filename", "mode");
step 3. 어쩌구저쩌구 진행
step 4. 파일 닫기
fclose(fp);
이때 fopen의 mode에는 다양한 것이 있다.
[1] text file용
fp = fopen("filename", "r"); // for reading - 주로 쓰는 것 1
fp = fopen("filename", "w"); // for writing - 주로 쓰는 것 2
fp = fopen("filename", "a"); // for appending
[2] binary file용
fp = fopen("filename", "rb"); // for reading
fp = fopen("filename", "wb"); // for writing
fp = fopen("filename", "ab"); // for appending
formatted file I/O
stdio.h 헤더 파일에서 가져다가 쓸 수 있는 파일 입출력 관련 함수에는
대표적으로 fopen, fclose, fscanf, fprintf가 있다.
fscanf의 프로토타입은 : fscanf(ifp, control_string, other_arguments);
fprintf의 경우는 : fprintf(ofp, control_string, other_arguments);
#include <stdio.h>
int main(void){
FILE *ifp, *ofp;
ifp = fopen("in_file.txt", "r");
ofp = fopen("out_file.txt", "w");
int i;
fscanf(ifp, "%d", &i);
fprintf(ofp, "%d", i);
fclose(ifp);
fclose(ofp);
return 0;
}
ex)
#include <stdio.h>
void main(void){
FILE *ifp, *ofp;
int a, sum=0;
ifp = fopen("infile", "r");
ofp=fopen("outfile", "w");
while (fscanf(ifp, "%d", &a)==1){
sum += a;
}
fprintf(ofp, "The sum is %d.\n", sum);
fclose(ifp);
fclose(ofp);
}
stdin, stdout, stderr
stdin : standard input file - keyboard
stdout : standard output file - screen
stderr : standard error file - screen
fprintf(stdout, );는 printf();
fscanf(stdin, );는 scanf();와 같다.
(원래 ifp, ofp를 stdout, stdin으로 바꾼 것)
character file I/O
[1] read
파일로부터 character를 받아와보자!
EOF를 return하기 전까지 반복하면 된다.
c = getc(fp);
c = fgetc(fp);
[2] write
에러 발생시 EOF를 return함.
putc(c, fp);
fputc(c, fp);
EOF == End of File
stdio.h에서는 EOF를 #define EOF -1로 정의하고 있음.
EOF인지 확인하려면..int feof(FILR *fp); 이용할 수 있다.
file을 쭉 받아오려면 어떻게 해야하지?
ex) copy file1 file2
#include <stdio.h>
int main(void){
FILE *fp1, *fp2;
int c;
fp1 = fopen("in.txt", "r");
fp2 = fopen("out.txt", "w");
while ((c=getc(fp1))!=EOF){
putc(c,fp2);
}
fclose(fp1);
fclose(fp2);
return 0;
}
파일명을 컴파일 단계에서 말하도록 할 수도 있다.
argc, *argv[] 싫어엉
#include <stdio.h>
int main(int argc, char *argv[]){
FILE *fp1, *fp2;
int c;
fp1 = fopen(argv[1], "r");
fp2 = fopen(argv[2], "w");
while ((c=getc(fp1))!= EOF)
putc(c,fp2);
fclose(fp1);
fclose(fp2);
return 0;
}
error handling and exit
ex) double spacing a file
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
FILE *fp1, *fp2;
int c;
if (argc != 3) exit(1);
fp1 = fopen(argv[1], "r");
fp2 = fopen(argv[2], "w");
while ((c=getc(fp1))!=EOF) {
putc(c, fp2);
if (c=='\n') putc('\n', fp2);
}
fclose(fp1);
fclose(fp2);
exit(0);
}
line I/O
line 중심 인풋 함수로 fgets가 있고,
아웃풋 함수로 fputs가 있다.
두 함수의 용례를 살펴보자.
- fgets() -
line oriented input function
char *fgets(char *line, int n, FILE *fp);
최대 n-1개의 character를 한 줄에서(*line) 읽어들인다.
만약 다음 줄이 오거나, 파일이 끝나면 함수가 종료됨
버퍼용으로 배열 끝에(*line) '\0'이 삽입된다.
char *fgets(char *s, int n, FILE *iop){
int c;
char *cs;
cs = s;
while ((c=getc(iop))!=EOP &&--n>0)
if ((*cs++ = c) == '\n') break;
*cs = '\0';
return (c==EOF && cs==s)?NULL:s;
}
- fputs() -
line oriented output function
int fputs(char *line, FILE *fp);
null로 끝나는 string line을 카피해서 fp로 보낸다.
성공하면 nonnegative value를 return하고, 실패하면 EOF(-1) return함
함수 내부 구조는
int fputs(char *s, FILE *iop)
{
int c;
while (c=*s++) putc(c, iop);
return ferror(iop) ? EOF : 0;
}
-fputs(), fgets() 용례 -
매우 중요
#include <stdio.h>
int main(void){
FILE *ifp = fopen("input.txt", "r");
FILE *ofp = fopen("output.txt", "w");
if (ifp == NULL){
printf("ERROR\n");
return 0;
}
while (1){
char arr[100];
char *tmp = fgets(arr, 100, ifp);
if (tmp == NULL){
break;
}
fputs(arr, ofp);
}
fclose(ifp);
return 0;
}
#include<stdio.h>
int main(void)
{
//read mode로 파일을 생성하고 오픈합니다.
FILE* pFile = fopen("test.txt", "r");
if(pFile == NULL)
{
//파일이 없다. 프로그램 종료
return 0;
}
//파일의 끝이 나올때 까지 반복문으로 fgets 수행.
while(true)
{
char arr[100];//문자열을 담을 변수
char* pStr = fgets(arr, 100, pFile);
if(pStr == NULL)
{
//파일의 끝
break;
}
//파일 계속 읽어들이기. (출력에 \n가 없음.)
printf("fgets 1sr arg : %s", arr);
}
//파일 닫기
fclose(pFile);
return 0;
}
[C언어/C++] fgets, fputs 함수에 대해서 (tistory.com)
random File I/O
파일 데이터를 읽는 방식에는 순차 엑세스와 랜덤 엑세스가 있다.
랜덤 파일 엑세스는 임의의 위치로 이동해서 필요한 부분만 읽고 쓰는 방식을 말한다.
C에서는 fseek, ftell로 이를 수행한다.
프로토타입 형식
int fseek(FILE *fp, long offset, int place);
long ftell(FILE *fp);
fseek() 함수
int fseek(FILE *fp, long offset, int place);
fp : 탐색하는 파일의 FILE형 변수 포인터
offset : place 위치에서 이동하는 바이트 수
place : stdio.h 헤더 상수 중 하나(SEEK_CUR / 현재 파일 포인터의 위치 , SEEK_SET / 파일의 시작, SEEK_END / 파일 끝)
ftell() 함수
long ftell(FILE *stream);
지정된 스트림의 함수 포인터를 돌려줌
ex)
#include <stdio.h>
int main(void){
int c;
FILE *ifp;
ifp = fopen("in.txt", "r");
fseek(ifp, 0, SEEK_END);
fseek(ifp, -1, SEEK_CUR);
while (ftell(ifp)>0){
c = getc(ifp);
putchar(c);
fseek(ifp, -2, SEEK_CUR);
}
fclose(ifp);
return 0;
}
cf)
#include <stdio.h>
int main(void){
char fileName[256];
int fileIndex, text;
FILE *file;
printf("읽을 파일 이름을 지정하십시오.");
scanf("%s", fileName);
printf("파일을 읽을 시작 위치를 바이트 단위로 지정하십시오.");
scanf("%d", &fileIndex);
file = fopen(fileName, "rb");
if (file == NULL){
fprintf(stderr, "파일 조작에 에러가 발생했습니다.\n");
return 0;
}
fseek(file, fileIndex, SEEK_SET);
printf("파일 위치 %d에서 읽습니다\n", (int)ftell(file));
while (1){
text = fgetc(file);
if (feof(file)) break;
printf("%c", text);
}
printf("\n");
fclose(file);
return 0;
}
low level I/O
system call : 운영체제 커널에 보내는 리퀘스트
create() : 새로운 빈 파일을 만들거라
int create(char *filename, mode_t, mode)
open() : 파일을 오픈해라
int open(const char* Path, int flags [, int mode ]);
close() : file 닫아라
int close(int fd);
read() : file을 읽어와라
size_t read(int fd, void * buf, size_t cnt);
write() : 파일을 써라
size_t write(int fd, void *buf, size_t cnt);
open creat close
??
file access permissions
read, write
ex) read(), write()
#include <unistd.h>
#include <stdio.h>
int getchar(void);
int main(void){
char buf[BUFSIZ];
int n;
while ((n=read(0,buf,BUFSIZ))>0)
write(1,buf,n);
return 0;
}
int getchar(void){
char c;
return (read(0,&c,1)==1)?(unsigned char)c:EOF;
}
ex) open, creat, close
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#define PERMS 0666
int main(int argc, char *argv[]){
int f1, f2, n;
char buf[BUFSIZ];
if (argc!=3){
fprintf(stderr, "Usage:cp from to"); exit(1);
}
if ((f1=open(argv[1], O_RDONLY, 0))==-1){
fprintf(stderr, "cp: can't open %s",argv[1]); exit(1);
}
if ((f2=creat(argv[2], PERMS))==-1){
fprintf(stderr, "cp:can't create %s, mode %03o", argv[2], PERMS); exit(1);
}
while ((n=read(f1, buf, BUFSIZ))>0){
if (write(f2, buf, n)!=n){
fprintf(stderr, "cp:write error on file %s", argv[2]); exit(1);
}
}
exit(0);
}
random access - Lseek
'Computer Science > C' 카테고리의 다른 글
연습 문제 #1 | 간단한 알고리즘(bubble sort, selection sort, merge sort), 간단한 자료구조(queue, linked list, stack, binary tree) (0) | 2021.12.20 |
---|---|
서울대 프로그래밍연습 2020 기출 문제 풀이 | print, 피보나치 수열, 스택, 등차수열 (0) | 2021.12.18 |
C언어 8강 | 전처리기 Preprocessors (0) | 2021.12.17 |
C언어 7강 | Bitwise operators (0) | 2021.12.17 |
C언어 10강 | Structures and list processing | 제일 중요함 *** (0) | 2021.12.17 |