[C언어] 파일 포인터 사용하기 - 코딩도장

2024. 3. 6. 23:37· Coding/C
목차
  1. [코딩도장] Unit 71
  2. 1. 파일 포인터 활용하기 (fseek, ftell)
  3. 2. 파일 크기만큼 파일 읽기
  4. 3. 심사문제

[코딩도장] Unit 71


1. 파일 포인터 활용하기 (fseek, ftell)

1. 파일 포인터 이동하기 (fseek)

fseek 함수는 기준점에서 이동할 거리(크기)를 지정하여 파일 포인터를 이동시킨다

  • fseek(파일포인터, 이동할크기, 기준점)
fseek(fp, 0, SEEK_END);    // 파일 포인터를 파일의 끝으로 이동시킴

fseek 의 기준점은

  • SEEK_SET    파일의 처음부터 시작
  • SEEK_CUR    현재 위치부터 이동 시작
  • SEEK_END    파일의 끝부터 시작

SEEK_SET, SEEK_CUR, SEEK_END는

기준점을 기준으로 파일 포인터의 위치를 바꾼다

 

fseek 함수의 기준점

fseek(fp, 0, SEEK_SET); 이면 파일의 처음으로 간다

fssek(fp, 0, SEEK_END); 이면 파일의 끝으로 간다

 

현재 위치에서 순방향으로 10바이트 이동하려면

fseek(fp, 10, SEKK_CUR); 과 같이 10바이트만큼 순방향으로 이동하도록 하면 된다

 

역방향으로 10바이트 이동하려면

fssek(fp, -10, SEEK_CUR); 과 같이 음수를 지정하면 된다

 

fseek 함수의 사용

파일 포인터의 이동 방향은 포인터 연산의 이동 방향과 같다

 

2. 파일 크기 구하기 (ftell)

파일포인터의 현재 위치를 얻어오려면 ftell 함수를 사용하면 된다

  • ftell(파일포인터)
size = ftell(fp);          // 파일 포인터의 현재 위치를 얻음

이동할 크기를 0으로하고 기준점을 SEEK_END로 지정하여

ftell 함수를 사용하면 파일의 크기를 알 수 있다

 

fseek(fp, 0, SEEK_END);    // 파일 포인터를 파일의 끝으로 이동시킴
size = ftell(fp);          // 파일 포인터의 현재 위치를 얻음

 

fseek, ftell 함수로 파일 크기 구하기

 

 

2. 파일 크기만큼 파일 읽기

1. 파일 크기만큼 파일 읽기

FILE *fp = fopen("hello.txt", "r");    // hello.txt 파일을 읽기 모드(r)로 열기.
                                       // 파일 포인터를 반환
  
fseek(fp, 0, SEEK_END);    // 파일 포인터를 파일의 끝으로 이동시킴
size = ftell(fp);          // 파일 포인터의 현재 위치를 얻음

fopen 함수로 파일을 읽기 모드로 열고

fseek 함수와 ftell 함수로 파일의 크기를 구한다

 

buffer = malloc(size + 1);    // 파일 크기 + 1바이트(문자열 마지막의 NULL)만큼 동적 메모리 할당
memset(buffer, 0, size + 1);  // 파일 크기 + 1바이트만큼 메모리를 0으로 초기화

파일의 문자열을 읽어서 C언어 문자열로 만들 때는

문자열 마지막의 NULL 공간까지 확보해야 한다

 

따라서 파일 크기 + 1바이트만큼 메모리를 할당한다

malloc 함수로 할당한 메모리는 memset 함수를 사용하여 0으로 초기화 한다

NULL공간 확보 후, NULL로 초기화

할당한 메모리를 NULL 로 초기화하지 않으면

문자열 끝 부분에 다른 값이 들어있을 수도 있다

문자열의 끝인 NULL을 찾을 수 없어 문자열 이외의 값이 함께 출력되므로 주의해야 한다

 

fseek(fp, 0, SEEK_SET);                // 파일 포인터를 파일의 처음으로 이동시킴
count = fread(buffer, size, 1, fp);    // hello.txt에서 파일 크기만큼 값을 읽음

파일의 크기를 구할 때 파일 포인터를 끝으로 이동시켰다

이 상태에서는 파일을 읽을 수 없기 때문에

fseek 함수를 이용하여 파일 포인터를 맨 처음으로 이동시킨다

 

printf("%s size: %d, count: %d\n", buffer, size, count);
                // Hello world! size: 13, count: 1: 파일의 내용, 파일 크기, 읽은 횟수 출력

printf 로 버퍼의 내용을 출력하면 파일의 내용이 출력된다

 

fclose(fp);      // 파일 포인터 닫기

free(buffer);    // 동적 메모리 해제

파일 읽기가 끝났으면 파일 포인터를 닫고 메모리를 해제한다

 

2. 제한된 버퍼로 파일 전체 읽기 (feof)

feof 함수는 현재 파일 포인터가 파일의 끝인지 검사한다

  • feof(파일포인터)
while (feof(fp) == 0)    // 파일 포인터가 파일의 끝이 아닐 때 계속 반복

feof 함수는 파일 포인터가 파일의 끝이면 1을 반환 아니면 0을 반환한다

 

char buffer[5] = { 0, };    // 문자열 데이터 4바이트 NULL 1바이트. 4 + 1 = 5

버퍼 크기를 5바이트로 만들어준다

문자열을 읽어서 출력할 것이기 때문에 문자열 4바이트 NULL 1바이트이다

 

while (feof(fp) == 0)    // 파일 포인터가 파일의 끝이 아닐 때 계속 반복
{
    count = fread(buffer, sizeof(char), 4, fp);    // 1바이트씩 4번(4바이트) 읽기
    
    printf("%s", buffer);                          // 읽은 내용 출력
    memset(buffer, 0, 5);                          // 버퍼를 0으로 초기화
    total += count;                                // 읽은 크기 누적
}

while 반복문에 조건식으로 feof(fp) == 10 을 지정하여

파일 포인터가 파일의 끝이 아닐 때 계속 반복하도록 한다

 

fread 함수로 파일을 읽을 때는 buffer 를 선언한 자료형이 char 이기 때문에

sizeof(char)를 지정하여 1바이트 크기로 4번 읽는다

fread 로 파일을 읽었을 때 읽은 크기만큼 반환값이 나오기 때문에 파일의 전체 크기를 구할 수 있다

 

fread 로 파일을 읽고 크기는 count에 저장한다

printf 로 buffer 의 내용을 출력한다

출력이 끝났다면 memset 함수로 buffer 를 초기화 한다

 

이렇게 한정된 버퍼를 이용해 전체 문자열을 출력할 수 있다

 

 

3. 심사문제

71.9 파일을 부분적으로 읽기

문자열이 저장된 words.txt 파일이 주어집니다. 다음 소스 코드에서 getData 함수를 완성하여 words.txt에서 읽은 문자열을 출력하고, 그 다음 줄에 읽은 크기를 출력하는 프로그램을 완성하세요.

정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int getFileSize(FILE *fp)
{
    int size;
    int currPos = ftell(fp);

    fseek(fp, 0, SEEK_END);
    size = ftell(fp);

    fseek(fp, currPos, SEEK_SET);

    return size;
}

char *getData(int offset, int size, int *count, FILE *fp)
{
    __________________________________
    __________________________________

    __________________________________
    __________________________________

    __________________________________
}

int main()
{
    char *buffer;
    int size;
    int count;

    FILE *fp = fopen("words.txt", "r");

    size = getFileSize(fp);
    buffer = getData(0, size, &count, fp);
 
    printf("%s\n", buffer);
    printf("%d", count);

    fclose(fp);

    free(buffer);

    return 0;
}

 

 

정답

char *buffer;
    
buffer = malloc(size + 1);
memset(buffer, 0, size + 1);

fseek(fp, offset, SEEK_SET);
*count = fread(buffer, sizeof(char), size, fp);

return buffer;

71.10 파일을 부분적으로 읽기

문자열이 저장된 words.txt 파일이 주어집니다.(반드시 GitHub 저장소의 Unit 71/words.txt 파일로 테스트하세요.) 파일 처음부터 순방향으로 7바이트 지점에서 4바이트만큼 읽고, 파일 끝에서 역방향으로 6바이트 지점에서 2바이트만큼 읽은 값을 출력하는 프로그램을 만드세요. 단, 읽은 문자열은 공백으로 띄우지 않고 붙여서 출력합니다.

 

정답

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *readForword(char *buffer, int offset, int size, FILE *fp) {
    if (feof(fp) == 1)
        return NULL;
    
    fseek(fp, offset, SEEK_SET);
    fread(buffer, sizeof(char), size, fp);

    return buffer;
}

char *readBackword(char *buffer, int offset, int size, FILE *fp) {
    if (feof(fp) == 1)
        return NULL;

    fseek(fp, offset, SEEK_END);
    fread(buffer, sizeof(char), size, fp);
}

int main() {
    char forBuffer[20] = {0, };
    char backBuffer[10] = {0, };

    FILE *fp = fopen("words.txt", "r");

    readForword(forBuffer, 7, 4, fp);
    readBackword(backBuffer, -6, 2, fp);

    strcat(forBuffer, backBuffer);
    printf("%s", forBuffer);
    
    fclose(fp);

    return 0;
}

파일을 정방향으로 읽는 함수 readForword 를 작성하고

파일을 역방향으로 읽는 함수 readBackword 를 작성한다

두 함수를 이용해 문자열을 읽어온 뒤

두 문자열을 strcat 함수를 이용해 이어붙인다


71.11 파일을 읽은 뒤 거꾸로 저장하기

문자열이 저장된 words.txt 파일이 주어집니다. 파일을 읽은 뒤 내용을 거꾸로 저장하는 프로그램을 만드세요. 결과는 fwrite 함수로 stdout에 저장하면 됩니다. 단, words.txt 의 최대 크기는 10,000바이트입니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int size, readSize;
    char *buffer;

    FILE *fp = fopen("words.txt", "r");

    fseek(fp, 0, SEEK_END);
    size = ftell(fp);

    buffer = malloc(size);

    while (size > 0) {
        fseek(fp, -1, SEEK_CUR);
        readSize = fread(buffer, sizeof(char), 1, fp);

        fwrite(buffer, sizeof(char), 1, stdout);

        fseek(fp, -1, SEEK_CUR);
        size --;
    }
    free(buffer);
    fclose(fp);

    return 0;
}

fseek 함수를 이용해 파일 포인터를 맨 끝으로 이동시킨 후

문자열을 거꾸로 읽어와 버퍼에 저장한다

 

하지만 fread 함수는 순방향으로 1 이동하기 때문에

문자열을 읽어온 후 fseek 함수를 이용해 역방향으로 1 이동시켜줘야 한다

(아니면 제자리에서 무한 반복하는 문제가 발생한다)

저작자표시 비영리 변경금지 (새창열림)

'Coding > C' 카테고리의 다른 글

[C언어] 파일에서 문자열 읽고 쓰기 - 코딩도장  (0) 2024.02.29
[C언어] 함수 가변인자, 재귀호출 - 코딩도장  (0) 2024.02.10
[C언어] 함수에서 매개변수 사용하기(포인터, 배열, 구조체) - 코딩도장  (0) 2024.02.06
[C언어] 함수 사용하기 - 코딩도장  (0) 2024.02.02
[C언어] 자료형 변환, 포인터 연산 - 코딩도장  (0) 2024.01.30
  1. [코딩도장] Unit 71
  2. 1. 파일 포인터 활용하기 (fseek, ftell)
  3. 2. 파일 크기만큼 파일 읽기
  4. 3. 심사문제
'Coding/C' 카테고리의 다른 글
  • [C언어] 파일에서 문자열 읽고 쓰기 - 코딩도장
  • [C언어] 함수 가변인자, 재귀호출 - 코딩도장
  • [C언어] 함수에서 매개변수 사용하기(포인터, 배열, 구조체) - 코딩도장
  • [C언어] 함수 사용하기 - 코딩도장
GunP4ng
GunP4ng
GunP4ng
GunP4ng
GunP4ng
전체
오늘
어제
  • 분류 전체보기 (104)
    • Hacking (31)
      • Pwnable (30)
      • Web (0)
      • Reversing (0)
      • Misc (1)
    • War Game (21)
      • Pwnable (21)
      • Web (0)
      • Misc (0)
    • pwnable.kr (0)
    • CTF (0)
    • Coding (48)
      • baekjoon (26)
      • C (22)
    • ETC (4)
      • Certificate (4)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 글쓰기

공지사항

인기 글

태그

  • return_to_library
  • uaf
  • WarGame
  • C언어
  • ROP
  • x86
  • srop
  • PIE
  • got_overwrite
  • BOF
  • Dreamhack
  • 코딩
  • DFB
  • shellcode
  • 구조체
  • plt
  • Tcache
  • Got
  • 스택
  • 코딩도장
  • 백준
  • doublefreebug
  • x64
  • rtl_chaining
  • 포인터
  • 메모리
  • Use-After-Free
  • 함수
  • tcache_dup
  • RTL

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.3.0
GunP4ng
[C언어] 파일 포인터 사용하기 - 코딩도장
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.