계좌 관리 프로그램

 

 지금까지 공부한 내용들을 바탕으로 계좌 관리 프로그램을 작성해 봤습니다. 계좌를 생성하는 기능과 입금, 출금하는 기능 계좌 전체를 조회하는 기능이 있습니다. 파일 입출력을 이용해서 "data.txt"라는 텍스트 파일에 있는 계좌정보를 가져오기도하고, 계좌를 생성한 뒤에 입금, 출금 한 내용을 "data.txt"파일에 저장할 수 있도록 했습니다. "bank.h"헤더파일과 "bank.c","main.c" 세 파일로 분할 컴파일 했습니다. "bank.h"헤더파일에는 구조체 정의와 각 함수정의 및 헤더파일들을 인클루드했고, "bank.c"에서는 각 함수들의 기능 구현을 했습니다. 마지막으로 "main.c"는 "bank.h"헤더파일을 인클루드하고 "bank.c"의 함수를 호출해서 사용하도록 작성 했습니다.


- bank.h

----------------------------------------------------------------------------------------

#define NAME_LEN 20 // define은 단순매크로로 값을 정해 편하게 사용할 수 있습니다. 

// 아래 헤더파일을 bank.h에 인클루드한 이유는 main.c와 bank.c에서 사용하기 위해서 입니다.

#include <stdio.h> 

#include <stdlib.h>

#include <string.h>

#pragma warning(disable:4996)


typedef struct bank{ // 계좌정보를 저장할 구조체 선언

char *name[NAME_LEN]; // 예금주[최대20자리]

int id;                         // 계좌번호

int money;                   // 잔액

struct bank *next;

}bank;


bank *head, *tail; // 노드의 처음과 끝

void Init_account(FILE *fp); // 노드의 처음과 끝에 메모리 할당하고, 파일에서 입력을 받도록 하는 함수

void Make_account(FILE *fp); // 계좌를 생성하는 함수

void Deposit(FILE *fp); // 입금 함수

void WithDraw(FILE *fp); // 출금 함수

void WriteAccount(FILE *fp); // 계좌의 정보를 저장하는 함수

void Account_inquire(void); // 계좌를 조회하는 함수

void ReadAccount(int id, char *name, int money); // 텍스트 파일에서 입력을 받는 함수

----------------------------------------------------------------------------------------


- bank.c

----------------------------------------------------------------------------------------


#include "bank.h"


void Init_account(FILE *fp)

{

int id;

char name[NAME_LEN];

int money;

head = (bank *)malloc(sizeof(bank));

tail = (bank *)malloc(sizeof(bank));

head->next = tail;

tail->next = tail;


while (fscanf(fp, "%d %s %d", &id, name, &money) == 3){ // 정수형, 문자형, 정수형 3개일 때만 입력을 받음

ReadAccount(id, name, money);

}

}


void ReadAccount(int id, char *name, int money)

{

bank *t;

t = (bank *)malloc(sizeof(bank));

t->id = id;

strcpy(t->name, name);

t->money = money;


t->next = head->next; // 다음 노드를 가리킴

head->next = t; // 노드의 처음을 가리킴

}


void Make_account(FILE *fp)

{

int id;

char name[NAME_LEN];

int money;

bank *t;

t = (bank *)malloc(sizeof(bank));


printf("\n*********계좌 생성*********\n");

printf("계좌번호 : "); scanf("%d", &id);

printf("예 금 주 : "); scanf("%s", name);

printf("입 금 액 : "); scanf("%d", &money);


t->id = id;

strcpy(t->name, name);

t->money = money;


t->next = head->next;

head->next = t;


WriteAccount(fp); // 저장하는 함수로 파일 포인터를 넘겨줌

}


void Deposit(FILE *fp)

{

int id;

int money;

bank *t;

printf("계좌번호 : "); scanf("%d", &id);

printf("입 금 액 : "); scanf("%d", &money);


for (t = head->next; t != tail; t = t->next)

{

if (t->id == id)

{

t->money += money; // 잔액에 입금할 금액을 더해서

WriteAccount(fp); // 저장

return;

}

}

printf("없는 계좌번호입니다.\n");

}


void WithDraw(FILE *fp)

{

int id;

int money;

bank *t;

printf("계좌번호 : "); scanf("%d", &id);

printf("출 금 액 : "); scanf("%d", &money);


for (t = head->next; t != tail; t = t->next)

{

if (t->id == id)

{

if (t->money<money) // 출금액이 잔액보다 클 경우

{

printf("출금액이 잔액을 초과할 수 없습니다.\n");

return;

}

else{

t->money -= money; // 잔액에서 출금액을 빼서

}

WriteAccount(fp); // 저장

return;

}

}

printf("없는 계좌번호입니다.\n");

}

void Account_inquire(void)

{

bank *t;

for (t = head->next; t != tail; t = t->next)

{

printf("\n*********잔액 조회*********\n");

printf("계좌번호 : %d\n", t->id);

printf("예 금 주 : %s님\n", t->name);

printf("잔    액 : %d원\n\n", t->money);

}

}


void WriteAccount(FILE *fp)

{

bank *t;

rewind(fp); // 파일 읽는 포인터 지점을 맨 첨으로 돌리는 함수

for (t = head->next; t != tail; t = t->next)

{

fprintf(fp, "%d %s %d\n", t->id, t->name, t->money);

}

}

----------------------------------------------------------------------------------------


- main.c

----------------------------------------------------------------------------------------

#include "bank.h"

int main()
{
int input;
FILE *fp;
fp = fopen("data.txt", "r+"); // 파일모드가 r+일 경우  읽고쓰기를 동시에 수행 합니다.
Init_account(fp);

do{
printf("계좌 생성&관리 프로그램입니다. 원하시는 번호를 입력하세요.\n");
printf("*********************************************\n");
printf("1)계좌 생성 2)계좌 조회 3)입금 4)출금 5)종료\n");
printf("*********************************************\n");
printf("입력 >");
scanf("%d", &input);

switch (input){
case 1:
Make_account(fp);
break;
case 2:
Account_inquire();
break;
case 3:
Deposit(fp);
break;
case 4:
WithDraw(fp);
break;
case 5:
input = 0;
free(head); // 종료하면서 메모리 반환
free(tail);
break;
default:
printf("잘못 입력하셨습니다. \n");
return main();
}
}
while (input != 0);
}

----------------------------------------------------------------------------------------


 위 코드의 실행 결과는 다음과 같습니다. 우선 "data.txt"파일에 초기값으로 아래 그림과 같이 입력 하고 저장한뒤에 프로그램을 실행했습니다.


 계좌 하나를 추가로 생성하고, 새로만든 계좌와 기존의 계좌 각각 입금, 출금을 수행했습니다. 


 계좌를 조회하고 종료하는 그림입니다. 새로만든 계좌와 기존의 계좌 모두 정상적으로 출력됩니다. "data.txt"파일에도 저장되었을까요?


 살짝 깨지기는 했지만 값이 정상적으로 저장된걸 확인 할 수 있습니다.




'언어 > C' 카테고리의 다른 글

VSCODE 환경 C개발 환경  (0) 2019.03.27
[C] 파일 입·출력  (0) 2017.01.05
[C] 자기 참조 구조체와 연결리스트  (2) 2017.01.04
[C] 동적 메모리  (0) 2017.01.03
[C] 공용체  (0) 2016.12.27

자기 참조 구조체


 자기 참조 구조체는 자신과 동일한 구조체를 가리킬 수 있는 포인터 변수를 필드 변수로 가지는 구조체입니다. 형태는 다음과 같습니다.

----------------------------------------------------------------------------------------

struct Node

{

int a;

struct Node* b; // 자신의 구조체를 가리키는 포인터 변수

};

----------------------------------------------------------------------------------------


연결리스트

 연결리스트는 컴퓨터 관련 공부나 자격증 공부를할 때 많이 들어보셨을 단어입니다. 연결리스트는 구조체와 포인터를 이용해 유동적으로 데이터를 저장할 수 있는 자료구조로 자기 참조 구조체를 연결해 사용합니다. 아래 그림과 같이 a의 주소만 알고있다면 b와 c에 접근이 가능한 구조입니다.

 struct Node *head;와 같이 구조체를 정의했을 때 위 그림의 a,b,c노드에 접근하는 방법은 아래 표와 같습니다

a.n

 head → n

b.n

 head → next → n

c.n

 head → next → next → n

 

 위의 그림을 봤을때 각 노드는 다음 노드의 주소를 가리킵니다. 마지막 노드는 어떤 주소를 가리킬까요? 마지막 노드는 NULL값을 저장합니다. 이 NULL값은 더이상 연결된 노드가 없음을 의미합니다.


 아래 코드는 정수를 입력받아 연결리스트를 구성해서 출력하고 메모리를 반환한뒤에 종료하는 코드입니다. 반복문에서는 p = p->next; 와같은 문장을 이용해 참조를 이동할 수 있습니다.
----------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)

struct Node{
int n;
struct Node *next;
};

void showMenu(); // 반복문안에서 입력을 받기위한 문자열을 출력하는 함수
void printNodes(struct Node* p); // 입력받은 정수를 출력하기 위한 함수
void freeNodes(struct Node* p); // 사용이 끝난 노드의 메모리를 반환하는 함수

int main(){
int flag = 1; // 반복문을 실행하기 위한 변수로 1로 초기화 하고 0이 될때 반복문이 종료됩니다.
int input; // 입력받을 정수
struct Node *head; // 노드의 처음
struct Node *last; // 노드의 끝
struct Node *node; // 추가될 노드의 주소를 임시로 저장할 포인터 변수

head = NULL; // 추가된 노드가 없기때문에 head와 last를 NULL로 초기화
last = NULL;

while (flag){
showMenu();
scanf("%d", &input);

if (input == 0) // 0을입력하면 종료
{
flag = 0;
}
else{
node = (struct Node*)malloc(sizeof(struct Node)); // 구조체 역시 sizeof연산자를 이용할 수 있습니다. 구조체를 동적할당
node->n = input; // 생성된 Node 구조체에 값을 설정합니다.
node->next = NULL;

if (head == NULL) // 연결 리스트가 비어있을 경우, head에 생성된 node 의 주소를 저장
{
head = node;
}
else // 연결 리스트가 비어있지 않을 경우, 마지막 노드의 next에 생성된 node 의 주소를 저장합니다.
  {
last->next = node;
}
last = node; // 연결 리스트에 추가된 node 의 주소를 last 에 저장합니다.
}
}
  // 반복문이 종료되면 printNodes함수와 freeNodes함수를 실행합니다.
printNodes(head); 
freeNodes(head);
}

void showMenu(){
printf("저장할 정수를 입력하세요. \n 종료 0 >");
}

void printNodes(struct Node* p)
{
while (p != NULL){  // 마지막 노드가 아닌 경우
printf("%d\n", p->n); // 노드를출력하고,
p = p->next; // 다음 노드를 가리킵니다.
}
}
void freeNodes(struct Node* p){
struct Node *temp;
while (p != NULL){ // 마지막 노드가 아닌 경우
temp = p; // temp에 p를 저장해서
p = p->next; 
free(temp); // 반환합니다.
}
}
----------------------------------------------------------------------------------------

 실행 결과는 아래와 같습니다.


* 출처 : 한국기술교육대학교 온라인평생교육원 C 프로그래밍_2 

          스타일 C프로그래밍 저.김종훈,김종진 출.WellBook




'언어 > C' 카테고리의 다른 글

[C] 계좌 관리 프로그램  (2) 2017.01.10
[C] 파일 입·출력  (0) 2017.01.05
[C] 동적 메모리  (0) 2017.01.03
[C] 공용체  (0) 2016.12.27
[C] 구조체  (2) 2016.12.26

+ Recent posts