본문 바로가기

programming study/C

[나도코딩]C 프로그래밍 - 입문부터 게임 개발까지 (9)(2020.12.30)

본 내용은 해당 강의 토대로 작성


파일 입출력

변수의 값들은 컴퓨터의 메모리 상에 저장된다. 메모리는 프로그램이 종료되면 그 값들이 날아가게 된다. 반면, 파일은 종료를 해도 별도로 저장되기 때문에 다시 그대로 불러올 수 있다.

파일 쓰기 fputs

명령어를 통해서 컴퓨터의 공간에 파일을 생성하고 데이터를 저장할 수 있다.

#define _CRT_SECURE_NO_WARNINGS //파일 쓰기를 사용하기 위해 정의
#include <stdio.h>
#define MAX 10000 //소스코드 어디서나 MAX는 10000이라는 상수 정의

int main(void)
{
  char line[MAX]; //char line[10000]
  FILE *file = fopen("/Users/jaeminjeon/test1.txt","wb"); // 컴퓨터의 경로에 파일을 열기
  if (file == NULL)
  {
    printf("파일 열기 실패\n");
    return 1;
  }
  fputs("fputs를 이용해서 글을 적습니다\n", file); //해당 파일에 텍스트 입력
  fputs("잘 적히는지 확인바랍니다\n", file);
  fclose(file); //파일 저장
  return 0;
}

#define _CRT_SECURE_NO_WARNINGS : 파일 쓰기 하기 전에 최상단에 정의

fopen(경로) : 경로의 파일을 열기

r / w / a : 읽기전용 / 쓰기전용 / 이어쓰기

t / b : 텍스트 / 바이너리

fputs("내용",파일포인터) : 해당 파일 내용 쓰기

fclose(파일포인터) : 파일 닫고 저장

FILE *file = fopen("/Users/jaeminjeon/test1.txt","wb"); 는 해당 경로에 파일을 열어 file에 넣는다는 뜻이다. wb 는 읽기전용의 바이너리데이터라는 의미이다. 이 명령어에 의해서, 해당 경로에 파일을 탐색한 다음, fputs 명령어에 의해 텍스트가 입력된다. 이 때, 파일을 열고 나서 닫지 않은 상태에서 프로그램에 문제가 생기면 데이터가 손실될 수 있으니 항상 fclose 명령어로 파일을 저장하고 닫아야 한다. 그 결과, 아래의 텍스트 파일이 해당 경로에 생성되어있다.

스크린샷 2020-12-29 오후 11.48.47

파일 읽기 fgets

이제 위에서 생성한 파일의 텍스트를 읽어보자.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MAX 10000 //소스코드 어디서나 MAX는 10000이라는 상수
int main(void)
{
  char line[MAX]; 
  FILE *file = fopen("/Users/jaeminjeon/test1.txt","rb");//읽기
  if (file == NULL)
  {
    printf("파일 열기 실패\n");
    return 1;
  }
  while (fgets(line, MAX, file) != NULL) //생성한 파일 읽기 저장할곳, 사이즈, 파일포인터
  {
    printf("%s", line); //해당 내용 출력하기
  }
  fclose(file); 
  return 0;
}

fgets(저장할곳,사이즈,파일포인터) : 파일포인터의 파일을 찾아서 저장할 곳에 사이즈만큼 저장

fopen에서 읽을 때, rb를 사용한다. while 문으로 fgets 로 가져온 텍스트가 NULL 이 아니면 계속 가져오게 한다. 즉, 해당 파일의 텍스트를 모두 가져올 수 있다. 명령어가 끝나고 fclose를 써는 것도 잊지말자.

스크린샷 2020-12-30 오전 12.27.20

또다른 파일 쓰기 fprintf

fprintf 도 파일을 쓰는 기능이다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MAX 10000

int main(void)
{
  int num[6] = {0,0,0,0,0,0}; //로또 추첨 번호
  int bonus = 0; //보너스 번호
  char str1[MAX];
  char str2[MAX];
  FILE * file = fopen("/Users/jaeminjeon/test2.txt", "Wb"); //쓰기전용 바이너리
  if(file == NULL)
  {
    printf("파일 열기 실패\n");
    return 1;
  }
  // 로또 추첨 번호 저장
  fprintf(file, "%s %d %d %d %d %d %d\n", "추첨번호", 1,2,3,4,5,6);
  fprintf(file, "%s %d\n", "보너스번호", 7);
  fclose(file); 
  return 0;
}

위의 예시를 보면, fprintf는 포맷에 맞춰서 입력할 수 있다.

스크린샷 2020-12-30 오후 12.45.23

또다른 파일 읽기 fscanf

fscanf 도 파일을 읽을 수 있다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define MAX 10000 //소스코드 어디서나 MAX는 10000이라는 상수

int main(void)
{
  int num[6] = {0,0,0,0,0,0}; //로또 추첨 번호
  int bonus = 0; //보너스 번호
  char str1[MAX];
  char str2[MAX];
  FILE * file = fopen("/Users/jaeminjeon/test2.txt", "rb"); //읽기 전용
  if(file == NULL)
  {
    printf("파일 열기 실패\n");
    return 1;
  }
  fscanf(file,"%s %d %d %d %d %d %d", str1, &num[0], &num[1], &num[2], &num[3], &num[4], &num[5]);
  printf("%s %d %d %d %d %d %d\n", str1, num[0], num[1], num[2], num[3], num[4], num[5]);
  fscanf(file,"%s %d", str2, &bonus);
  printf("%s %d\n", str2, bonus);    
  fclose(file); 
  return 0;
}

선언한 변수에 파일의 숫자들을 받아와서 출력한다.

스크린샷 2020-12-30 오후 12.45.10

비밀일기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //strcmp가져오기
//비밀번호를 입력 받아서
//맞는 경우? 비밀일기를 읽어와서 보여주고, 계속 작성하도록 한다.
//틀린 경우? 경고 메시지를 표시하고 종료한다.
#define MAX 10000
int main(void)
{
  //fgets, fputs 활용
  char line[MAX]; //파일에서 불러온 내요을 저장할 변수
  char contents[MAX]; //일기장에 입력할 내용
  char password[20]; //비밀번호 입력
  char c; //비밀번호 입력 할 때 키값 확인용[마스킹]
  printf("'비밀일기'에 오신 것을 환영합니다\n");
  printf("비밀번호를 입력하세요 : ");
  //getchar() /getch()의 차이?
  //getchar() : 엔터를 입력받아야 동작
  //getch() : 키 입력시 바로바로 동작
  int i = 0;
  while (1)
  {
    c = getch();
    if (c == 13) //(13은)Enter -> 비밀번호 입력 종료
    {
      password[i] = '\0'; //엔터를 치면 NULL이 들어감
      break;
    }
    else //비밀번호 입력 중
    {
      printf("*");
      password[i] = c;
    }
    i++;
  }
  //비밀번호 : skehzheld
  printf("\n\n === 비밀번호 확인 중...===\n\n"); 
  if (strcmp(password, "skehzheld")==0) //비밀번호 일치 확인
  {
    printf("=== 비밀번호 확인 완료 === \n\n");
    char *fileName = "c:\\secretdiary.txt";
    FILE * file = fopen(fileName, "a+b");
    //파일이 없으면 생성, 있으면 append(뒤에부터 내용을 추가)
    if(file==NULL)
    {
      printf("파일 열기 실패\n");
      return 1;
    }
    while(fgets(line,MAX,file) != NULL)
    {
      printf("%s", line);
    }
    printf("\n\n 내용을 계속 작성하세요! 종료는 EXIT 입력하세요\n\n");

    while (1)
    {
      scanf("%[^\n]", contents); //줄바꿈 나오기 전까지 모든 문장을 다 받음(한 문장씩)
      getchar(); //Enter 입력 (\n) Flush처리 위의 줄바꿈을 없애버림

      if(strcmp(contents, "EXIT")==0)
      {
        printf("비밀일기 입력을 종료합니다\n\n");
        break;
      }
      fputs(contents, file);
      fputs("\n", file); //Enter를 위에서 무시 처리 했으므로 임의 추가
    }
    fclose(file);  
  }
  else //비밀번호 틀린 경우
  {
    printf(" === 비밀호가 틀렸어요 ===  \n\n");
    printf("사용자 이외에 접근 금지\n\n\n");
  }
  return 0;
}

느낀점

드디어 C언어 기초(!)가 끝났다. 쉽게 설명해주는 강의 덕분에 잘 따라오고 마칠 수 있었다. 아쉽게도, 마지막 프로젝트 또한 윈도우 환경이 안되어서 실행이 되지 않았다. stackoverflow에 검색해보니까 getch()는 C의 표준 라이브러리 함수가 아니라더라… 이번에 성공하지 못한 물고기 게임과 비밀일기는 기억해 놔서 더 공부를 한 뒤 해결방법을 찾아내고 싶다.

공부를 하면서, 컴퓨터의 자료구조에 대해서 조금이나마 알게되었다. 생각보다 이해가 잘되고 재미있어서 한 번 제대로 공부해 볼 것이다. 웹을 공부하다가 C언어는 모든 언어의 근본이라는 소리를 듣고 덜컥 공부하게 되었지만 즐거운 시간이었다. (처음에 세팅할 때 빼고…)

이제부터는 알고리즘 문제풀이를 풀기위해 관련 이론과 파이썬을 배우러 가야겠다!!