C언어에서 파일 입출력과 문자열 처리 결합하기

C언어에서 파일 입출력과 문자열 처리는 데이터 관리와 가공에서 핵심적인 역할을 합니다. 본 기사에서는 파일 입출력의 기본적인 사용법부터 문자열 처리와의 결합 방법, 실용적인 예제까지 단계적으로 살펴봅니다. 이를 통해 효율적인 데이터 처리 코드를 작성하는 방법을 배울 수 있습니다.

목차
  1. 파일 입출력의 기본 개념
    1. 파일 포인터와 파일 모드
    2. 파일 읽기와 쓰기
    3. 파일 닫기
    4. 예제 코드
  2. 문자열 처리의 기본 개념
    1. 문자열의 정의와 초기화
    2. 주요 문자열 함수
    3. 예제: 문자열 길이 계산
    4. 문자열 처리와 메모리 관리
    5. 문자열의 입출력
  3. 파일 입출력과 문자열 처리의 결합
    1. 파일에서 문자열 읽기
    2. 예제: 파일에서 한 줄 읽기
    3. 문자열 데이터 가공
    4. 예제: 문자열 공백 제거
    5. 가공한 문자열 파일에 저장
    6. 예제: 파일에 문자열 저장
    7. 파일 입출력과 문자열 처리의 워크플로우
  4. 실용적인 응용 예제
    1. 문제 정의
    2. 코드 구현
    3. 코드 설명
    4. 실행 결과
  5. 파일 오류 처리
    1. 파일 열기 오류 확인
    2. 예제: 파일 열기 오류 처리
    3. 파일 읽기 오류 처리
    4. 예제: 읽기 오류 확인
    5. 파일 쓰기 오류 처리
    6. 예제: 쓰기 오류 확인
    7. 일반적인 오류 원인과 해결책
    8. 에러 처리를 통한 안정성 향상
  6. 문자열 검색과 대체
    1. 문자열 검색
    2. 예제: 파일에서 특정 문자열 검색
    3. 문자열 대체
    4. 예제: 파일의 문자열 대체
    5. 코드 설명
    6. 응용 사례
    7. 결론
  7. 성능 최적화 기법
    1. 버퍼링을 활용한 최적화
    2. 예제: 버퍼 크기 설정
    3. 메모리 할당 최적화
    4. 예제: 동적 메모리 사용
    5. 파일 읽기/쓰기 병렬 처리
    6. 예제: 다중 쓰레드를 이용한 파일 처리 (POSIX)
    7. 불필요한 작업 최소화
    8. 최적화 요약
    9. 결론
  8. 실습 문제
    1. 문제 1: 단어 빈도수 계산
    2. 문제 2: 특정 단어 치환
    3. 문제 3: 숫자 데이터 분석
    4. 문제 4: 줄 번호 추가
    5. 실습 문제 활용법
  9. 요약

파일 입출력의 기본 개념


C언어에서 파일 입출력은 데이터를 외부 파일로 저장하거나 외부 파일에서 데이터를 읽어오는 과정을 의미합니다. 이를 통해 프로그램이 데이터를 영구적으로 저장하거나 읽을 수 있습니다.

파일 포인터와 파일 모드


C언어에서 파일 입출력은 FILE 구조체를 사용하는 파일 포인터를 통해 이루어집니다.
파일을 열 때는 fopen() 함수를 사용하며, 열기 모드로 파일 작업의 종류를 지정합니다.

  • “r” (읽기): 파일을 읽기 전용으로 엽니다. 파일이 존재하지 않으면 오류를 반환합니다.
  • “w” (쓰기): 파일을 쓰기 전용으로 엽니다. 파일이 없으면 생성하고, 존재하면 내용을 덮어씁니다.
  • “a” (추가): 파일을 쓰기 전용으로 열며, 파일 끝에 데이터를 추가합니다.

파일 읽기와 쓰기


C언어에서 데이터를 파일에 쓰거나 파일에서 읽기 위해 다양한 함수를 제공합니다.

  • fprintf(): 파일에 포맷화된 데이터를 씁니다.
  • fscanf(): 파일에서 포맷화된 데이터를 읽습니다.
  • fgets(): 파일에서 한 줄을 읽습니다.
  • fputs(): 파일에 한 줄을 씁니다.

파일 닫기


작업이 끝난 후에는 반드시 fclose() 함수를 사용하여 파일을 닫아야 합니다. 이는 시스템 자원을 해제하고 데이터 손상을 방지합니다.

예제 코드

#include <stdio.h>

int main() {
    FILE *file = fopen("example.txt", "w");
    if (file == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return 1;
    }

    fprintf(file, "Hello, World!\n");
    fclose(file);
    printf("파일 작성이 완료되었습니다.\n");

    return 0;
}


위 코드는 “example.txt” 파일에 “Hello, World!”라는 내용을 작성한 후 파일을 닫습니다.

문자열 처리의 기본 개념


C언어에서 문자열은 문자 배열로 표현되며, 다양한 내장 함수와 기법을 통해 처리할 수 있습니다. 문자열 처리는 파일 입출력과 결합하여 데이터 가공에 유용하게 활용됩니다.

문자열의 정의와 초기화


문자열은 문자 배열로 선언하며, 끝에 \0(널 문자)이 포함됩니다.

char str1[] = "Hello";
char str2[10] = "World";

주요 문자열 함수


C언어는 문자열을 처리하기 위한 다양한 함수를 제공합니다.

  • strlen(): 문자열의 길이를 반환합니다.
  • strcpy(): 문자열을 복사합니다.
  • strcat(): 두 문자열을 연결합니다.
  • strcmp(): 두 문자열을 비교합니다.
  • strchr(): 문자열에서 특정 문자의 위치를 찾습니다.
  • strstr(): 문자열에서 특정 문자열을 검색합니다.

예제: 문자열 길이 계산

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

int main() {
    char str[] = "C programming";
    printf("문자열의 길이: %lu\n", strlen(str));
    return 0;
}

문자열 처리와 메모리 관리


C언어에서 문자열은 고정된 크기의 배열에 저장되므로, 적절한 크기를 지정하거나 동적 메모리를 사용해야 합니다. 동적 메모리는 malloc()free()를 통해 관리할 수 있습니다.

문자열의 입출력


C언어에서 문자열은 표준 입출력 함수로 처리할 수 있습니다.

  • printf(): 문자열을 출력합니다.
  • scanf(): 문자열을 입력받습니다.
  • gets()fgets(): 문자열의 전체 줄을 입력받습니다.
char str[100];
printf("문자열 입력: ");
fgets(str, sizeof(str), stdin);
printf("입력된 문자열: %s", str);

문자열 처리는 다양한 데이터 가공과 저장 작업의 기본이 되며, 파일 입출력과 결합하여 더욱 강력한 응용 프로그램을 작성할 수 있습니다.

파일 입출력과 문자열 처리의 결합


파일 입출력과 문자열 처리를 결합하면 파일에서 데이터를 읽어와 필요한 대로 변환하거나 가공한 뒤 다시 저장하는 작업이 가능합니다. 이러한 작업은 데이터 분석, 로깅, 설정 파일 처리 등 다양한 응용 분야에서 사용됩니다.

파일에서 문자열 읽기


파일에서 문자열을 읽어와 가공하는 과정은 fgets()와 같은 함수를 통해 수행됩니다. 이 함수는 파일에서 한 줄씩 읽어들입니다.

예제: 파일에서 한 줄 읽기

#include <stdio.h>

int main() {
    FILE *file = fopen("input.txt", "r");
    if (file == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return 1;
    }

    char line[100];
    while (fgets(line, sizeof(line), file) != NULL) {
        printf("읽은 내용: %s", line);
    }

    fclose(file);
    return 0;
}

문자열 데이터 가공


읽어온 문자열을 가공하기 위해 C언어의 문자열 함수를 활용합니다. 예를 들어, 공백을 제거하거나 특정 단어를 치환하는 작업을 수행할 수 있습니다.

예제: 문자열 공백 제거

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

void removeSpaces(char *str) {
    char *p1 = str, *p2 = str;
    while (*p1) {
        if (*p1 != ' ') {
            *p2++ = *p1;
        }
        p1++;
    }
    *p2 = '\0';
}

가공한 문자열 파일에 저장


가공된 문자열 데이터를 파일에 저장하려면 fprintf()fputs()와 같은 함수를 사용합니다.

예제: 파일에 문자열 저장

#include <stdio.h>

int main() {
    FILE *file = fopen("output.txt", "w");
    if (file == NULL) {
        printf("파일을 열 수 없습니다.\n");
        return 1;
    }

    char processedData[] = "Processed String Data";
    fprintf(file, "%s\n", processedData);
    fclose(file);

    printf("가공된 데이터를 파일에 저장했습니다.\n");
    return 0;
}

파일 입출력과 문자열 처리의 워크플로우

  1. 파일 열기: 파일을 읽기(r) 또는 쓰기(w) 모드로 엽니다.
  2. 문자열 읽기: 파일에서 데이터를 읽어 문자열로 저장합니다.
  3. 문자열 가공: 필요한 변환 작업을 수행합니다.
  4. 파일 쓰기: 가공된 데이터를 파일에 저장합니다.
  5. 파일 닫기: 작업이 끝난 후 파일을 닫아 자원을 해제합니다.

이 결합 작업을 통해 데이터를 읽고, 변환하고, 저장하는 과정을 자동화할 수 있습니다. 이는 실무에서 매우 유용한 기술입니다.

실용적인 응용 예제


이번 섹션에서는 파일 입출력과 문자열 처리를 결합하여 학생 점수 데이터를 처리하는 실용적인 코드를 작성해 봅니다. 이 예제는 파일에서 데이터를 읽고, 평균 점수를 계산한 뒤 결과를 다시 파일에 저장하는 과정을 포함합니다.

문제 정의

  1. 입력 파일: scores.txt
  • 파일에는 학생 이름과 점수가 한 줄씩 저장되어 있습니다.
  • 예:
    Alice 85 Bob 90 Charlie 78
  1. 출력 파일: results.txt
  • 각 학생의 이름과 점수를 출력하고, 마지막 줄에 평균 점수를 추가합니다.

코드 구현


아래 코드는 위의 요구사항을 처리하는 전체 과정을 보여줍니다.

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

int main() {
    FILE *inputFile = fopen("scores.txt", "r");
    if (inputFile == NULL) {
        printf("입력 파일을 열 수 없습니다.\n");
        return 1;
    }

    FILE *outputFile = fopen("results.txt", "w");
    if (outputFile == NULL) {
        printf("출력 파일을 열 수 없습니다.\n");
        fclose(inputFile);
        return 1;
    }

    char name[50];
    int score, totalScore = 0, count = 0;

    fprintf(outputFile, "학생 점수 목록:\n");

    while (fscanf(inputFile, "%s %d", name, &score) != EOF) {
        fprintf(outputFile, "%s: %d\n", name, score);
        totalScore += score;
        count++;
    }

    if (count > 0) {
        float average = (float)totalScore / count;
        fprintf(outputFile, "\n평균 점수: %.2f\n", average);
    } else {
        fprintf(outputFile, "\n학생 데이터가 없습니다.\n");
    }

    fclose(inputFile);
    fclose(outputFile);

    printf("처리가 완료되었습니다. 결과는 results.txt에 저장되었습니다.\n");

    return 0;
}

코드 설명

  1. 파일 열기:
  • scores.txt에서 데이터를 읽기 위해 fopen()을 사용합니다.
  • 결과를 저장할 results.txt를 쓰기 모드로 엽니다.
  1. 데이터 읽기:
  • fscanf()를 사용하여 파일에서 이름과 점수를 한 줄씩 읽습니다.
  1. 점수 계산:
  • 읽은 점수를 누적하여 총합을 계산하고 학생 수를 카운트합니다.
  1. 데이터 저장:
  • 각 학생의 이름과 점수를 출력 파일에 기록합니다.
  • 평균 점수를 계산하여 마지막 줄에 추가합니다.
  1. 파일 닫기:
  • 모든 작업이 끝난 후 파일을 닫아 시스템 자원을 해제합니다.

실행 결과


입력 파일 scores.txt의 내용:

Alice 85  
Bob 90  
Charlie 78  

출력 파일 results.txt의 내용:

학생 점수 목록:  
Alice: 85  
Bob: 90  
Charlie: 78  

평균 점수: 84.33

이 예제를 통해 파일 입출력과 문자열 처리를 결합하여 데이터를 읽고, 가공하고, 저장하는 전체 워크플로우를 경험할 수 있습니다.

파일 오류 처리


C언어에서 파일 입출력 작업 중 오류가 발생할 수 있습니다. 파일을 열 수 없거나 읽기/쓰기 중 문제가 생기면 프로그램은 예상치 못한 동작을 하게 됩니다. 이를 방지하기 위해 파일 오류를 확인하고 처리하는 방법을 알아봅니다.

파일 열기 오류 확인


fopen() 함수가 NULL을 반환하는 경우, 파일을 열 수 없다는 뜻입니다. 이는 파일 경로가 잘못되었거나 파일이 존재하지 않을 때 발생합니다.

예제: 파일 열기 오류 처리

#include <stdio.h>

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

    fclose(file);
    return 0;
}
  • perror() 함수는 오류 메시지를 출력하며, 시스템 오류 메시지를 함께 표시합니다.

파일 읽기 오류 처리


fread(), fgets(), fscanf()와 같은 함수는 읽기 작업 중 오류가 발생하면 반환값으로 실패를 알립니다. 이 반환값을 확인하여 읽기 작업이 정상적으로 완료되었는지 판단할 수 있습니다.

예제: 읽기 오류 확인

#include <stdio.h>

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

    char buffer[100];
    if (fgets(buffer, sizeof(buffer), file) == NULL) {
        if (feof(file)) {
            printf("파일 끝에 도달했습니다.\n");
        } else {
            perror("읽기 오류");
        }
    } else {
        printf("읽은 내용: %s", buffer);
    }

    fclose(file);
    return 0;
}

파일 쓰기 오류 처리


fwrite()fprintf()와 같은 함수가 쓰기 작업 중 오류를 반환할 수 있습니다. 쓰기 작업 후 반환값을 확인하여 처리 상태를 판단해야 합니다.

예제: 쓰기 오류 확인

#include <stdio.h>

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

    if (fprintf(file, "Hello, World!\n") < 0) {
        perror("쓰기 오류");
        fclose(file);
        return 1;
    }

    fclose(file);
    printf("파일 쓰기가 완료되었습니다.\n");
    return 0;
}

일반적인 오류 원인과 해결책

  1. 파일이 존재하지 않음
  • 파일을 열기 전에 존재 여부를 확인하거나 fopen()을 “w” 모드로 사용해 새 파일을 생성합니다.
  1. 경로 오류
  • 잘못된 파일 경로를 사용했을 가능성이 있습니다. 상대 경로 대신 절대 경로를 사용하거나 디렉토리 구성을 확인합니다.
  1. 파일 권한 부족
  • 읽기 전용 파일에 쓰기 작업을 시도하거나, 파일에 접근할 권한이 없는 경우입니다. 파일 권한을 확인하고 적절히 수정합니다.
  1. 디스크 공간 부족
  • 파일 쓰기 중 디스크 공간이 부족할 수 있습니다. 이 경우 시스템의 사용 가능한 디스크 공간을 확인하고 확보합니다.

에러 처리를 통한 안정성 향상


파일 입출력 작업의 오류 처리는 프로그램의 안정성을 크게 향상시킵니다. 위의 방법들을 통해 파일 관련 오류를 식별하고 적절히 처리하면 예기치 않은 문제를 예방할 수 있습니다.

문자열 검색과 대체


파일에서 특정 문자열을 검색하고 대체하는 작업은 텍스트 데이터 처리에서 자주 사용됩니다. 예를 들어, 로그 파일에서 특정 단어를 찾거나 설정 파일의 값을 업데이트할 때 활용할 수 있습니다.

문자열 검색


파일 내에서 특정 문자열을 검색하려면 fgets()로 파일의 각 줄을 읽고 strstr()를 사용하여 문자열이 포함되어 있는지 확인합니다.

예제: 파일에서 특정 문자열 검색

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

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

    char line[256];
    char keyword[] = "target";
    int lineNumber = 0;

    while (fgets(line, sizeof(line), file) != NULL) {
        lineNumber++;
        if (strstr(line, keyword) != NULL) {
            printf("라인 %d에서 '%s' 발견: %s", lineNumber, keyword, line);
        }
    }

    fclose(file);
    return 0;
}
  • strstr()는 문자열에서 검색할 키워드가 처음 등장하는 위치를 반환하며, 없다면 NULL을 반환합니다.

문자열 대체


문자열 대체는 특정 문자열을 다른 문자열로 바꿉니다. 파일 내에서 변경 작업을 수행하려면 파일 내용을 메모리에 읽어들여 수정한 뒤, 다시 파일에 저장하는 방식으로 진행합니다.

예제: 파일의 문자열 대체

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

void replaceString(char *line, const char *oldWord, const char *newWord) {
    char buffer[256];
    char *pos;

    while ((pos = strstr(line, oldWord)) != NULL) {
        int len = pos - line;
        strncpy(buffer, line, len);
        buffer[len] = '\0';

        strcat(buffer, newWord);
        strcat(buffer, pos + strlen(oldWord));

        strcpy(line, buffer);
    }
}

int main() {
    FILE *inputFile = fopen("data.txt", "r");
    FILE *outputFile = fopen("output.txt", "w");

    if (inputFile == NULL || outputFile == NULL) {
        perror("파일 열기 오류");
        return 1;
    }

    char line[256];
    char oldWord[] = "old";
    char newWord[] = "new";

    while (fgets(line, sizeof(line), inputFile) != NULL) {
        replaceString(line, oldWord, newWord);
        fputs(line, outputFile);
    }

    fclose(inputFile);
    fclose(outputFile);

    printf("문자열 대체 완료. 결과는 output.txt에 저장되었습니다.\n");
    return 0;
}

코드 설명

  1. 검색 및 위치 확인
  • strstr()를 사용하여 문자열에서 대체할 단어의 위치를 확인합니다.
  1. 문자열 재구성
  • strncpy()로 대체 전까지의 문자열을 복사하고, 대체 단어를 삽입한 뒤, 남은 문자열을 이어 붙입니다.
  1. 파일 갱신
  • 수정된 문자열을 출력 파일에 기록합니다.

응용 사례

  1. 로그 파일 분석: 특정 키워드를 검색하여 중요 정보를 추출합니다.
  2. 설정 파일 수정: 특정 설정 값을 업데이트합니다.
  3. 텍스트 데이터 정리: 특정 단어나 구문을 표준화된 형태로 대체합니다.

결론


문자열 검색과 대체는 파일 데이터 처리에서 강력한 도구로, 간단한 코드 변경으로 다양한 형태의 텍스트 데이터를 처리할 수 있습니다. 위 예제를 통해 효율적인 검색과 대체 작업을 구현할 수 있습니다.

성능 최적화 기법


파일 입출력과 문자열 처리는 효율성이 중요한 작업입니다. 대량의 데이터를 처리하거나 성능이 요구되는 환경에서 최적화된 코드를 작성하는 방법을 알아봅니다.

버퍼링을 활용한 최적화


파일 입출력은 디스크 I/O와 관련이 있어 시간이 오래 걸릴 수 있습니다. 이를 줄이기 위해 버퍼를 사용하여 데이터를 한 번에 처리하는 방식이 효과적입니다.

  • setvbuf(): 파일 스트림에 버퍼를 설정합니다.
  • 기본적으로 표준 입출력은 버퍼링되지만, 직접 버퍼 크기를 조정하여 성능을 개선할 수 있습니다.

예제: 버퍼 크기 설정

#include <stdio.h>

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

    char buffer[8192]; // 8KB 버퍼
    setvbuf(file, buffer, _IOFBF, sizeof(buffer));

    char line[256];
    while (fgets(line, sizeof(line), file) != NULL) {
        // 처리 작업
    }

    fclose(file);
    return 0;
}

메모리 할당 최적화


문자열 처리에서 메모리 재할당이 자주 발생하면 성능이 저하될 수 있습니다. 동적 메모리를 사용할 때는 초기 크기를 적절히 설정하고, 필요한 경우에만 확장합니다.

예제: 동적 메모리 사용

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

int main() {
    char *data = malloc(1024); // 초기 메모리 할당
    if (data == NULL) {
        perror("메모리 할당 실패");
        return 1;
    }

    strcpy(data, "초기 데이터");
    printf("%s\n", data);

    // 필요 시 크기 확장
    data = realloc(data, 2048);
    if (data == NULL) {
        perror("메모리 재할당 실패");
        return 1;
    }

    strcat(data, " - 추가 데이터");
    printf("%s\n", data);

    free(data);
    return 0;
}

파일 읽기/쓰기 병렬 처리


대량의 파일 데이터를 처리할 때는 다중 쓰레드나 비동기 처리를 통해 입출력 속도를 높일 수 있습니다.

예제: 다중 쓰레드를 이용한 파일 처리 (POSIX)

#include <stdio.h>
#include <pthread.h>

void *readFile(void *arg) {
    FILE *file = fopen((char *)arg, "r");
    if (file == NULL) {
        perror("파일 열기 오류");
        return NULL;
    }

    char line[256];
    while (fgets(line, sizeof(line), file) != NULL) {
        printf("읽은 내용: %s", line);
    }

    fclose(file);
    return NULL;
}

int main() {
    pthread_t thread1, thread2;

    pthread_create(&thread1, NULL, readFile, "file1.txt");
    pthread_create(&thread2, NULL, readFile, "file2.txt");

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    return 0;
}

불필요한 작업 최소화

  1. 중복 작업 제거: 동일한 데이터를 여러 번 읽거나 가공하지 않도록 설계합니다.
  2. 필요한 데이터만 읽기: 전체 파일을 읽기보다 필요한 데이터만 검색합니다.

최적화 요약

  • 버퍼링: 파일 입출력에서 큰 버퍼를 사용하여 성능을 향상시킵니다.
  • 메모리 관리: 문자열 처리에서 동적 메모리를 적절히 관리합니다.
  • 병렬 처리: 다중 쓰레드를 활용하여 작업 속도를 높입니다.
  • 작업 최소화: 중복 작업과 불필요한 데이터 처리를 줄입니다.

결론


성능 최적화는 단순한 작업 속도를 넘어 프로그램의 확장성과 안정성에 영향을 미칩니다. 위의 최적화 기법을 적절히 조합하여 파일 입출력과 문자열 처리 작업의 성능을 극대화할 수 있습니다.

실습 문제


파일 입출력과 문자열 처리에 대한 이해를 심화하기 위해 다음과 같은 실습 문제를 제공합니다. 이 문제는 지금까지 다룬 내용을 직접 구현해보며 학습 효과를 높이기 위한 것입니다.

문제 1: 단어 빈도수 계산


문제 설명

  1. 텍스트 파일(input.txt)에서 각 단어의 빈도를 계산합니다.
  2. 결과를 새로운 파일(output.txt)에 저장합니다.
  3. 단어는 대소문자를 구분하지 않습니다.

예제 입력 (input.txt)

Hello world hello
This is a test. Hello World!

예제 출력 (output.txt)

hello: 3  
world: 2  
this: 1  
is: 1  
a: 1  
test: 1  

힌트

  • 파일에서 단어를 읽어오려면 fscanf()를 사용하세요.
  • 문자열을 소문자로 변환하려면 tolower()를 활용하세요.
  • 단어와 빈도를 저장하기 위해 배열이나 구조체를 사용할 수 있습니다.

문제 2: 특정 단어 치환


문제 설명

  1. 텍스트 파일(data.txt)에서 특정 단어(예: “old”)를 다른 단어(예: “new”)로 치환합니다.
  2. 치환된 내용을 원래 파일에 덮어씁니다.

예제 입력 (data.txt)

This is an old file. Old habits die hard.

예제 출력 (data.txt)

This is an new file. New habits die hard.

힌트

  • 파일 내용을 메모리에 읽어온 후 strstr()로 치환 작업을 수행하세요.
  • 파일을 다시 열어 덮어쓰기 모드로 저장하세요.

문제 3: 숫자 데이터 분석


문제 설명

  1. 숫자가 포함된 텍스트 파일(numbers.txt)에서 모든 숫자를 읽어옵니다.
  2. 숫자의 총합, 평균, 최댓값, 최솟값을 계산합니다.
  3. 결과를 출력하거나 파일에 저장합니다.

예제 입력 (numbers.txt)

The temperatures for the week are: 25, 30, 28, 35, 27, 29, 31.

예제 출력

총합: 205  
평균: 29.29  
최댓값: 35  
최솟값: 25  

힌트

  • 숫자는 fscanf()strtok()를 사용해 추출합니다.
  • atoi() 또는 strtol()을 사용하여 문자열을 정수로 변환하세요.

문제 4: 줄 번호 추가


문제 설명

  1. 텍스트 파일(input.txt)의 각 줄 앞에 줄 번호를 추가합니다.
  2. 결과를 새로운 파일(output.txt)에 저장합니다.

예제 입력 (input.txt)

Hello World!  
This is a test.  
C programming is fun.  

예제 출력 (output.txt)

1. Hello World!  
2. This is a test.  
3. C programming is fun.  

힌트

  • fgets()로 파일에서 한 줄씩 읽어와 처리하세요.
  • fprintf()를 사용해 출력 파일에 줄 번호와 함께 기록하세요.

실습 문제 활용법


위 문제들은 파일 입출력과 문자열 처리 기술을 연습하고, 실무에서도 활용 가능한 코드를 작성하는 데 도움을 줍니다. 각 문제를 해결하면서 성능 최적화와 에러 처리를 고려해 보세요.

도전 과제

  • 대용량 파일에서도 성능 저하 없이 작동하도록 구현해 보세요.
  • 멀티스레드를 사용하여 작업을 병렬화하는 방법도 시도해 보세요.

요약


본 기사에서는 C언어에서 파일 입출력과 문자열 처리의 결합 방법을 다뤘습니다. 파일 읽기와 쓰기, 문자열 검색과 대체, 성능 최적화 기법 등 실용적인 코딩 기술을 학습했으며, 실습 문제를 통해 이를 직접 구현하고 응용할 수 있는 기회를 제공했습니다. 효율적이고 안정적인 데이터 처리를 위한 중요한 기술을 익힐 수 있었습니다.

목차
  1. 파일 입출력의 기본 개념
    1. 파일 포인터와 파일 모드
    2. 파일 읽기와 쓰기
    3. 파일 닫기
    4. 예제 코드
  2. 문자열 처리의 기본 개념
    1. 문자열의 정의와 초기화
    2. 주요 문자열 함수
    3. 예제: 문자열 길이 계산
    4. 문자열 처리와 메모리 관리
    5. 문자열의 입출력
  3. 파일 입출력과 문자열 처리의 결합
    1. 파일에서 문자열 읽기
    2. 예제: 파일에서 한 줄 읽기
    3. 문자열 데이터 가공
    4. 예제: 문자열 공백 제거
    5. 가공한 문자열 파일에 저장
    6. 예제: 파일에 문자열 저장
    7. 파일 입출력과 문자열 처리의 워크플로우
  4. 실용적인 응용 예제
    1. 문제 정의
    2. 코드 구현
    3. 코드 설명
    4. 실행 결과
  5. 파일 오류 처리
    1. 파일 열기 오류 확인
    2. 예제: 파일 열기 오류 처리
    3. 파일 읽기 오류 처리
    4. 예제: 읽기 오류 확인
    5. 파일 쓰기 오류 처리
    6. 예제: 쓰기 오류 확인
    7. 일반적인 오류 원인과 해결책
    8. 에러 처리를 통한 안정성 향상
  6. 문자열 검색과 대체
    1. 문자열 검색
    2. 예제: 파일에서 특정 문자열 검색
    3. 문자열 대체
    4. 예제: 파일의 문자열 대체
    5. 코드 설명
    6. 응용 사례
    7. 결론
  7. 성능 최적화 기법
    1. 버퍼링을 활용한 최적화
    2. 예제: 버퍼 크기 설정
    3. 메모리 할당 최적화
    4. 예제: 동적 메모리 사용
    5. 파일 읽기/쓰기 병렬 처리
    6. 예제: 다중 쓰레드를 이용한 파일 처리 (POSIX)
    7. 불필요한 작업 최소화
    8. 최적화 요약
    9. 결론
  8. 실습 문제
    1. 문제 1: 단어 빈도수 계산
    2. 문제 2: 특정 단어 치환
    3. 문제 3: 숫자 데이터 분석
    4. 문제 4: 줄 번호 추가
    5. 실습 문제 활용법
  9. 요약