Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

fseek(3)

1장. fseek(3)

차례
1.1. 사용법
1.2. 설명
1.3. 반환값
1.4. 에러
1.5. 예제
1.6. 참고문헌

시트림위치의 재지정


1.1. 사용법

#include <stdio.h>

int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);
		


1.2. 설명

fseek()함수는 stream에서의 위치를 변경하기 위해서 사용한다. 새로운 위치는 offset을 통해서 바이트 단위로 지정할 수 있다. 위치 변경을 위해서는 기준점이 있어야 할건데, 이는 whence를 이용해서 결정할 수 있다. whence는 위치변경을 위한 기준점에 따라서 SEEK_SET SEEK_CUR, SEEK_END가 있다. SEEK_SET는 시작점을, SEEK_CUR은 현재 스트림에서의 위치를, SEEK_END는 스트림의 마지막점을 기준으로 한다.

ftell()함수는 stream에서의 현재 위치를 구하기 위해서 사용한다.

rewind()함수는 stream에서의 위치를 처음으로 되돌리기 위해서 사용한다. rewind()는 fseek()를 이용해서 동일하게 구현할 수 있다.

(void)fseek(stream, 0L, SEEK_SET)
		
fgetpos()와 fsetpos()는 ftell()과 fseek()의 조합(whence는 SEEK_SET)이다. 즉 위치를 변경하고 현재의 위치값을 fpost_t 객체에 되돌려준다.


1.3. 반환값

rewind()함수는 아무것도 되돌려주지 않는다. fgetpos(), fseek(), fsetpos()는 0을 ftell()는 현재 위치를 되돌려준다. 실패했을 경우에는 -1을 리턴한다.


1.4. 에러

EBADF

stream이 위치를 정할 수 없는 스트림이다. STDOUT, STDIN이 대표적인 위치를 정할 수 없는 스트림이다.

EINVAL

whence인자가 SEEK_SET, SEEK_END, SEEK_CUR이 아닌 값을 사용했다.

EINTR

시스템 호출이 인터럽트 되었다.


1.5. 예제

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

int main(int argc, char **argv)
{
    FILE *fp;
    char buf[256];
    char gline[12];
    int linenum = 0;
    int inputline;
    int *line_index;

    fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        perror("open error");
        return 1;
    }

    // 라인의 갯수를 계산한다. 
    while(fgets(buf, 255, fp) != NULL)
    {
        if (buf[strlen(buf)-1] == '\n')
            linenum++;
    }
    // 라인의 갯수만큼 메모리를 할당한다. 
    // line_index 배열에는 각 라인의 위치가 들어간다. 
    line_index = (int *)malloc(sizeof(int) * linenum +1);

    // 스트림을 처음으로 되돌린다. 
    rewind(fp);

    // 파일의 처음부터 돌면서 
    // ftell()을 이용 각 라인의 위치(offset)를 저장한다.
    line_index[0] = 0;

    int a=0;
    while(fgets(buf, 255, fp) != NULL)
    {
        // 사실은 라인의 크기가 255를 초과할 경우 이에 대한 
        // 대책을 마련해야 하지만 귀찮은 관계로 넘어간다.
        if (buf[strlen(buf)-1] == '\n' && a+1 < linenum)
        {
            line_index[a+1] = ftell(fp);
            a++;
        }
    }

    printf("Line num is %d\n", linenum);
    // 라인 번호를 입력하면 해당 라인으로 
    // fseek()함수를 이용해서 점프하고 라인의 내용을 출력한다.
    while(1)
    {
        printf("Goto Line : ");
        fgets(gline, 11, stdin);
        gline[strlen(gline) - 1] = '\0';
        inputline = atoi(gline);
        if (inputline < linenum && inputline > -1)
        {
            fseek(fp, line_index[inputline], SEEK_SET);
            fgets(buf, 255, fp);
            printf("%d(%d) : %s", inputline, line_index[inputline],buf);
        }
        else
        {
            printf("input num Error (0 - %d)\n", linenum-1);
        }
        printf("\n");
    }
}