C 언어에서 fprintf와 fscanf로 형식화된 입출력 처리

C 언어에서 파일 입출력은 프로그래밍에서 데이터를 영구적으로 저장하고 처리하는 데 핵심적인 역할을 합니다. 특히, fprintffscanf 함수는 형식화된 데이터를 파일에 쓰고 읽는 데 사용됩니다. 이러한 함수의 사용법을 익히면 효율적인 데이터 처리가 가능하며, 프로그램의 안정성과 유지보수성을 높일 수 있습니다. 본 기사에서는 fprintffscanf의 기본 사용법부터 응용 사례, 문제 해결 방안까지 다양한 관점을 다룰 예정입니다.

목차

fprintf와 fscanf의 개념 및 기본 사용법


fprintffscanf는 C 언어에서 파일 입출력을 처리하기 위해 제공되는 표준 함수입니다.

fprintf의 정의와 기본 사용법


fprintf는 지정된 파일 스트림에 형식화된 데이터를 출력하는 함수입니다. 다음은 기본적인 함수 시그니처입니다:

int fprintf(FILE *stream, const char *format, ...);
  • stream: 데이터를 출력할 파일 포인터입니다.
  • format: 출력 형식을 지정하는 문자열입니다.
  • 가변 인수(...): 포맷에 따라 출력할 데이터입니다.

사용 예제:

FILE *file = fopen("example.txt", "w");
if (file) {
    fprintf(file, "Name: %s, Age: %d\n", "Alice", 30);
    fclose(file);
}

fscanf의 정의와 기본 사용법


fscanf는 지정된 파일 스트림에서 데이터를 읽고, 형식화된 입력 처리를 수행하는 함수입니다. 기본 시그니처는 다음과 같습니다:

int fscanf(FILE *stream, const char *format, ...);
  • stream: 데이터를 읽을 파일 포인터입니다.
  • format: 입력 형식을 지정하는 문자열입니다.
  • 가변 인수(...): 데이터를 저장할 변수들의 주소입니다.

사용 예제:

FILE *file = fopen("example.txt", "r");
if (file) {
    char name[50];
    int age;
    fscanf(file, "Name: %s, Age: %d", name, &age);
    printf("Read - Name: %s, Age: %d\n", name, age);
    fclose(file);
}

기본 개념 요약

  • fprintf: 파일에 데이터를 포맷화하여 출력.
  • fscanf: 파일에서 포맷화된 데이터를 읽기.
    이 두 함수는 파일 입출력에서 데이터 구조화를 간단하게 처리하는 데 매우 유용합니다.

fprintf로 파일에 데이터 쓰기


fprintf 함수는 파일에 데이터를 형식화하여 출력하는 데 사용됩니다. 이 함수는 포맷 문자열을 이용해 데이터를 원하는 형식으로 표현할 수 있으며, 가변 길이의 데이터를 처리하는 데 매우 유용합니다.

기본 사용법


다음은 fprintf로 파일에 데이터를 쓰는 기본 예제입니다:

#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "w"); // 파일 쓰기 모드로 열기
    if (file == NULL) {
        perror("파일 열기 오류");
        return 1;
    }

    // 데이터를 형식화하여 파일에 출력
    fprintf(file, "Name: %s\n", "John Doe");
    fprintf(file, "Age: %d\n", 28);
    fprintf(file, "Height: %.2f cm\n", 175.5);

    fclose(file); // 파일 닫기
    return 0;
}

출력 결과:
data.txt 파일의 내용은 다음과 같습니다:

Name: John Doe
Age: 28
Height: 175.50 cm

포맷 문자열의 유연성

  • 문자열 출력: %s를 사용하여 문자열 데이터를 출력합니다.
  • 정수 출력: %d, %u 등을 사용해 정수형 데이터를 출력합니다.
  • 소수 출력: %f, %.2f 등을 사용해 부동소수점 데이터를 출력하며, 소수점 자릿수를 지정할 수 있습니다.
  • 16진수/8진수 출력: %x, %o를 사용해 16진수 또는 8진수로 출력할 수 있습니다.

응용 사례

  1. 구조체 데이터 출력
    구조체를 fprintf로 출력하여 데이터를 정리할 수 있습니다.
   typedef struct {
       char name[50];
       int age;
       float height;
   } Person;

   void savePersonToFile(FILE *file, Person p) {
       fprintf(file, "Name: %s, Age: %d, Height: %.2f\n", p.name, p.age, p.height);
   }
  1. 로그 파일 생성
    프로그램 실행 중 상태를 기록하는 로그 파일 작성에 활용할 수 있습니다.
   FILE *logFile = fopen("log.txt", "a"); // 추가 모드로 열기
   fprintf(logFile, "[%s] Error: %s\n", "2024-12-25 10:00:00", "파일 없음");
   fclose(logFile);

주의 사항

  • 파일이 제대로 열렸는지 확인해야 합니다. fopen이 실패하면 NULL을 반환합니다.
  • 데이터를 쓰고 나서는 반드시 fclose를 호출하여 리소스를 해제해야 합니다.
  • 포맷 문자열을 안전하게 작성하여 보안 문제를 방지해야 합니다.

fprintf는 데이터를 형식화하여 저장하는 강력한 도구로, 구조적 데이터 관리와 로깅 등에 필수적으로 사용됩니다.

fscanf로 파일에서 데이터 읽기


fscanf 함수는 파일에서 데이터를 읽어 들이고 이를 형식화하여 변수에 저장하는 데 사용됩니다. 이 함수는 데이터를 구조적으로 처리하거나 분석할 때 유용합니다.

기본 사용법


다음은 fscanf를 사용하여 파일에서 데이터를 읽는 간단한 예제입니다:

#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r"); // 파일 읽기 모드로 열기
    if (file == NULL) {
        perror("파일 열기 오류");
        return 1;
    }

    char name[50];
    int age;
    float height;

    // 데이터를 파일에서 읽기
    fscanf(file, "Name: %s\n", name);
    fscanf(file, "Age: %d\n", &age);
    fscanf(file, "Height: %f\n", &height);

    printf("Name: %s, Age: %d, Height: %.2f cm\n", name, age, height);

    fclose(file); // 파일 닫기
    return 0;
}

data.txt의 내용이 다음과 같다면:

Name: John
Age: 28
Height: 175.50

출력 결과:

Name: John, Age: 28, Height: 175.50 cm

포맷 문자열과 가변 인수


fscanf는 포맷 문자열을 사용하여 파일의 데이터를 원하는 변수에 저장합니다.

  • 문자열 입력: %s를 사용해 문자열 데이터를 읽습니다.
  • 정수 입력: %d를 사용해 정수형 데이터를 읽습니다.
  • 소수 입력: %f를 사용해 부동소수점 데이터를 읽습니다.

응용 사례

  1. 구조체 데이터 읽기
    파일의 데이터를 구조체에 저장하는 예제:
   typedef struct {
       char name[50];
       int age;
       float height;
   } Person;

   Person readPersonFromFile(FILE *file) {
       Person p;
       fscanf(file, "Name: %s, Age: %d, Height: %f", p.name, &p.age, &p.height);
       return p;
   }
  1. 다양한 데이터 유형 읽기
    여러 유형의 데이터를 처리하는 복합 예제:
   FILE *file = fopen("data.txt", "r");
   if (file) {
       char category[20];
       int id;
       double price;
       fscanf(file, "Category: %s ID: %d Price: %lf", category, &id, &price);
       printf("Category: %s, ID: %d, Price: %.2f\n", category, id, price);
       fclose(file);
   }

주의 사항

  • 읽기 전에 파일 포인터가 제대로 열렸는지 확인하세요.
  • 데이터 형식이 파일 내용과 일치하지 않으면 예상치 못한 동작이 발생할 수 있습니다.
  • 공백, 줄 바꿈 등의 구문 요소는 포맷 문자열과 일치해야 합니다.
  • 포맷 문자열에서 %s를 사용할 경우 버퍼 오버플로를 방지하기 위해 길이를 제한하는 것이 좋습니다.
    예: %49s (최대 49자 읽기).

오류 처리

  • fscanf는 읽은 항목 수를 반환합니다. 이를 활용해 오류를 처리할 수 있습니다.
   int result = fscanf(file, "%s %d", name, &age);
   if (result != 2) {
       printf("읽기 오류 발생\n");
   }

fscanf는 파일에서 데이터를 효율적으로 읽고 이를 변수에 할당하는 데 유용하며, 파일 기반 데이터 처리의 핵심 도구입니다.

파일 입출력 오류 처리


파일 입출력 작업에서는 다양한 오류가 발생할 수 있습니다. fprintffscanf를 사용할 때 이러한 오류를 효과적으로 처리하는 방법을 알아봅니다.

파일 열기 오류 처리


파일을 열지 못한 경우, fopen 함수는 NULL을 반환합니다. 이를 확인하여 오류를 처리할 수 있습니다.

FILE *file = fopen("data.txt", "r");
if (file == NULL) {
    perror("파일 열기 오류");
    return 1; // 프로그램 종료
}
  • perror 함수는 표준 출력에 오류 메시지를 출력합니다.

fprintf 및 fscanf의 반환값 확인

  • fprintf 반환값: 출력된 문자의 개수를 반환합니다. 음수면 출력에 실패한 것입니다.
   if (fprintf(file, "Name: %s\n", "John") < 0) {
       perror("파일 쓰기 오류");
   }
  • fscanf 반환값: 성공적으로 읽은 항목의 개수를 반환합니다. 읽기 실패 시 반환값이 예상치 못한 값이 됩니다.
   int result = fscanf(file, "Name: %s Age: %d", name, &age);
   if (result != 2) {
       fprintf(stderr, "파일 읽기 오류: 읽은 항목 수 %d\n", result);
   }

파일 쓰기 중단 처리


파일 쓰기 중 시스템의 리소스가 부족하거나 디스크가 가득 찬 경우 쓰기가 중단될 수 있습니다.

  • 쓰기 확인 방법:
   if (fflush(file) != 0) { // 파일 버퍼를 강제로 비움
       perror("파일 버퍼 비우기 실패");
   }

EOF(End of File) 처리


파일 끝에 도달했는지 확인하는 방법:

while (fscanf(file, "%s", buffer) != EOF) {
    printf("읽은 데이터: %s\n", buffer);
}
  • EOF는 파일의 끝을 나타내는 상수입니다.
  • feof 함수로 파일 끝인지 확인할 수 있습니다:
   if (feof(file)) {
       printf("파일 끝에 도달했습니다.\n");
   }

파일 상태 확인


파일 작업 중 상태를 확인하려면 다음 함수를 사용할 수 있습니다:

  1. ferror: 파일 작업 중 오류가 발생했는지 확인합니다.
   if (ferror(file)) {
       perror("파일 작업 중 오류 발생");
       clearerr(file); // 오류 플래그를 재설정
   }
  1. feof: 파일의 끝에 도달했는지 확인합니다.
   if (feof(file)) {
       printf("파일 끝에 도달했습니다.\n");
   }

권장 오류 처리 패턴

FILE *file = fopen("data.txt", "r");
if (file == NULL) {
    perror("파일 열기 오류");
    return 1;
}

char buffer[50];
while (fscanf(file, "%49s", buffer) != EOF) {
    if (ferror(file)) {
        perror("파일 읽기 오류");
        break;
    }
    printf("읽은 데이터: %s\n", buffer);
}

fclose(file);

오류 처리의 중요성

  • 프로그램의 안정성을 보장합니다.
  • 예상치 못한 데이터 손실을 방지합니다.
  • 사용자에게 적절한 오류 메시지를 제공하여 문제를 진단할 수 있도록 돕습니다.

파일 입출력 오류 처리는 견고하고 신뢰할 수 있는 프로그램을 작성하는 데 필수적입니다. 오류를 예측하고 처리하면 프로그램의 안정성을 크게 향상시킬 수 있습니다.

fprintf와 fscanf의 유용한 활용법


fprintffscanf는 파일 입출력의 기본을 제공할 뿐만 아니라 다양한 응용 사례에서 데이터를 효율적으로 처리할 수 있는 도구입니다. 이 섹션에서는 실제 프로그래밍에서 이 함수들을 활용하는 방법을 살펴봅니다.

데이터 구조 저장 및 로드


데이터 구조를 파일에 저장하고 다시 읽어오는 작업은 데이터 처리 프로그램에서 흔히 사용됩니다.

#include <stdio.h>

typedef struct {
    char name[50];
    int age;
    float height;
} Person;

void savePersonToFile(FILE *file, Person p) {
    fprintf(file, "%s %d %.2f\n", p.name, p.age, p.height);
}

Person loadPersonFromFile(FILE *file) {
    Person p;
    fscanf(file, "%s %d %f", p.name, &p.age, &p.height);
    return p;
}

int main() {
    Person p1 = {"Alice", 25, 170.5};
    FILE *file = fopen("person.txt", "w");
    if (file) {
        savePersonToFile(file, p1);
        fclose(file);
    }

    file = fopen("person.txt", "r");
    if (file) {
        Person p2 = loadPersonFromFile(file);
        printf("Name: %s, Age: %d, Height: %.2f\n", p2.name, p2.age, p2.height);
        fclose(file);
    }
    return 0;
}

로그 파일 생성


프로그램의 실행 상태를 기록하여 디버깅하거나 기록 보관용으로 사용할 수 있습니다.

#include <stdio.h>
#include <time.h>

void writeLog(FILE *logFile, const char *message) {
    time_t now = time(NULL);
    fprintf(logFile, "[%s] %s\n", ctime(&now), message);
}

int main() {
    FILE *logFile = fopen("log.txt", "a");
    if (logFile) {
        writeLog(logFile, "프로그램 시작");
        writeLog(logFile, "작업 완료");
        fclose(logFile);
    }
    return 0;
}

데이터 분석 및 처리


파일로부터 데이터를 읽어와 분석하는 데 fscanf를 사용할 수 있습니다.

#include <stdio.h>

int main() {
    FILE *file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("파일 열기 오류");
        return 1;
    }

    int sum = 0, count = 0, value;
    while (fscanf(file, "%d", &value) != EOF) {
        sum += value;
        count++;
    }
    fclose(file);

    printf("합계: %d, 평균: %.2f\n", sum, (float)sum / count);
    return 0;
}

다중 데이터 유형 처리


파일에 서로 다른 데이터 유형을 저장하고 다시 읽어오는 예제입니다.

#include <stdio.h>

int main() {
    FILE *file = fopen("mixed_data.txt", "w");
    if (file) {
        fprintf(file, "%s %d %.2f\n", "Item1", 100, 12.5);
        fprintf(file, "%s %d %.2f\n", "Item2", 200, 8.99);
        fclose(file);
    }

    file = fopen("mixed_data.txt", "r");
    if (file) {
        char name[50];
        int quantity;
        float price;
        while (fscanf(file, "%s %d %f", name, &quantity, &price) != EOF) {
            printf("Name: %s, Quantity: %d, Price: %.2f\n", name, quantity, price);
        }
        fclose(file);
    }
    return 0;
}

유용한 팁

  • 데이터를 구조화하기 위해 파일 포맷을 설계합니다. 예: CSV, JSON, XML.
  • fprintffscanf를 활용해 간단한 파일 기반 데이터베이스를 구현할 수 있습니다.
  • 데이터 읽기/쓰기 작업을 캡슐화하여 코드 가독성을 높이고 재사용성을 증대시킵니다.

fprintffscanf는 간단하면서도 강력한 도구로, 데이터를 처리하고 저장하는 작업을 체계적이고 효율적으로 수행할 수 있습니다. 이러한 함수들을 적절히 활용하면 프로그램의 기능을 확장할 수 있습니다.

포맷 문자열의 사용 주의점


fprintffscanf에서 포맷 문자열은 데이터를 출력하거나 입력 형식을 지정하는 핵심 요소입니다. 하지만 잘못된 포맷 문자열 사용은 예상치 못한 오류나 심각한 보안 문제를 초래할 수 있습니다. 안전하고 효과적으로 포맷 문자열을 사용하는 방법과 주의사항을 알아봅니다.

포맷 문자열의 주요 구성 요소


포맷 문자열은 다음과 같은 형식 지정자를 포함합니다:

  • %d, %i: 정수
  • %f, %.2f: 부동소수점 수
  • %s: 문자열
  • %c: 문자
  • %x, %o: 16진수, 8진수
  • %p: 포인터 주소

주의 사항 및 안전한 사용법

1. 입력 데이터 크기 제한


%s 형식 지정자는 문자열 입력에서 버퍼 오버플로를 초래할 수 있습니다. 이를 방지하려면 최대 길이를 지정하세요.

char buffer[50];
fscanf(file, "%49s", buffer); // 최대 49자까지만 읽음

이렇게 하면 메모리 초과 접근으로 인한 프로그램 충돌을 방지할 수 있습니다.

2. 출력 포맷의 명확한 정의


포맷 문자열에서 출력의 형태를 명확히 지정해야 합니다.

fprintf(file, "Value: %.2f\n", 123.4567); // 소수점 이하 2자리만 출력

부정확하거나 불완전한 포맷 정의는 예상치 못한 출력 결과를 초래할 수 있습니다.

3. 포맷 문자열에 외부 입력 사용 금지


외부 입력을 포맷 문자열로 직접 사용하는 것은 보안 취약점(포맷 문자열 공격)을 초래할 수 있습니다.

// 잘못된 예
fprintf(file, user_input); // user_input에 "%s %s"가 포함되면 예상치 못한 동작 발생

대신, 포맷 문자열을 명확히 정의하세요.

fprintf(file, "%s", user_input); // 안전한 사용법

4. 데이터 타입 일치 확인


포맷 지정자와 데이터 타입이 일치하지 않으면 런타임 오류가 발생할 수 있습니다.

int value = 123;
fprintf(file, "%f", value); // 잘못된 예

정확한 데이터 타입에 맞는 형식 지정자를 사용하세요.

fprintf(file, "%d", value); // 올바른 예

포맷 문자열의 고급 사용

1. 동적 폭 및 정밀도 설정


포맷 문자열에서 폭이나 정밀도를 동적으로 지정할 수 있습니다.

int width = 10;
fprintf(file, "%*d\n", width, 42); // 폭 10으로 정수 출력

2. 사용자 정의 포맷 생성


데이터 구조의 특정 형식을 포맷 문자열로 정의할 수 있습니다.

typedef struct {
    char name[50];
    int age;
} Person;

void savePerson(FILE *file, Person p) {
    fprintf(file, "Name: %s, Age: %d\n", p.name, p.age);
}

포맷 문자열 오류 방지 팁

  1. 포맷 문자열을 정적 또는 하드코딩된 값으로 유지하세요.
  2. 가변 인수와 포맷 문자열의 매칭을 검증하세요.
  3. 컴파일러 경고(-Wall, -Wformat-security 등)를 활성화하여 포맷 문자열 관련 오류를 감지하세요.

요약


포맷 문자열은 파일 입출력에서 데이터를 구조화하고 표현하는 강력한 도구입니다. 하지만 부주의한 사용은 프로그램 오류나 보안 취약점을 초래할 수 있으므로, 포맷 문자열의 작성과 사용 시 안전성을 항상 고려해야 합니다. 적절한 방식을 활용하면 fprintffscanf의 기능을 최대한 활용할 수 있습니다.

대안 입출력 함수 비교


C 언어에서는 fprintffscanf 외에도 다양한 입출력 함수를 제공하여 특정 상황에 더 적합한 방법을 선택할 수 있습니다. 이 섹션에서는 fgets, fputs와 같은 대안 함수들과 fprintf, fscanf를 비교하며, 각 함수의 특징과 적합한 용도를 설명합니다.

fprintf와 fscanf의 특징

  • 장점
  • 포맷 문자열을 사용해 데이터를 정밀하게 출력 및 입력할 수 있습니다.
  • 여러 데이터 유형을 한 번에 처리할 수 있습니다.
  • 단점
  • 파일 포맷이 예상과 다를 경우 읽기 오류가 발생할 수 있습니다.
  • 간단한 입출력 작업에서는 상대적으로 복잡할 수 있습니다.

fgets와 fputs

  • fgets: 파일에서 문자열을 한 줄씩 읽습니다.
  • fputs: 파일에 문자열을 한 줄씩 씁니다.

사용 예제:

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file) {
        fputs("Hello, World!\n", file); // 문자열 쓰기
        fputs("C programming is fun.\n", file);
        fclose(file);
    }

    file = fopen("example.txt", "r");
    if (file) {
        char buffer[100];
        while (fgets(buffer, sizeof(buffer), file)) { // 한 줄 읽기
            printf("%s", buffer);
        }
        fclose(file);
    }
    return 0;
}

비교

함수장점단점
fprintf다양한 데이터 유형 처리 가능포맷 문자열의 정확성이 필요함
fscanf포맷 문자열로 구조적 데이터 읽기 가능데이터 포맷 불일치 시 오류 가능
fputs간단한 문자열 쓰기에 적합포맷화된 데이터 출력 불가
fgets한 줄씩 데이터를 읽기에 편리문자열 이외 데이터 처리 불가

getc와 putc

  • getc: 파일에서 문자를 한 번에 한 개씩 읽습니다.
  • putc: 파일에 문자를 한 번에 한 개씩 씁니다.

사용 예제:

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file) {
        putc('A', file); // 문자 쓰기
        putc('B', file);
        fclose(file);
    }

    file = fopen("example.txt", "r");
    if (file) {
        char ch;
        while ((ch = getc(file)) != EOF) { // 문자 읽기
            putchar(ch);
        }
        fclose(file);
    }
    return 0;
}

비교

함수장점단점
putc단일 문자 쓰기에 적합다량의 데이터 처리에는 비효율적
getc단일 문자 읽기에 적합문자열 및 구조적 데이터 처리 불가

scanf와 printf


scanfprintf는 표준 입출력에 사용되며, fscanffprintf의 콘솔 버전이라고 할 수 있습니다.

  • scanf: 표준 입력(stdin)에서 형식화된 데이터 읽기.
  • printf: 표준 출력(stdout)에 형식화된 데이터 쓰기.

어떤 함수를 선택해야 할까?

  1. 구조화된 데이터 처리:
  • fprintffscanf는 데이터의 구조적 처리와 파일 포맷이 중요한 경우에 적합합니다.
  1. 간단한 문자열 입출력:
  • fgetsfputs는 텍스트 기반 파일을 다룰 때 간단하고 직관적입니다.
  1. 단일 문자 처리:
  • getcputc는 개별 문자 처리나 바이너리 데이터 처리에 유용합니다.
  1. 콘솔 입출력:
  • scanfprintf는 파일이 아닌 콘솔 입출력 작업에 적합합니다.

각 함수는 목적에 따라 효율적으로 활용할 수 있으며, 프로그램의 요구사항에 따라 적절히 조합하여 사용하면 입출력 작업을 더 쉽게 처리할 수 있습니다.

연습 문제 및 코드 예제


fprintffscanf를 활용한 파일 입출력의 이해를 돕기 위해 연습 문제와 예제를 제공합니다. 이 문제들은 실전에서 자주 접할 수 있는 데이터 처리 시나리오를 포함하고 있습니다.

문제 1: 학생 정보 저장 및 읽기


요구사항:

  • 사용자로부터 학생의 이름, 나이, 성적을 입력받아 파일에 저장합니다.
  • 파일에 저장된 데이터를 다시 읽어와 화면에 출력합니다.

코드 예제:

#include <stdio.h>

typedef struct {
    char name[50];
    int age;
    float grade;
} Student;

void saveStudentToFile(FILE *file, Student s) {
    fprintf(file, "%s %d %.2f\n", s.name, s.age, s.grade);
}

void loadStudentsFromFile(FILE *file) {
    Student s;
    while (fscanf(file, "%49s %d %f", s.name, &s.age, &s.grade) != EOF) {
        printf("Name: %s, Age: %d, Grade: %.2f\n", s.name, s.age, s.grade);
    }
}

int main() {
    FILE *file = fopen("students.txt", "w");
    if (file == NULL) {
        perror("파일 열기 오류");
        return 1;
    }

    Student s1 = {"Alice", 20, 85.5};
    Student s2 = {"Bob", 22, 90.0};
    saveStudentToFile(file, s1);
    saveStudentToFile(file, s2);
    fclose(file);

    file = fopen("students.txt", "r");
    if (file) {
        loadStudentsFromFile(file);
        fclose(file);
    }

    return 0;
}

문제 2: 판매 데이터 분석


요구사항:

  • 판매 데이터가 파일에 저장되어 있습니다. 각 줄에는 상품명, 판매 수량, 가격이 기록됩니다.
  • 데이터를 읽어 총 판매 금액을 계산하고 출력합니다.

코드 예제:

#include <stdio.h>

int main() {
    FILE *file = fopen("sales.txt", "r");
    if (file == NULL) {
        perror("파일 열기 오류");
        return 1;
    }

    char itemName[50];
    int quantity;
    float price, total = 0.0;

    printf("Sales Data:\n");
    printf("----------------------------\n");
    printf("Item\tQuantity\tPrice\tTotal\n");
    while (fscanf(file, "%49s %d %f", itemName, &quantity, &price) != EOF) {
        float itemTotal = quantity * price;
        total += itemTotal;
        printf("%s\t%d\t\t%.2f\t%.2f\n", itemName, quantity, price, itemTotal);
    }
    fclose(file);

    printf("----------------------------\n");
    printf("Total Sales: %.2f\n", total);

    return 0;
}

문제 3: 텍스트 데이터 수정


요구사항:

  • 텍스트 파일에서 특정 단어를 찾아 다른 단어로 바꿉니다.
  • 수정된 데이터를 새 파일에 저장합니다.

코드 예제:

#include <stdio.h>
#include <string.h>

int main() {
    FILE *inputFile = fopen("input.txt", "r");
    FILE *outputFile = fopen("output.txt", "w");
    if (inputFile == NULL || outputFile == NULL) {
        perror("파일 열기 오류");
        return 1;
    }

    char word[50];
    while (fscanf(inputFile, "%49s", word) != EOF) {
        if (strcmp(word, "oldWord") == 0) {
            fprintf(outputFile, "%s ", "newWord");
        } else {
            fprintf(outputFile, "%s ", word);
        }
    }

    fclose(inputFile);
    fclose(outputFile);

    printf("단어 치환 작업이 완료되었습니다.\n");
    return 0;
}

문제 4: CSV 파일 처리


요구사항:

  • CSV 파일을 읽어 데이터를 분석합니다.
  • 각 행의 값을 더하고 결과를 출력합니다.

코드 예제:

#include <stdio.h>

int main() {
    FILE *file = fopen("data.csv", "r");
    if (file == NULL) {
        perror("파일 열기 오류");
        return 1;
    }

    char line[100];
    while (fgets(line, sizeof(line), file)) {
        int sum = 0, value;
        char *token = strtok(line, ",");
        while (token) {
            sscanf(token, "%d", &value);
            sum += value;
            token = strtok(NULL, ",");
        }
        printf("Row Sum: %d\n", sum);
    }

    fclose(file);
    return 0;
}

연습 문제를 통해 배울 점

  • 파일 입출력의 기본 흐름(열기, 읽기/쓰기, 닫기).
  • fprintffscanf를 활용한 구조적 데이터 처리.
  • 다양한 데이터 형식(텍스트, CSV 등)을 다루는 방법.
  • 간단한 데이터 분석과 파일 수정 작업.

위 연습 문제들을 해결하면 파일 입출력과 데이터 처리 능력을 강화할 수 있습니다.

요약


본 기사에서는 C 언어에서 fprintffscanf를 활용한 형식화된 입출력 처리의 기본 개념, 사용법, 응용 사례를 다뤘습니다. 주요 내용으로는 데이터 저장 및 읽기, 포맷 문자열의 안전한 사용, 파일 입출력 오류 처리, 대안 함수 비교, 실전 예제 등을 포함했습니다. 이를 통해 파일 기반 데이터 처리와 분석에서의 효율성을 높이는 방법을 이해할 수 있습니다.

목차