프로그래밍C 개발자

C 언어에서 파일 스트림 작업 과정을 설명하십시오. 표준 라이브러리를 사용하여 파일을 열고, 읽고, 쓰고, 닫는 방법은 무엇입니까? 파일 작업 시 어떤 문제가 발생할 수 있으며, 이를 어떻게 해결할 수 있습니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

질문 이력:

C 언어에서 파일 작업은 언어의 초기 구현에서부터 나타난 기본적인 기술입니다. C 표준 라이브러리 (stdio.h)는 OS 간에 프로그램을 이식 가능하게 만드는 입력 및 출력 스트림 작업을 위한 범용 함수를 제공합니다.

문제:

초보 프로그래머는 종종 파일 스트림 작업 시 실수를 합니다: 파일 열기 결과를 확인하지 않거나, 버퍼링을 위한 메모리를 잘못 관리하거나, 읽기 또는 쓰기 오류를 처리하지 않거나, 파일을 닫는 과정에서 리소스 누수가 발생할 수 있습니다. 버퍼를 잘못 다루면 데이터 손실이 발생할 수 있습니다.

해결책:

파일 작업을 올바르게 수행하기 위해 항상 다음을 수행해야 합니다:

  • fopen 함수를 사용하여 파일을 열기;
  • 열기의 성공 여부를 확인하기;
  • 읽기/쓰기를 위해 fread, fwrite, fscanf, fprintf 함수를 사용하기;
  • fclose를 통해 파일을 닫기.

예제 코드:

#include <stdio.h> int main() { FILE *fp = fopen("example.txt", "w"); if (!fp) { perror("파일 열기 실패"); return 1; } fprintf(fp, "Hello, world! "); fclose(fp); fp = fopen("example.txt", "r"); if (!fp) { perror("파일 읽기용 열기 오류"); return 1; } char buffer[100]; while (fgets(buffer, sizeof(buffer), fp)) { printf("%s", buffer); } fclose(fp); return 0; }

주요 특징:

  • 파일 스트림 작업은 명시적으로 파일을 열고 닫아야 합니다.
  • 파일 작업 결과를 항상 확인해야 합니다.
  • 파일 버퍼링은 성능에 영향을 미치며, 시기 적절하게 닫지 않으면 오류를 발생시킬 수 있습니다.

함정 질문.

fclose를 여러 번 연속으로 호출해도 될까요?

아니요, 파일 스트림을 이중으로 닫는 것은 정의되지 않은 동작을 초래합니다. fclose 이후에 파일 디스크립터는 유효하지 않게 됩니다.

fread 함수가 파일의 끝에 도달하면 무엇을 반환합니까?

fread는 성공적으로 읽힌 요소의 수를 반환합니다. 파일의 끝에 도달하면 반환되는 수는 예상보다 적을 수 있습니다. 항상 feofferror를 통해 진단해야 합니다.

같은 파일 스트림을 동시에 읽고 쓸 수 있습니까?

가능합니다. 파일이 "r+" 또는 "w+" 모드로 열려 있으면 사용할 수 있지만, 읽기/쓰기 모드를 변경할 때는 fflush나 다른 파일 위치 이동 작업(fseek)을 수행해야 합니다. 그렇지 않으면 동작이 정의되지 않습니다.

일반적인 실수 및 안티 패턴

  • 파일 열기 성공 여부를 확인하지 않기.
  • 파일을 닫지 않아서 리소스 누수 발생.
  • fclose 이후 동일한 FILE * 포인터를 사용하기.
  • 출력 버퍼를 플러시하지 않음 (fflush가 호출되지 않음, 스트림이 닫히지 않음).

실생활 예제

부정적인 케이스

개발자가 fopen의 반환값을 확인하지 않고 로그 파일에 데이터를 기록했을 때, 파일 디스크립터가 소진되면 더 이상 파일을 열 수 없었고 로그 메시지가 손실되었습니다.

장점:

  • 코드는 간단해 보였습니다.

단점:

  • 파일 디스크립터가 소진되었을 때 데이터가 영원히 손실되었습니다.
  • 오류는 진단되지 않았으며 반환 코드를 확인하지 않았습니다.

긍정적인 케이스

다른 코드 버전에서는 항상 모든 반환 값을 확인했습니다 (fopen, fwrite, fclose). 오류가 발생하면 perror를 통해 자세한 진단 메시지를 인쇄하고 프로그램을 정상적으로 종료하여 모든 리소스를 해제했습니다.

장점:

  • 신뢰성 있는 오류 처리.
  • 디버깅의 용이성과 리소스 해제 보장.

단점:

  • 코드가 다소 길어지고 모든 오류를 주의 깊게 관리해야 했습니다.