[C] 씹어먹는 C 언어 - <16 - 1~3. struct>

Kim Dongil·2022년 10월 30일
0

C

목록 보기
23/28

1. 구조체 안에 또다른 구조체 변수를 설정할 수 있을까요?

(난이도 : 中)

  • 구조체도 하나의 타입이기 때문에
    구조체를 멤버로 가지는 구조체를 만들 수 있을 것 같습니다.

  • 배열과 비슷하다는 관점에서 보면 배열 안에 배열 즉, 다차원 배열을 설정할 수 있듯이 구조체도 구조체 안의 구조체가 가능할 것 같습니다.
    구조체를 하나의 타입으로 여길 수 있다는 관점에서 보면, 구조체는 다양한 타입을 원소로 가질 수 있기 때문에 구조체 타입 역시 원소로 가질 수 있을 것 같습니다.

2. 구조체를 인자로 가지는 함수를 생각해보세요.

(난이도 : 中)

  • 만약 struct test 라는 구조체를 선언하고,
    main함수에서 struct test abc라는 구조체를 선언했다면
    구조체를 인자로 가지는 함수는 한 구조체에만 적용될 수 있을 것 같습니다.
    int goojo(struct test *pa);와 같이 인자는 한 타입만을 받기에 struct test 자체가 하나의 타입이기 때문입니다.
    다수의 구조체 strct test, struct test2, struct test3을 하나의 인자로 통합할 수는 없을 것 같습니다.

  • 구조체를 배열의 관점에서 보면 배열의 이름은 시작 주소를 가리키는 포인터가 될 수 있기 때문에 구조체 역시 이름만으로도 인자로 사용할 수 있을 것 같습니다. 다만, 인덱스로 참조하지 않는다는 점에서 시작 주소가 아니라 그냥 구조체가 저장된 가상의 주소를 넘길 것 같습니다.

3. (이전에 만든)도서 관리 프로그램을만들되,구조체를 이용해 봅시다. 또한 register_book 과 같은 함수를 이용하여 책을 등록해봅시다.

(난이도 : 下)

#include <stdio.h>

int add_book(struct BOOK* book, int* total_book);
int search_book(struct BOOK* book, int total_book);
int borrow_book(struct BOOK* book);
int return_book(struct BOOK* book);

int compare(char* str1, char* str2);


struct BOOK {
	char book_name[30], auth_name[30], publ_name[30];
	int borrowed;
};

int main(void) {

	struct BOOK book[100];
	int total_book = 0;
	int user_input;

	while (1) {
		printf("도서 관리 프로그램 입니다 \n");
		printf("무엇을 하시겠습니까?  \n\n");
		printf("1. 책 추가하기 \n");
		printf("2. 책 검색하기 \n");
		printf("3. 책 대여하기 \n");
		printf("4. 책 반납하기 \n");
		printf("번호 입력 : ");
		scanf("%d", &user_input);
		printf("\n");

		switch (user_input) {
		case 1: // 책 추가하기
			add_book(book, &total_book);
			break;
		case 2: // 책 검색하기
			search_book(book, total_book);
			break;
		case 3: // 책 대여하기
			borrow_book(book);
			break;
		case 4: // 책 반납하기
			return_book(book);
			break;
		case 5: // 종료
			return 0;
		}
	}

	return 0;
}

int add_book(struct BOOK* book, int* total_book) {
	int user_input;

	if (total_book == 99) {
		printf("더 이상 추가할 공간이 없습니다. \n");
		return 0;
	}

	printf("1. 책 추가하기 \n");
	printf("2. 돌아가기 \n");
	printf("입력 : ");
	scanf("%d", &user_input);
	printf("\n");

	if (user_input == 1) {
		printf("책 이름 입력 : ");
		scanf("%s", book[*total_book].book_name);
		printf("책 저자 입력 : ");
		scanf("%s", book[*total_book].auth_name);
		printf("책 저자 입력 : ");
		scanf("%s", book[*total_book].publ_name);
	}

	if (user_input == 2) {
		return 0;
	}

	book[*total_book].borrowed = 0;
	(*total_book)++;

	return 0;
}

int search_book(struct BOOK* book, int total_book) {
	int user_input;
	char name[30];
	int i;

	printf("어느 것으로 검색 할 것인가요? \n");
	printf("1. 책 제목 검색 \n");
	printf("2. 책 저자 검색 \n");
	printf("3. 책 출판사 검색 \n");
	printf("입력 : ");
	scanf("%d", &user_input);
	printf("\n");

	printf("검색할 단어 입력 : ");
	scanf("%s", name);
	printf("검색 결과 \n\n");

	switch (user_input) {
	case 1:
		for (i = 0; i < total_book; i++) {
			if (compare(book[i].book_name, name)) {
				printf("책 번호 : %d  // 책 이름 : %s // 책 저자 : %s // 책 출판사 : %s \n",
					i, book[i].book_name, book[i].auth_name, book[i].publ_name);
			}
		}
		break;
	case 2:
		for (i = 0; i < total_book; i++) {
			if (compare(book[i].auth_name, name)) {
				printf("책 번호 : %d  // 책 이름 : %s // 책 저자 : %s // 책 출판사 : %s \n",
					i, book[i].book_name, book[i].auth_name, book[i].publ_name);
			}
		}
		break;
	case 3:
		for (i = 0; i < total_book; i++) {
			if (compare(book[i].publ_name, name)) {
				printf("책 번호 : %d  // 책 이름 : %s // 책 저자 : %s // 책 출판사 : %s \n",
					i, book[i].book_name, book[i].auth_name, book[i].publ_name);
			}
		}
		break;
	}

	printf("\n");

	return 0;
}

int compare(char* str1, char* str2) {
	int i = 0, j = 0, length = 0;

	while (str2[length])
		length++;

	while (str1[i]) {
		if (str1[i] != str2[i])
			i++;
		else {
			i++;
			j++;
		}
	}

	if (j == length)
		return 1;

	return 0;
}

int borrow_book(struct BOOK* book) {
	int user_input;

	printf("빌릴 책 번호 입력 : ");
	scanf("%d", &user_input);

	if (book[user_input].borrowed == 1)
		printf("이미 대여된 책 입니다 \n");
	else
	{
		printf("책을 정상적으로 대여 했습니다 \n");
		book[user_input].borrowed = 1;
	}
	printf("\n");

	return 0;
}
int return_book(struct BOOK* book) {
	int user_input;

	printf("반납할 책 번호 입력 : ");
	scanf("%d", &user_input);

	if (book[user_input].borrowed == 0)
		printf("이미 반납한 책 입니다 \n");
	else
	{
		printf("책을 정상적으로 반납 했습니다 \n");
		book[user_input].borrowed = 0;
	}
	printf("\n");

	return 0;
}

4. 큰 수를 다루는 구조체를 생각해봅시다. 그 구조체의 이름은 BigNum 입니다. BigNum 구조체에는 다음과 같은 멤버들이 있을 수 있습니다.

struct BigNum {
  int i_digit[100];   // 정수 부분
  int d_digit[100];   // 소수 부분
  int i_total_digit;  // 전체 사용되고 있는 정수부분 자리수
  int d_total_digit;  // 전체 사용되고 있는 소수부분 자리수
  char sign;  // 부호, 0 이면 양수, 1 이면 음수. 0 은 양수로 간주한다.
};
  • 이 때, BigNum 구조체의 변수들의 덧셈, 뺄셈을 수행하는 함수를 작성해보세요
    (난이도 : 中上)

  • BigNum 구조체 변수들의 곱셈을 수행하는 함수를 만들어보세요
    (난이도 : 上)

  • BigNum 구조체 변수들의 나눗셈을 수행하는 함수를 만들어보세요
    (난이도 : 最上)

참고로 BigNum 구조체를 다룰 때 중요한 점은 수의 크기가 위 배열에 들어가지 않을 정도로 클 때를 적절히 처리해 주어야 한다는 점에 있습니다.

5.

공용체는 도대체 어디에 써먹을 수 있을까요? 이 글 을 읽어보세요.

씹어먹는 C 언어 - <16 - 1. 모아 모아 구조체(struct)>
씹어먹는 C 언어 - <16 - 2. 모아 모아 구조체(struct) - 구조체 인자로 가진 함수>
씹어먹는 C 언어 - <16 - 3. 구조체와 친구들(공용체(union), 열거형(enum))>

0개의 댓글