<C프로그래밍-새내기를 위한 첫 C 언어 책>연습문제 chapter 9 (1, 2, 3, 4, 5)

1. 다음은 출금 서비스를 위한 보기용 프로그램이다. 프로그램의 14, 16, 28, 29, 31, 32, 41행에서 변수 참조 규칙을 어기고 있는데, 그 이유를 설명하시오.
#include <stdio.h>
int check_PW();    //비밀번호 확인 서비스
void withdraw();    //출금 서비스
char name[10] = "한국은행";    //서비스 업체 이름

int main(void) {
    char reply;
    int balance = 100000, system_PW = 1111;    //계좌의 현재 잔액, 시스템 비밀번호
    do {
        printf("%s의 출금 서비스입니다.", name);
        if (check_PW())
            withdraw();
        else {
            printf("%d원의 출금을 요청하셨으나", amount);
            printf("비밀번호가 맞지 않으므로 서비스를 제공할 수 없습니다.");
            printf("지금까지 %d번 비밀번호 오류 발생", count);
        }
        printf("그만 하시겠습니까(Y/N)? "); scanf("%c", reply);
    } while (!(reply == 'N' || reply == 'n'));    //그만 두기를 원하지 않는 한 반복

    return 0;
}

void withdraw() {
    int amount;
    if (check_PW()) {
        printf("출금하실 금액은? "); scanf("%d", amount);
        if (balance < amount)
            printf("\n잔액이 부족합니다. 현재 잔액 %d원 \n", balance);
        else {
            balance -= amount;
            printf("\n출금 후 현재 잔액: %d원 \n", balance);
        }
    }
}

int check_PW() {
    static int count = 0;
    int input_PW;
    printf("\n%s 시스템 비밀번호는?", name); scanf("%d", &input_PW);
    if (input_PW == system_PW)
        return 1;
    else {
        count++;
        return 0;
    }
}

14행

printf("%d원의 출금을 요청하셨으나", amount);

amount는 withdraw 함수 내부에 선언된 지역 변수이므로 main 함수에서 사용할 수 없다.

 

16행

printf("지금까지 %d번 비밀번호 오류 발생", count);

count는 check_PW 함수 내부에 선언된 지역 변수이므로 main 함수에서 사용할 수 없다.

 

28행

if (balance < amount)

balance는 main 함수 내부에 선언된 지역 변수이므로 다른 함수에서 사용할 수 없다.

 

29행

printf("\n잔액이 부족합니다. 현재 잔액 %d원 \n", balance);

마찬가지.

 

31행

balance -= amount;

마찬가지.

 

32행

printf("\n출금 후 현재 잔액: %d원 \n", balance);

마찬가지.

 

41행

if (input_PW == system_PW)

system_PW는 main 함수 내부에 선언된 지역 변수이므로 다른 함수에서 사용할 수 없다.

 

전역 변수로 선언하든가, 함수에 매개 변수를 넘겨주어야 사용할 수 있다.


2. 다음 프로그램 실행결과 화면의 밑줄 친 곳에 결과 값을 적으시오.
#include <stdio.h>

int sum(int end);

int total;

int main(void)
{
	int i;

	for (i = 1; i <= 3; i++)
		total += sum(i);

	printf("In main, total %2d\n", total);
	return 0;
}

int sum(int end)
{
	static int called = 0;
	int total = 0;
	int i;

	called++;

	for (i = 1; i <= 4; i++)
		total += i;

	printf("In sum, called = %2d, total %2d\n", called, total);

	return total;
}

In sum, called = 1, total = 10

In sum, called = 2, total = 10

In sum, called = 2, total = 10

In main, total = 30


3. 실행결과 화면과 같이 결과가 출력되도록 다음 프로그램을 완성하시오.
#include <stdio.h>

void static_sum(int end);

int main()
{
	int i;

	for (i = 0; i < 10; i++)
		static_sum(i);

	return 0;
}

//이전에 누적된 합계에 새로 호출된 값까지의 합을 계속 누적하기
void static_sum(int end)
{
	//작성하기
	static int count = 0, sum = 0;

	count++;
	printf("%2d번째 호출, ", count);
	printf("sum = %3d ", sum);
	for (int i = 0; i <= end + 1; i++)
		sum += i;
	printf("+ 1 ~ %2d까지의 합: %3d\n", end + 1, sum);
}

4.[프로그램 9-16]은 계좌 잔액을 저장하는 balance 변수를 전역 변수로 사용한다. 계좌 잔액을 함수에서 잘못 수정하는 것을 방지하기 위해 main 함수의 지역 변수로 선언하여 프로그램을 다시 작성하시오.

<프로그램 9-16>

#include <stdio.h>
#include <stdlib.h>		// exit, system 함수를 위한 헤더 파일
#include <conio.h>		// getch 함수를 위한 헤더 파일
#define PASS 1			// 비밀번호가 일치할 때의 반환 값 1을 매크로 상수로 정의
#define FAIL 0			// 비밀번호가 다를 때의 반환 값 0을 매크로 상수로 정의

void display_menu();	// 서비스 목록 표시
int check_PW();			// 비밀번호 확인 서비스
void check_balance();	// 잔액 조회 서비스
void deposit();			// 입금 서비스
void withdraw();		// 출금 서비스

int balance;			// 계좌의 현재 잔액을 저장하는 전역 변수

int main()
{		
	int service;		// 사용자가 원하는 서비스 번호

	printf("우리 시스템을 방문해 주셔서 감사합니다.");

	// 사용자가 그만두기를 원하지 않는 한 서비스를 계속 제공하기
	do
	{
		display_menu();			// 사용자에게 제공하는 서비스 목록 표시
		printf("원하는 서비스를 선택하세요. "); 
		scanf("%d", &service);	// 사용자가 원하는 서비스 번호 입력받기 
		
		switch (service)
		{
			case 1: check_balance(); break;	// 잔액 조회
			case 2: deposit(); break;		// 입금 처리
			case 3: withdraw(); break;		// 출금 처리
			case 4: exit(0);				// 프로그램 종료
		}

		/* 사용자가 서비스 결과 화면을 확인한 후 
		   아무 키나 누르면 현재 화면을 지우고 새 화면에서 다시 시작하기 */
		printf("\n계속 서비스를 원하시면 아무키나 누르세요.");
		getch();
		system("cls");
	} while (service != 4);		// 4. 그만두기를 선택하지 않는 한 계속 반복하기

	return 0;
}

// 잔액 조회 서비스 함수
void check_balance()
{
	if (check_PW() == PASS)
		printf("\n현재 잔액: %d원 \n", balance);
}

// 입금 서비스 함수
void deposit()
{
	int amount;
	
	printf("\n입금하실 금액은? "); scanf("%d", &amount);

	balance += amount;
	printf("\n입금 후 현재 잔액: %d원\n", balance);
}

// 출금 서비스 함수
void withdraw()
{
	int amount;
	
	if (check_PW() == PASS)
	{
		printf("출금하실 금액은? "); scanf("%d", &amount);
		if (balance < amount)
			printf("\n잔액이 부족합니다. 현재 잔액 %d원 \n", balance);
		else
		{
			balance -= amount;
			printf("\n출금 후 현재 잔액: %d원 \n", balance);
		}
	}
}

// 사용자의 비밀번호와 시스템 비밀번호를 비교해 일치 여부 반환하기
int check_PW()
{
	static int count = 0;	// 이 함수에서 발생한 비밀번호 오류 횟수를 저장하는 정적 지역 변수
	int system_PW = 1111;	// 정해진 시스템 서비스 비밀번호
	int limit = 3;			// 비밀번호 오류 제한 횟수
	int input_PW;			// 사용자가 입력한 비밀번호
	
	printf("\n시스템 비밀번호를 입력하세요.");
	scanf("%d", &input_PW);

	if (input_PW == system_PW)	// 비밀번호가 맞는 경우
		return PASS;
	else						// 비밀번호가 틀린 경우 
	{
		count++;				// 비밀번호 오류 발생 횟수를 1증가
		if (count == limit)		// 비밀번호 오류가 3회 발생한 경우
		{
			printf("비밀번호 오류 3회 발생! \n");
			printf("신분증을 가지고 서비스센터를 방문하세요. \n");
			exit(0);			// 프로그램 실행 종료
		}
		else					// 비밀번호 오류가 발생했으나 오류 발생이 아직 3회가 아닌 경우
		{
			printf("비밀번호가 틀렸습니다. 총 %d회 오류!\n", count);
			return FAIL;
		}
	}
}

void display_menu()
{
	printf("\n\n");
	printf("==================\n");
	printf("== 1. 잔액 조회 ==\n");
	printf("== 2. 입금      ==\n");
	printf("== 3. 출금      ==\n");
	printf("== 4. 그만하기  ==\n");
	printf("==================\n");
}

 

<수정한 프로그램>

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>		// exit, system 함수를 위한 헤더 파일
#include <conio.h>		// getch 함수를 위한 헤더 파일
#define PASS 1			// 비밀번호가 일치할 때의 반환 값 1을 매크로 상수로 정의
#define FAIL 0			// 비밀번호가 다를 때의 반환 값 0을 매크로 상수로 정의

void display_menu();	// 서비스 목록 표시
int check_PW();			// 비밀번호 확인 서비스
void check_balance(balance);	// 잔액 조회 서비스
int deposit(balance);			// 입금 서비스
int withdraw(balance);		// 출금 서비스


int main()
{
	int service;		// 사용자가 원하는 서비스 번호
	int balance;			// 계좌의 현재 잔액을 저장하는 전역 변수

	printf("우리 시스템을 방문해 주셔서 감사합니다.");

	// 사용자가 그만두기를 원하지 않는 한 서비스를 계속 제공하기
	do
	{
		display_menu();			// 사용자에게 제공하는 서비스 목록 표시
		printf("원하는 서비스를 선택하세요. ");
		scanf("%d", &service);	// 사용자가 원하는 서비스 번호 입력받기 

		switch (service)
		{
		case 1: check_balance(); break;	// 잔액 조회
		case 2: balance =  deposit(); break;		// 입금 처리
		case 3: balance = withdraw(); break;		// 출금 처리
		case 4: exit(0);				// 프로그램 종료
		}

		/* 사용자가 서비스 결과 화면을 확인한 후
		   아무 키나 누르면 현재 화면을 지우고 새 화면에서 다시 시작하기 */
		printf("\n계속 서비스를 원하시면 아무키나 누르세요.");
		_getch();
		system("cls");
	} while (service != 4);		// 4. 그만두기를 선택하지 않는 한 계속 반복하기

	return 0;
}

// 잔액 조회 서비스 함수
void check_balance(balance)
{
	if (check_PW() == PASS)
		printf("\n현재 잔액: %d원 \n", balance);
}

// 입금 서비스 함수
int deposit(balance)
{
	int amount;

	printf("\n입금하실 금액은? "); scanf("%d", &amount);

	balance += amount;
	printf("\n입금 후 현재 잔액: %d원\n", balance);

	return balance;
}

// 출금 서비스 함수
int withdraw(balance)
{
	int amount;

	if (check_PW() == PASS)
	{
		printf("출금하실 금액은? "); scanf("%d", &amount);
		if (balance < amount)
			printf("\n잔액이 부족합니다. 현재 잔액 %d원 \n", balance);
		else
		{
			balance -= amount;
			printf("\n출금 후 현재 잔액: %d원 \n", balance);
		}
	}

	return balance;
}

// 사용자의 비밀번호와 시스템 비밀번호를 비교해 일치 여부 반환하기
int check_PW()
{
	static int count = 0;	// 이 함수에서 발생한 비밀번호 오류 횟수를 저장하는 정적 지역 변수
	int system_PW = 1111;	// 정해진 시스템 서비스 비밀번호
	int limit = 3;			// 비밀번호 오류 제한 횟수
	int input_PW;			// 사용자가 입력한 비밀번호

	printf("\n시스템 비밀번호를 입력하세요.");
	scanf("%d", &input_PW);

	if (input_PW == system_PW)	// 비밀번호가 맞는 경우
		return PASS;
	else						// 비밀번호가 틀린 경우 
	{
		count++;				// 비밀번호 오류 발생 횟수를 1증가
		if (count == limit)		// 비밀번호 오류가 3회 발생한 경우
		{
			printf("비밀번호 오류 3회 발생! \n");
			printf("신분증을 가지고 서비스센터를 방문하세요. \n");
			exit(0);			// 프로그램 실행 종료
		}
		else					// 비밀번호 오류가 발생했으나 오류 발생이 아직 3회가 아닌 경우
		{
			printf("비밀번호가 틀렸습니다. 총 %d회 오류!\n", count);
			return FAIL;
		}
	}
}

void display_menu()
{
	printf("\n\n");
	printf("==================\n");
	printf("== 1. 잔액 조회 ==\n");
	printf("== 2. 입금      ==\n");
	printf("== 3. 출금      ==\n");
	printf("== 4. 그만하기  ==\n");
	printf("==================\n");
}

5. 다음과 같이 판매 상품 5가지의 정보를 보여주고 사용자가 물건을 주문하는 프로그램을 작성하시오.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>		// exit, system 함수를 위한 헤더 파일
#include <conio.h>		// getch 함수를 위한 헤더 파일

#define N 6
char name[N][7] = { "", "노트", "연필", "지우개", "자", "볼펜" };
int unit_cost[N] = { 0, 1000, 500, 300, 800, 1500 };
int number[N] = { 0 };

void display_menu();	// 서비스 목록 표시
void order();	//상품 주문 서비스
void order_list();	//주문서 확인 서비스


int main()
{
	int service;		// 사용자가 원하는 서비스 번호
	int balance;			// 계좌의 현재 잔액을 저장하는 전역 변수

	printf(">>환영합니다.");

	// 사용자가 그만두기를 원하지 않는 한 서비스를 계속 제공하기
	do
	{
		display_menu();			// 사용자에게 제공하는 서비스 목록 표시
		printf("원하는 서비스를 선택하세요. ");
		scanf("%d", &service);	// 사용자가 원하는 서비스 번호 입력받기
		switch (service) {
		case 1: order(); break;
		case 2: order_list(); break;
		case 3: exit(0);
		}

		/* 사용자가 서비스 결과 화면을 확인한 후
		   아무 키나 누르면 현재 화면을 지우고 새 화면에서 다시 시작하기 */
		printf("\n계속 서비스를 원하시면 아무키나 누르세요.");
		_getch();
		system("cls");
	} while (service != 3);		// 3. 종료하기를 선택하지 않는 한 계속 반복하기

	return 0;
}

void display_menu()
{
	printf("\n\n");
	printf("========================\n");
	printf("== 1. 상품 주문하기   ==\n");
	printf("== 2. 주문서 확인하기 ==\n");
	printf("== 3. 종료하기        ==\n");
	printf("========================\n");
}

void order()
{	
	int thing, total;
	printf(">>상품 주문 서비스입니다.\n");
	printf("========================\n");
	for(int i = 1; i < N; i++)
		printf("%d %6s     %4d\n", i, name[i], unit_cost[i]);
	printf("========================\n");
	
	printf("원하는 상품의 번호는? ");
	scanf("%d", &thing);
	printf("%s을(를) 주문할 개수는? ", name[thing]);
	scanf("%d", &number[thing]);

	total = unit_cost[thing] * number[thing];
	printf("주문하신 %s %d개는 총 %d원입니다.\n", name[thing], number[thing], total);
}

void order_list()
{
	int total = 0, sum = 0;
	printf("\n\n");
	printf("상품 주문 내역서\n");
	printf("========================\n");
	printf("상품명   개수   가격\n");
	printf("------------------------\n");
	for (int i = 1; i < N; i++) {
		if (number[i] == 0) continue;	//주문하지 않은 물건은 생략
		total = unit_cost[i] * number[i];
		printf("%6s    %2d    %5d\n", name[i], number[i], total);
		sum += total;
	}
	printf("========================\n");
	printf("총액            %5d원\n", sum);
}

 

<실행 화면>

1.gif