2019년도 2학기 소프트웨어공학 수업 과제물 비디오 대여 프로그램입니다.

main

/*
* 파일이름: 비디오대여 프로그램
* 작 성 자: 김영진
* 작 성 일: 2019-10-27
* 목    적: 소프트웨어 공학 2차 프로젝트
*/

#include "header.h" //헤더파일 호출
#include <stdio.h>

int select; //메인화면에서 switch문을 이용하기위해 int형 변수 select 선언

int main(void) {
	DataLoad(); //프로그램 시작 시 텍스트파일에 저장되어있는 데이터를 불러온다.
	while (select != 5) { //5가 아닐때 반복시키는 조건으로 while문 생성
		printf("------------------------------------------------------ \n");
		printf("비디오대여 프로그램입니다. \n");
		printf("무엇을 하시겠습니까? \n");
		printf("1. 대여 \n2. 반납 \n3. 회원가입 \n4. 관리자모드 \n5. 종료 \n");
		printf("입력:");
		scanf_s("%d", &select); //입력받은 숫자를 select에 저장
		switch (select) {
		case 1:
			Rental(); //1번 입력 시 Rental 함수 활성화
			break;
		case 2:
			Return(); //2번 입력 시 Return 함수 활성화
			break;
		case 3:
			SignUp(); //3번 입력 시 SignUp 함수 활성화
			break;
		case 4:
			Administrator(); //4번 입력 시 Administrator 함수 활성화
			break;
		case 5:
			printf("프로그램을 종료합니다. \n"); //5번 입력 시 반복문 종료 및 프로그램 종료
			break;
		default:
			printf("다시 입력해주세요. \n"); //엉뚱한거 입력시 "다시 입력해주세요" 노출
		}
	}
}
#pragma once
#define _CRT_SECURE_NO_WARNINGS //scanf 및 fopen 컴파일에러 방지

#include <stdio.h> //입출력 함수 사용 위해서 호출
#include <string.h> //string 관련 함수 사용 위해서 호출
#include <stdlib.h> //atoi  사용을 위해 호출

typedef struct { //회원정보를 저장하기위한 구조체
	char name[10]; //회원이름
	char number[15]; //회원 연락처
}USER;

typedef struct { //비디오정보를 저장하기위한 구조체
	char video[20]; //비디오이름
	int state; //대여상태
}VIDEO;

typedef struct { //대여현황을 저장하기위한 구조체
	char u_name[10]; //대여한 회원이름
	char v_name[20]; //대여한 비디오
}RENT;

void Rental(); //대여기능 함수
void Return(); //반납기능 함수
void SignUp(); //회원가입기능 함수
void Administrator(); //관리자모드기능 함수

void Rental_videolist(); //대여_비디오 목록보기 기능 함수
void Rental_videosearch(); //대여_비디오 검색하기 기능 함수

void Administrator_member(); //관리자모드_회원관리 기능 함수

void DataLoad(); //프로그램 시작 시 데이터를 받아오는 기능 함수
void NewDataSave(); //삭제 또는 수정 기능 후 새로운 데이터를 저장시키는 함수

function

#include "header.h"	//헤더파일 호출
#include <stdio.h>

USER user[100]; //구조체 USER를 user라는 이름으로 100만큼의 저장공간을 할당한다.
VIDEO video[100]; //구조체 VIDEO를 video라는 이름으로 100만큼의 저장공간을 할당한다.
RENT rent[100]; //구조체RENT를 rent라는 이름으로 100만큼의 저장공간을 할당한다.

int user_m = 0; //회원정보 저장 시 카운팅하는 용도
int video_m = 0; //비디오정보 저장 시 카운팅하는 용도
int rent_m = 0; //대여내역 저장 시 카운팅하는 용도

int select_f; //현재 cpp화면에서 switch문을 이용하기 위해 선언됨
char search[20]; //비디오 검색기능에서 사용됨
int choice; //목록보기에서 선택하는 용도로 사용됨
char Rname[10]; //대여 및 반납 시 일치하는 정보를 비교하는용도로 사용됨
int password; //관리자모드 접근 시 입력된 비밀번호를 저장하는 용도로 사용됨
int state; //비디오의 대여상태와 비교하기위해 사용됨

FILE* fpp; //FILE형 pointer함수 fpp를 호출, fopen or fclose 등 파일을 열고 닫을 때 사용됨

void Rental() { //비디오 대여기능, 코드가 길어져서 목록보기와 검색기능을 따로 함수로 뺐다.
	printf("비디오대여를 진행합니다. \n");
	printf("1. 비디오목록 \n2. 비디오검색 \n");
	printf("입력:");
	scanf("%d", &select_f);
	switch (select_f) {
	case 1:
		Rental_videolist(); //1번 입력 시 Rental_videolist 함수가 활성화된다.
		break;
	case 2:
		Rental_videosearch(); //2번 입력 시 Rental_videosearch 함수가 활성화된다.
		break;
	default:
		printf("다시 입력해주세요. \n"); //엉뚱한 값 입력 시 다시 입력해주세요가 출력된다.
		return;
	}
}

void Rental_videolist() { //비디오 목록보기
	printf("대여 가능한 비디오 목록을 노출합니다. \n");
	for (int i = 0, list = 1; i < video_m; i++, list++) { //i 가 video_m 의 값만큼 반복하여 증가한다
		if (video[i].state == 0) {	//이때 video 구조체중 state값이 0인 것 만 출력시킨다.
			printf("%d. \"%s\" state %d\n", list, video[i].video, video[i].state);  //변수 list를 사용해 비디오번호를 출력시킨다.
		}
	}
	printf("비디오의 번호를 입력해주세요. \n");
	printf("입력:");
	scanf("%d", &choice); //list로 표현된 비디오번호를 보고 사용자가 선택을한다. 이 때 choice에 저장된다.
	printf("\"%s\"가 선택되었습니다. \n", video[choice - 1].video); //list는 1부터 증가하고 i는 0부터 증가하기 때문에
	printf("\"%s\"를 대여하시겠습니까? \n", video[choice - 1].video);//list를 보고 선택한 choice에는 -1을 해줘야 선택한 video와 일치한다.
	printf("1. 예 \n2. 아니오. \n");
	printf("입력:");
	scanf("%d", &state); //대여할지말지 1번 2번을 선택한 값이 state에 저장된다.

	if (state == video[choice - 1].state) { //1번을 입력했는데 이미 비디오의 상태가 대여중이라면
		printf("이미 대여중인 비디오입니다. \n"); //이미 대여중인 비디오라고 표시된다.
		return;
	}
	if (state == 2) { //2번을 입력하면 취소된다.
		printf("취소되었습니다. \n");
		return;
	}
	if (state != video[choice - 1].state) { //1번을 입력했고 비디오가 대여중이 아니라면 대여를 진행하게된다.
		printf("비디오대여를 위해 회원정보를 확인합니다. \n");
		printf("이름:"); //대여를 위해 회원정보를 확인한다.
		scanf("%s", Rname); //입력한 이름을 Rname에 저장한다.
		for (int i = 0; i < user_m; i++) { //i 가 user_m값 만큼 1씩 증가를 반복한다.
			if (strcmp(Rname, user[i].name) == 0) { //0번째 부터의 데이터와 차례대로 비교한 뒤 일치하는 데이터가 존재할 시
				printf("\"1\"번을 누르시면 완료됩니다. \n");
				printf("입력:");
				scanf("%d", &video[choice - 1].state); //비디오의 state값에 1을 입력하며 마무리된다.
				printf("\"%s\"님감사합니다. \"%s\"를 대여했습니다. \n", user[i].name, video[choice - 1].video);
				fpp = fopen("rent.txt", "at"); //rent.txt.파일을 at 권한으로 연다.
				fprintf(fpp, "%s:%s\n", user[i].name, video[choice - 1].video); //txt파일에 대여내역을 이어 작성한다.
				strcpy(rent[rent_m].u_name, user[i].name); //대여내역을 구조체에 복사한다.
				strcpy(rent[rent_m].v_name, video[choice - 1].video); //대여내역을 구조체에 복사한다.
				rent_m++; //rent_m 값을 1 증가시킨다.
				fclose(fpp); //rent.txt.파일을 닫는다.

				NewDataSave(); //회원정보,고객정보,대여현황정보를 최신화시키는 기능함수이다.
			}
		}
		return;
	}
}

void Rental_videosearch() { //비디오 검색하기
	printf("비디오검색을 진행합니다. \n");
	printf("검색:");
	scanf("%s", search); //입력받은 값을 search에 저장
	for (int i = 0; i < video_m; i++) { //i 를 video_m 값만큼 1씩 증가를 반복
		if (strcmp(search, video[i].video) == 0) { //search의 값과 video구조체 중 video의 값과 일치하는 데이터가 나올 시
			printf("\"%s\"에 대한 검색결과입니다. \n", video[i].video);
			printf("\"%s\" state %d \n", video[i].video, video[i].state); //검색결과 도출
			printf("\"0\"은 대여가능 \"1\"은 다른사람이 대여중인 비디오입니다. \n");
			printf("\"%s\"를 대여하시겠습니까? \n", video[i].video);
			printf("1. 예\n2. 아니오 \n");
			printf("입력:");
			scanf("%d", &state); //1 or 2를 state에 저장

			if (state == video[i].state) { //1번 입력 시 비디오가 대여중이라면 대여불가
				printf("다른 회원이 이미 이용중인 비디오입니다. \n");
				return;
			}
			if (state == 2) { //2번 입력 시 취소
				printf("취소되었습니다. \n");
				return;
			}
			if (state != video[i].state) { //1번 입력, 대여가능한 상태면 대여진행
				printf("비디오대여를 위해 회원정보를 확인합니다. \n");
				printf("이름:");
				scanf("%s", Rname); //이름을 입력받고
				for (int q = 0; q < user_m; q++) {
					if (strcmp(Rname, user[q].name) == 0) { //일치하는 회원정보가 존재할 시
						printf("\"1\"번을 누르시면 완료됩니다. \n");
						printf("입력:");
						scanf("%d", &video[i].state); //비디오의 state값에 1을 입력하며 완료된다.
						printf("\"%s\"님감사합니다. \"%s\"를 대여했습니다. \n", user[q].name, video[i].video);
						fpp = fopen("rent.txt", "at"); //rent.txt.파일을 at권한으로 열고
						fprintf(fpp, "%s:%s", user[q].name, video[i].video); //새로운 대여내역을 txt파일에 작성
						strcpy(rent[rent_m].u_name, user[q].name); //새로운 대여내역을 구조체에 복사
						strcpy(rent[rent_m].v_name, video[i].video); //새로운 대여내역을 구조체에 복사
						rent_m++; //rent_m 값 1 증가
						fclose(fpp); //파일을 닫는다.
						NewDataSave(); //새로운 데이터 최신화
					}
				}
				return;
			}
			return;
		}
		else { //비디오 검색하고 검색결과가 없다면 else로 오고 return 된다.
			printf("검색결과가 없습니다. \n");
			return;
		}
	}
}

void Return() { //비디오 반납하기
	printf("비디오반납을 진행합니다. \n");
	printf("반납할 비디오를 입력해주세요. \n");
	printf("입력:");
	scanf("%s", Rname); //반납할 비디오를 입력, Rname에 저장
	for (int i = 0; i < rent_m; i++) {
		if (strcmp(Rname, rent[i].v_name) == 0) { //대여중인 비디오와 일치하는 정보가 있는지 확인
			printf("%s", rent[i].v_name); //일치할 시 반납을 진행하고
			printf("\"0\"번을 입력해 반납을 완료합니다. \n");
			printf("입력:");
			scanf("%d", &video[i].state); //video의 state값에 0을 입력하며 완료
			printf("반납이 완료되었습니다. 이용해주셔서 감사합니다. \n");
			for (int a = i; a < rent_m; a++) //rent a에 i 값을 삽입하고
				rent[a] = rent[a + 1]; //a값에 a+1 값을 덮어쓰기, 이를 rent_m 값만큼 반복한다.
			rent_m--; //그래서 한칸씩 앞으로 당기며 덮어쓰기되며 마지막 rent_m값은 NULL값이 될것이기에 -1 해준다.
			NewDataSave(); //새로운 데이터를 최신화
			return;
		}
	}
}

void SignUp() { //회원가입

	fpp = fopen("user.txt", "at"); //user.txt 파일을 at 권한으로 연다.

	printf("회원가입을 진행합니다. \n");
	printf("이름:");
	scanf("%s", user[user_m].name); //입력된 이름을 user 구조체 name에 저장
	printf("연락처:");
	scanf("%s", user[user_m].number); //입력된 연락처를 user 구조체 number에 저장
	printf("%s:%s 회원가입을 축하합니다. \n", user[user_m].name, user[user_m].number);

	fprintf(fpp, "%s:%s\n", user[user_m].name, user[user_m].number); //금방 입력받은 값들을 txt파일에 프린트
	fclose(fpp); //txt파일 닫는다.
	user_m++; //user_m 값 1 증가
}

void Administrator() { //관리자모드
	printf("관리자모드를 진행합니다. \n");
	printf("비밀번호:");
	scanf("%d", &password);
	if (password == 123) { //입력받은 비밀번호가 123과 일치해야 입장가능.
		printf("1. 회원관리 \n2. 비디오입고 \n3. 대여현황 \n");
		printf("입력:");
		scanf("%d", &select_f);
		switch (select_f) {
		case 1: //1. 회원관리를 선택했다면 Administrator_member 함수가 활성화된다.
			Administrator_member(); //이건 코드가 너무 길어서 함수로 따로 뺐다.
			break;
		case 2: //비디오입고를 선택할 시 아래 코드가 진행된다.
			fpp = fopen("video.txt", "at"); //video.txt 파일을 at 권한으로 개방

			printf("비디오입고를 진행합니다. \n");
			printf("비디오명:");
			scanf("%s", video[video_m].video); //입력받은 비디오명을 video 구조체 video에 저장
			printf("\"0\"을 입력하여 완료해주세요. \n");
			printf("입력:");
			scanf("%d", &video[video_m].state); //0을 입력해 state값에 0을 넣으며 마무리
			fprintf(fpp, "%s:%d\n", video[video_m].video, video[video_m].state); //방금 추가된 내역을 txt파일에 프린트
			fclose(fpp); //txt파일 닫기
			printf("\"%s\"가 추가되었습니다. \n", video[video_m].video);
			video_m++; //video_m 값 1 증가
			break;
		case 3: //대여현황
			printf("비디오 대여현황입니다. \n");
			for (int i = 0; i < rent_m; i++) {  //대여정보를 저장하는 rent구조체의 정보를 모두 출력시킨다.
				printf("%s:%s\n", rent[i].u_name, rent[i].v_name);
			}
		}
	}
	if (password != 123) { //비밀번호가 일치하지 않을경우return
		printf("비밀번호가 일치하지 않습니다. \n");
		return;
	}
}



void Administrator_member() { //관리자모드 -> 회원관리
	printf("회원관리를 진행합니다. \n");
	printf("1. 회원목록 \n2. 회원검색 \n");
	printf("입력:");
	scanf("%d", &select_f);
	switch (select_f) {
	case 1: //회원목록
		printf("전체회원의 목록을 노출합니다. \n");
		for (int i = 0, list = 1; i < user_m; i++, list++) //i를 user_m만큼 1씩 증가를 반복 (list는 번호나열용도)
			printf("%d. %s:%s\n", list, user[i].name, user[i].number); //user구조체에 저장되있는 정보를 모두 출력
		printf("회원번호를 입력해주세요, 삭제/수정을 진행합니다. \n되돌아가려면 \"0\"을 입력해주세요. \n");
		printf("입력:");
		scanf("%d", &choice); //list로 보여지는 숫자를보고 choice에 입력
		if (choice != 0) { //0이 취소니까 0이 아닐 시 삭제/수정을 진행
			printf("\"%s\"님이 선택되었습니다, 무엇을 하시겠습니까? \n", user[choice - 1].name);
			printf("1. 삭제 \n2. 수정 \n"); //list=1, i=0 부터 증가를 시작했기 때문에 list를 보고 선택한 choice에는 -1을 붙여줘야 i값과 일치
			scanf("%d", &select_f);
			switch (select_f) {
			case 1: //삭제하기
				printf("\"%s\"님을 삭제하였습니다. \n", user[choice - 1].name);
				for (int i = choice - 1; i < user_m; i++) { //i 값에 choice-1값을 입력 그 상태에서 user_m만큼 i++ 를 반복
					user[i] = user[i + 1]; //i = i+1 을 함으로써 한칸씩 당겨서 덮어쓰기
				}
				user_m--; //맨 뒤는 NULL값이 될 것이기에 --;
				NewDataSave(); //새로운 데이터를 최신화
				break;
			case 2: //수정하기
				printf("회원수정을 진행합니다. \n");
				printf("이름:");
				scanf("%s", user[choice - 1].name); //수정사항을 선택한 정보에 덮어쓰기
				printf("연락처:");
				scanf("%s", user[choice - 1].number); //수정사항을 선택한 정보에 덮어쓰기
				printf("%s:%s로 수정이 완료되었습니다. \n", user[choice - 1].name, user[choice - 1].number);
				NewDataSave(); //새 데이터를 최신화
				break;
			}
		}
		if (choice == 0) { //되돌아가기 0번 입력 시 return
			return;
		}
		break;
	case 2: //회원검색
		printf("회원검색을 진행합니다. \n");
		printf("검색:");
		scanf("%s", search); //검색입력값을 search에 저장
		for (int i = 0; i < user_m; i++) { //i를 user_m만큼 1씩 증가 반복
			if (strcmp(search, user[i].name) == 0) { //search값과 user 구조체의 name 에서 일치하는 데이터가 있을 시 아래로 진행
				printf("\"%s\"에 대한 검색결과입니다. \n", user[i].name);
				printf("%s:%s 무엇을 하시겠습니까? \n", user[i].name, user[i].number);
				printf("1. 삭제 \n2. 수정 \n");
				printf("입력:");
				scanf("%d", &select_f);
				switch (select_f) {
				case 1: //회원삭제
					printf("\"%s\"님을 삭제하였습니다. \n", user[i].name);
					for (int u = i; u < user_m; u++) { //u 에 i값을 대입
						user[u] = user[u + 1]; //u 에 u + 1 값을 대입 이것을 user_m만큼 반복
					}							//한칸씩 당기며 덮어쓰기되는 효과
					user_m--; //마지막 값은 NULL값이 될 것 이기에 --;
					NewDataSave(); //새로운 데이터를 최신화
					break;
				case 2: //회원수정
					printf("회원수정을 진행합니다. \n");
					printf("이름:");
					scanf("%s", user[i].name); //입력받은 값을 덮어쓰기
					printf("연락처:");
					scanf("%s", user[i].number); //입력받은 값을 덮어쓰기
					printf("%s:%s로 수정이 완료되었습니다. \n", user[i].name, user[i].number);
					NewDataSave(); //새로운 데이터를 최신화
					break;
				}
				break;
			}
			else { //search 값과 user구조체의 name에서 일치하는 데이터가 없을 시 아래결과를 프린트
				printf("검색결과가 없습니다. \n");
				break;
			}
		}
		break;
	}
}

void DataLoad() {
	fpp = fopen("user.txt", "rt"); //user.txt 파일을 rt  권한으로 오픈
	if (fpp == NULL) { //만약 없을 시
		fpp = fopen("user.txt", "at"); //생성해서 열고
		fclose(fpp); //닫는다
	}
	char line[100]; //txt파일에 입력된 데이터를 한 줄 씩 구분해서 읽어오는 용도
	char* ptr; //캐릭터형 포인터변수 ptr 선언
	int word_cnt; //해당 줄에 있는 데이터를 구분해서 구조체에 저장하는 용도

	while (fscanf(fpp, "%s", line) > 0) { //txt파일에 있는 문자를 line에 담는다 이 때 스캔된 문자가 있으면 fscanf에 정수값이 반환되므로
		word_cnt = 0;						//0보다 클때=받아온문자가 있을때까지 while문을 반복
		ptr = strtok(line, ":"); //line에 저장된 문자를 클론 기준으로 잘라서 ptr에 저장
		while (ptr != NULL) {  //ptr에 문자를 저장할 때 갯수만큼 정수형태로 반환됨 NULL값이 아닐 때 반복
			word_cnt++; //반복하는 횟수만큼 word_cnt 가 증가됨
			switch (word_cnt) { //첫번째 반복시 case1 두번째 반복시 case2로 이동
			case 1:
				strcpy(user[user_m].name, ptr); //ptr값을 user구조체의 name에 저장
				break;
			case 2:
				strcpy(user[user_m].number, ptr); //ptr값을 user 구조체의 number에 저장
				break;
			}
			ptr = strtok(NULL, ":"); // 클론을 기준으로 ptr에 NULL값을 반환
		}
		user_m++; //문자열카피가 끝나면 user_m 를 1 증가
	}
	fclose(fpp); //파일을 닫는다

	//여기서부터는 주석의 내용이 모두 유사하기때문에 특이점이 없을 시 생략한다.
	fpp = fopen("video.txt", "rt");
	if (fpp == NULL) {
		fpp = fopen("video.txt", "at");
		fclose(fpp);
	}
	while (fscanf(fpp, "%s", line) > 0) {
		word_cnt = 0;
		ptr = strtok(line, ":");
		while (ptr != NULL) {
			word_cnt++;
			switch (word_cnt) {
			case 1:
				strcpy(video[video_m].video, ptr);
				break;
			case 2:
				video[video_m].state = atoi(ptr); //ptr에 저장된 주소값에서 문자열을 정수형태로 반환 후 video구조체의 state에 대입
				break;
			}
			ptr = strtok(NULL, ":");
		}
		video_m++;
	}
	fclose(fpp);

	fpp = fopen("rent.txt", "rt");
	if (fpp == NULL) {
		fpp = fopen("rent.txt", "at");
		fclose(fpp);
	}
	while (fscanf(fpp, "%s", line) > 0) {
		word_cnt = 0;
		ptr = strtok(line, ":");
		while (ptr != NULL) {
			word_cnt++;
			switch (word_cnt) {
			case 1:
				strcpy(rent[rent_m].u_name, ptr);
				break;
			case 2:
				strcpy(rent[rent_m].v_name, ptr);
				break;
			}
			ptr = strtok(NULL, ":");
		}
		rent_m++;
	}
	fclose(fpp);
}

void NewDataSave() { //새로운 데이터를 최신화한다.
	fpp = fopen("user.txt", "wt"); //user.txt.파일을 wt 권한으로 연다.
	for (int i = 0; i < user_m; i++) { //i 를 user_m 만큼 1씩 증가 반복
		fprintf(fpp, "%s:%s\n", user[i].name, user[i].number); //txt파일에 구조체에 저장된 내역을 모두 프린팅한다.
	}
	fclose(fpp); //파일을 닫는다.

	//이하동문
	fpp = fopen("video.txt", "wt");
	for (int i = 0; i < video_m; i++) {
		fprintf(fpp, "%s:%d\n", video[i].video, video[i].state);
	}
	fclose(fpp);

	fpp = fopen("rent.txt", "wt");
	for (int i = 0; i < rent_m; i++) {
		fprintf(fpp, "%s:%s\n", rent[i].u_name, rent[i].v_name);
	}
	fclose(fpp);
}

태그:

Cpp

카테고리:

업데이트:

댓글남기기