하나의 프로그램 안에서 하나 이상의 함수를 사용할 때 발생하는 문제를 다룬다.
10.1 : local variables
10.2 : external variables
10.3 : blocks (compound statements containing declarations)
10.4 : c의 'scope - 범위 or 변수 범위'. local, external, blocks안에서 선언된 name의 규칙
10.5 : 함수 프로토타입, 함수 정의, 변수선언 등에 대한 방법
10.1 Local Variables
함수의 body 안에서 선언된 변수를 그 함수에 local하다, local variable이다라고 한다.
int sum_digits(int n) {
int sum = 0; /* local variable */
while (n > 0) {
sum += n % 10;
n /= 10;
}
return sum;
}
properties of local variables
automatic storage duration: storage duration (or extent)은 프로그램 내에서 변수를 위한 storage(저장공간?)가 존재하는 부분을 말한다. local variable의 storage는 그 변수가 속한 함수가 호출될 때 '자동적으로' allocate(할당)되고, 함수가 return할 때 deallocate(해제?)된다. local variable은 속한 함수가 값을 리턴했을 때 값을 유지하지 않는다. 따라서 함수가 다시 호출되었을 때, 예전 값을 유지한다는 보장이 없다.
block scope : 변수의 scope(범위)는 프로그램 중에서 그 변수가 참조될 수 있는 부분이다. local variable은 'block scope'를 갖는다. 그 변수의 선언부터, 속한 함수 body의 끝 부분까지. local variable의 범위가 속한 함수를 넘지 못하기 때문에, 다른 함수에서는 같은 이름의 변수를 다른 목적으로 사용할 수 있다.
(C99) C99에서는 변수의 선언이 반드시 함수의 맨 처음에 오지 않아도 되기 때문에, local variable의 범위를 아주 작게 할 수도 있다.
Static Local Variables
로컬 변수 선언시에 'static'을 추가하면, 그 변수는 automatic storage duration이 아닌 static storage duration을 갖는다. 이제 이 변수의 storage는 함수가 끝날 때 같이 끝나지 않고 프로그램이 끝날 때까지 유지된다. 그러나, 여전히 block scope를 가지며 다른 함수에서 visible하지 않다.
void f(void) {
static int i; /* static local variable */
...
}
Parameters
파라미터도 local variable과 같은 특성을 가진다(automatic storage duration, block scope).
파라미터와 local variable의 유일한 실질적인 차이점은 파라미터는 함수가 호출될 때 자동적으로 initialize된다는 것.
10.2 External Variables
함수와의 정보 전달은 passing argument를 통해서도 가능하지만, exeternal variable을 통해서도 가능하다.
external variable(또는, global variable)은 함수 몸체 바깥에서 선언된 변수이다.
properties of external variables
static storage duration : static으로 선언된 local variable과 같다. 한번 변수에 저장된 값은 계속 저장되어 있다.
file scope : 변수가 선언된 시점부터 프로그램이 끝날 때까지 visible하다. 따라서 선언 이후에 나오는 모든 함수에서 접근하고 값을 수정할 수 있다.
using external variables to implement a stack(fragment)
더보기 접기
#include <stdbool.h>
#define STACK_SIZE 100
/* external variables */
int contents[STACK_SIZE];
int top = 0;
void make_empty(void) {
top = 0;
}
bool is_empty(void) {
return top == 0;
}
bool is_full(void) {
return top == STACK_SIZE;
}
void push(int i) {
if (is_full())
stack_overflow();
else
contents[top++] = i;
}
int pop(void) {
if (is_empty())
stack_underflow();
else
return contents[--top];
}
접기
Pros and Cons of External Variables
다수의 함수가 하나의 변수를 공유하거나, 몇개의 함수가 다수의 변수를 공유할 때 external variable을 사용하면 편리하다.
그러나 대부분의 경우에는 parameter를 통한 전달이 변수를 공유하는 것보다 낫다. 그 이유는
- 프로그램을 관리하면서 external variable을 수정할 때(type 등) 그것이 각각의 함수에 대해 어떤 영향을 미치는지 일일이 체크해야 한다.
- external variable에 잘못된 값이 할당되었을 때, 어떤 함수가 잘못되었는지 찾기 힘들다.
- external variable에 의존하는 함수는 다른 프로그램에서 재사용하기가 힘들다. (not self-contained)
재사용을 위해 그 함수가 필요로 하는 모든 external variable까지 같이 가져가야 한다.
external variable을 남용하는 프로그래머들이 많다.
external variable을 사용할 때는, 의미있는 이름을 사용해야 한다.
숫자 맞추기 게임(external variable을 사용)
더보기 접기
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#pragma warning(disable:4996)
#define MAX_NUMBER 100
/* external variables */
int secret_number;
/* prototypes */
void initialize_number_generator(void);
void choose_new_secret_number(void);
void read_guesses(void);
int main(void) {
char command;
printf("Guess the secret number between 1 and %d.\n\n", MAX_NUMBER);
initialize_number_generator();
do {
choose_new_secret_number();
printf("A new number has been chosen.\n");
read_guesses();
printf("Play again? (Y/N) ");
scanf(" %c", &command);
printf("\n");
} while (command == 'y' || command == 'Y');
return 0;
}
/**********************************************************
* initialize_number_generator: Initializes the random *
* number generator using *
* the time of day. *
**********************************************************/
void initialize_number_generator(void) {
srand((unsigned) time(NULL));
}
/**********************************************************
* choose_new_secret_number: Randomly selects a number *
* between 1 and MAX_NUMBER and *
* stores it in secret_number. *
**********************************************************/
void choose_new_secret_number(void) {
secret_number = rand() % MAX_NUMBER + 1;
}
/**********************************************************
* read_guesses: Repeatedly reads user guesses and tells *
* the user whether each guess is too low, *
* too high, or correct. When the guess is *
* correct, prints the total number of *
* guesses and returns. * *
**********************************************************/
void read_guesses(void) {
int guess, num_guesses = 0;
for (;;) {
num_guesses++;
printf("Enter guess: ");
scanf("%d", &guess);
if (guess == secret_number) {
printf("You won in %d guesses!\n\n", num_guesses);
return;
}
else if (guess < secret_number)
printf("Too low; try again.\n");
else
printf("Too high; try again.\n");
}
}
접기
숫자 맞추기(external variable 사용하지 않고. 바뀐 부분은 볼드체)
더보기 접기
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#pragma warning(disable:4996)
#define MAX_NUMBER 100
void initialize_number_generator(void);
int new_secret_number(void);
void read_guesses(int secret_number );
int main(void) {
char command;
int secret_number;
printf("Guess the secret number between 1 and %d.\n\n", MAX_NUMBER);
initialize_number_generator();
do {
secret_number = new_secret_number();
printf("A new number has been chosen.\n");
read_guesses(secret_number);
printf("Play again? (Y/N) ");
scanf(" %c", &command);
printf("\n");
} while (command == 'y' || command == 'Y');
return 0;
}
/**********************************************************
* initialize_number_generator: Initializes the random *
* number generator using *
* the time of day. *
***********************************************************/
void initialize_number_generator(void) {
srand((unsigned)time(NULL));
}
/**********************************************************
* new_secret_number: Returns a randomly chosen number *
* between 1 and MAX_NUMBER *
***********************************************************/
int new_secret_number (void) {
return rand() % MAX_NUMBER + 1;
}
/**********************************************************
* read_guesses: Repeatedly reads user guesses and tells *
* the user whether each guess is too low, *
* too high, or correct. When the guess is *
* correct, prints the total number of *
* guesses and returns. * *
***********************************************************/
void read_guesses(int secret_number ) {
int guess, num_guesses = 0;
for (;;) {
num_guesses++;
printf("Enter guess: ");
scanf("%d", &guess);
if (guess == secret_number) {
printf("You won in %d guesses!\n\n", num_guesses);
return;
}
else if (guess < secret_number)
printf("Too low; try again.\n");
else
printf("Too high; try again.\n");
}
}
접기
10.3 Blocks
앞서 5.2에서 여러개의 statement를 묶어 { statements } 로 만든 것을 다뤘다. (selection statement에서)
이제부터 여러개의 statement를 중괄호로 묶은 것을 block이라고 표현한다.
block 안에 변수의 선언도 들어갈 수 있는데, 그렇게 선언된 변수들은 automatic storage duration, block scope이다.
블럭 안에서 변수를 선언하는것의 장점 - 아주 잠깐 사용할 변수들을 함수 앞부분에 정의해 어수선하게 만들지 않아도 된다. name conflict를 줄인다.
(C99) 함수와 마찬가지로, 블럭 안 어디서나 변수를 선언할 수 있다.
10.4 Scope
범위에 대한 규칙
블럭 내에서 선언된 변수의 이름이 이미 visible한(file scope이거나, 소속한 블럭에서 이미 선언되었거나) identifier(식별자: https://msdn.microsoft.com/ko-kr/library/e7f8y25b.aspx )경우, 새로운 선언은 예전 것을 'hide'하고, 식별자는 새로운 의미를 갖는다. 그 블럭이 끝나면, 그 식별자는 다시 예전 의미를 다시 얻는다.
10.5 Organizing a C Program
여기서는 하나의 파일 안에서 이뤄지는 프로그램을 다룸. 여러개의 파일을 사용하는 프로그램은 15장에서 다룸.
프로그램 순서 예시:
#include directives
#define directives
Type definitions
Declarations of external variables
Prototypes for functions other than main
Definition of main
Definitions of other functions
포커 점수 계산
더보기 접기
/* #include directives go here */
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
/* #define directives go here */
#define NUM_RANKS 13
#define NUM_SUITS 4
#define NUM_CARDS 5
/* declarations of external variables go here */
int num_in_rank[NUM_RANKS];
int num_in_suit[NUM_SUITS];
bool straight, flush, four, three;
int pairs; /* can be 0, 1, or 2 */
/* prototypes */
void read_cards(void);
void analyze_hand(void);
void print_result(void);
/******************************************************************
main: Calls read_cards, analyze_hand, and print_result
repeatedly.
******************************************************************/
int main(void) {
for (;;) {
read_cards();
analyze_hand();
print_result();
}
}
/******************************************************************
read_cards: Reads the cards into external variables;
checks for bad cards and duplicate cards.
******************************************************************/
void read_cards(void) {
bool card_exists[NUM_RANKS][NUM_SUITS];
char ch, rank_ch, suit_ch;
int rank, suit;
bool bad_card;
int cards_read = 0;
for (rank = 0; rank < NUM_RANKS; rank++) {
num_in_rank[rank] = 0;
for (suit = 0; suit < NUM_SUITS; suit++)
card_exists[rank][suit] = false;
}
for (suit = 0; suit < NUM_SUITS; suit++)
num_in_suit[suit] = 0;
while (cards_read < NUM_CARDS) {
bad_card = false;
printf("Enter a card: ");
rank_ch = getchar();
switch (rank_ch) {
case '0': exit(EXIT_SUCCESS);
case '2': rank = 0; break;
case '3': rank = 1; break;
case '4': rank = 2; break;
case '5': rank = 3; break;
case '6': rank = 4; break;
case '7': rank = 5; break;
case '8': rank = 6; break;
case '9': rank = 7; break;
case 't': case 'T': rank = 8; break;
case 'j': case 'J': rank = 9; break;
case 'q': case 'Q': rank = 10; break;
case 'k': case 'K': rank = 11; break;
case 'a': case 'A': rank = 12; break;
default: bad_card = true;
}
suit_ch = getchar();
switch (suit_ch) {
case 'c': case 'C': suit = 0; break;
case 'd': case 'D': suit = 1; break;
case 'h': case 'H': suit = 2; break;
case 's': case 'S': suit = 3; break;
default: bad_card = true;
}
while ((ch = getchar()) != '\n')
if (ch != ' ') bad_card = true;
if (bad_card)
printf("Bad card; ignored.\n");
else if (card_exists[rank][suit])
printf("Duplicate card; ignored.\n");
else {
num_in_rank[rank]++;
num_in_suit[suit]++;
card_exists[rank][suit] = true;
cards_read++;
}
}
}
/******************************************************************
analyze_hand: Determines whether the hand contains a
straight, a flush, four-of-a-kind,
and/or three-of-a-kind; determines the number of pairs;
stores the results into external variables.
******************************************************************/
void analyze_hand(void) {
int num_consec = 0;
int rank, suit;
straight = false;
flush = false;
four = false;
three = false;
pairs = 0;
/* check for flush */
for (suit = 0; suit < NUM_SUITS; suit++)
if (num_in_suit[suit] == NUM_CARDS)
flush = true;
/* check for straight */
rank = 0;
while (num_in_rank[rank] == 0) rank++;
for (; rank < NUM_RANKS && num_in_rank[rank] > 0; rank++)
num_consec++;
if (num_consec == NUM_CARDS) {
straight = true;
return;
}
/* check for 4-of-a-kind, 3-of-a-kind, and pairs */
for (rank = 0; rank < NUM_RANKS; rank++) {
if (num_in_rank[rank] == 4) four = true;
if (num_in_rank[rank] == 3) three = true;
if (num_in_rank[rank] == 2) pairs++;
}
}
/******************************************************************
print_result: Notifies the user of the result, using
the external variables set by analyze_hand.
******************************************************************/
void print_result(void) {
if (straight && flush) printf("Straight flush");
else if (four) printf("Four of a kind");
else if (three &&
pairs == 1) printf("Full house");
else if (flush) printf("Flush");
else if (straight) printf("Straight");
else if (three) printf("Three of a kind");
else if (pairs == 2) printf("Two pairs");
else if (pairs == 1) printf("Pair");
else printf("High card");
printf("\n\n");
}
접기
문제풀이 접기
1번 stack을 활용해 괄호 - (, {, [ 가 제대로 nested되었는지 검사하는 프로그램 만들기
/*
1. read characters while input character is not newline.
2. when it reads (, {, [ : push the character into stack.
2. when it reads ), }, ] : pop from the stack and check that the item popped is a matched parenthesis or brace. (if not, NOT MATCHED)
3. when it reads new line, check stack is empty. if if is, MATCHED. if underflow called, NOT MATCHED
4. if overflow called, print the msg 'Stack Overflow' and terminate immediately.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 100
/* external variables */
int contents[STACK_SIZE];
int top = 0;
/* function prototypes */
void make_empty(void);
bool is_empty(void);
bool is_full(void);
void push(char ch);
char pop(void);
void stack_overflow(void);
void stack_underflow(void);
bool check_brace(char right);
void matched(void);
void not_matched(void);
/* Stack Functions */
void make_empty(void) { top = 0; }
bool is_empty(void) { return top == 0; }
bool is_full(void) { return top == STACK_SIZE; }
void push(char ch) {
if (is_full())
stack_overflow();
else
contents[top++] = ch; }
char pop(void) {
if (is_empty())
stack_underflow();
else
return contents[--top]; }
void stack_overflow(void) {
printf("Stack Overflow\n");
exit(EXIT_FAILURE); // stdlib.h
}
void stack_underflow(void) {
not_matched();
}
/* End of Stack Functions*/
int main(void) {
char ch;
make_empty();
printf("Enter parentheses and/or brace: ");
while ((ch = getchar()) != '\n') {
if (ch == 40 || ch == 123 || ch == 91)
push(ch);
else if ((ch == 41 || ch == 125 || ch == 93) && !check_brace(ch))
not_matched();
}
if (is_empty())
matched();
else
not_matched();
}
bool check_brace(char right) {
char left = pop();
return (left == 40 && right == 41) || (left == 123 && right == 125) || (left == 91 && right == 93);
}
void matched(void) {
printf("Parentheses/braces are nested properly.\n");
exit(EXIT_SUCCESS);
}
void not_matched(void) {
printf("Parentheses/braces are NOT nested properly.\n");
exit(EXIT_SUCCESS);
}
2번 poker.c에서 num_in_rank와 num_int_suit 배열을 main 안으로 집어넣기
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
/* #define directives go here */
#define NUM_RANKS 13
#define NUM_SUITS 4
#define NUM_CARDS 5
/* declarations of external variables go here */
bool straight, flush, four, three;
int pairs; /* can be 0, 1, or 2 */
/* prototypes */
void read_cards(int num_in_rank[], int num_in_suit[] );
void analyze_hand(int num_in_rank[], int num_in_suit[] );
void print_result(void);
/******************************************************************
main: Calls read_cards, analyze_hand, and print_result
repeatedly.
******************************************************************/
int main(void) {
for (;;) {
int num_in_rank[NUM_RANKS];
int num_in_suit[NUM_SUITS];
read_cards(num_in_rank, num_in_suit );
analyze_hand(num_in_rank, num_in_suit );
print_result();
}
}
/******************************************************************
read_cards: Reads the cards into external variables;
checks for bad cards and duplicate cards.
******************************************************************/
void read_cards(int num_in_rank[], int num_in_suit[] ) {
bool card_exists[NUM_RANKS][NUM_SUITS];
char ch, rank_ch, suit_ch;
int rank, suit;
bool bad_card;
int cards_read = 0;
for (rank = 0; rank < NUM_RANKS; rank++) {
num_in_rank[rank] = 0;
for (suit = 0; suit < NUM_SUITS; suit++)
card_exists[rank][suit] = false;
}
for (suit = 0; suit < NUM_SUITS; suit++)
num_in_suit[suit] = 0;
while (cards_read < NUM_CARDS) {
bad_card = false;
printf("Enter a card: ");
rank_ch = getchar();
switch (rank_ch) {
case '0': exit(EXIT_SUCCESS);
case '2': rank = 0; break;
case '3': rank = 1; break;
case '4': rank = 2; break;
case '5': rank = 3; break;
case '6': rank = 4; break;
case '7': rank = 5; break;
case '8': rank = 6; break;
case '9': rank = 7; break;
case 't': case 'T': rank = 8; break;
case 'j': case 'J': rank = 9; break;
case 'q': case 'Q': rank = 10; break;
case 'k': case 'K': rank = 11; break;
case 'a': case 'A': rank = 12; break;
default: bad_card = true;
}
suit_ch = getchar();
switch (suit_ch) {
case 'c': case 'C': suit = 0; break;
case 'd': case 'D': suit = 1; break;
case 'h': case 'H': suit = 2; break;
case 's': case 'S': suit = 3; break;
default: bad_card = true;
}
while ((ch = getchar()) != '\n')
if (ch != ' ') bad_card = true;
if (bad_card)
printf("Bad card; ignored.\n");
else if (card_exists[rank][suit])
printf("Duplicate card; ignored.\n");
else {
num_in_rank[rank]++;
num_in_suit[suit]++;
card_exists[rank][suit] = true;
cards_read++;
}
}
}
/******************************************************************
analyze_hand: Determines whether the hand contains a
straight, a flush, four-of-a-kind,
and/or three-of-a-kind; determines the number of pairs;
stores the results into external variables.
******************************************************************/
void analyze_hand(int num_in_rank[], int num_in_suit[] ) {
int num_consec = 0;
int rank, suit;
straight = false;
flush = false;
four = false;
three = false;
pairs = 0;
/* check for flush */
for (suit = 0; suit < NUM_SUITS; suit++)
if (num_in_suit[suit] == NUM_CARDS)
flush = true;
/* check for straight */
rank = 0;
while (num_in_rank[rank] == 0) rank++;
for (; rank < NUM_RANKS && num_in_rank[rank] > 0; rank++)
num_consec++;
if (num_consec == NUM_CARDS) {
straight = true;
return;
}
/* check for 4-of-a-kind, 3-of-a-kind, and pairs */
for (rank = 0; rank < NUM_RANKS; rank++) {
if (num_in_rank[rank] == 4) four = true;
if (num_in_rank[rank] == 3) three = true;
if (num_in_rank[rank] == 2) pairs++;
}
}
/******************************************************************
print_result: Notifies the user of the result, using
the external variables set by analyze_hand.
******************************************************************/
void print_result(void) {
if (straight && flush) printf("Straight flush");
else if (four) printf("Four of a kind");
else if (three &&
pairs == 1) printf("Full house");
else if (flush) printf("Flush");
else if (straight) printf("Straight");
else if (three) printf("Three of a kind");
else if (pairs == 2) printf("Two pairs");
else if (pairs == 1) printf("Pair");
else printf("High card");
printf("\n\n");
}
6번 RPN 계산기
/* Project 6*/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#pragma warning(disable:4996)
#define STACK_SIZE 100
/**** STACK ****/
/* external variables */
int contents[STACK_SIZE];
int top = 0;
void make_empty(void) {
top = 0;
}
bool is_empty(void) {
return top == 0;
}
bool is_full(void) {
return top == STACK_SIZE;
}
void stack_underflow(void) {
printf("Not enough operands in expression.\n");
exit(EXIT_FAILURE);
}
void stack_overflow(void) {
printf("Expression is too complex.\n");
exit(EXIT_FAILURE);
}
void push(int i) {
if (is_full())
stack_overflow();
else
contents[top++] = i;
}
int pop(void) {
if (is_empty())
stack_underflow();
else
return contents[--top];
}
/**** END OF STACK ****/
/* function prototypes */
void read_expression(void);
void read_operand(int i);
void read_operator(char ch);
void print_result(void);
int main(void) {
read_expression();
return 0;
}
void read_expression(void) {
char ch;
make_empty();
printf("Enter an RPN expression: ");
while (1) {
scanf(" %c", &ch);
if (ch == 'q' || ch == 'Q')
exit(EXIT_SUCCESS);
else if (ch == '=')
print_result();
else if (ch >= 48 && ch <= 57)
read_operand(ch - 48);
else
read_operator(ch);
}
}
void read_operand(int i) {
push(i);
}
void read_operator(char ch) {
int i, j, result;
j = pop();
i = pop();
switch (ch) {
case '+': result = i + j; push(result); break;
case '-': result = i - j; push(result); break;
case '*': result = i * j; push(result); break;
case '/': result = i / j; push(result); break;
default: printf("input error.\n"); exit(EXIT_FAILURE);
}
}
void print_result() {
int result;
result = pop();
printf("Value of expression: %d\n", result);
read_expression();
}
7번 7-segment display
/* Project 7 */
#include <stdio.h>
#include <stdbool.h>
#pragma warning(disable:4996)
#define MAX_DIGITS 10
#define HEIGHT 4
#define TOTAL_DIGITS 10
#define TOTAL_SEGMENTS 7
const int segments[TOTAL_DIGITS][TOTAL_SEGMENTS] = {
{ 1, 1, 1, 1, 1, 1, 0 },
{ 0, 1, 1, 0, 0, 0, 0 },
{ 1, 1, 0, 1, 1, 0, 1 },
{ 1, 1, 1, 1, 0, 0, 1 },
{ 0, 1, 1, 0, 0, 1, 1 },
{ 1, 0, 1, 1, 0, 1, 1 },
{ 1, 0, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 0, 1, 1 }
};
char digits[HEIGHT][MAX_DIGITS * 4];
/* function prototypes */
void clear_digits_array(void);
/* stores blank characters into all elements of the digits array */
void process_digit(int digit, int position);
/* stores the seven-segment representation of digit into a specified position
in the digits array (positions range from 0 to MAX_DIGITS - 1) */
void print_digits_array(void);
/* displays the rows of the digits array, each on a single line, producing output */
int main(void) {
int position;
char ch;
clear_digits_array();
position = 0;
printf("Enter a number: ");
ch = getchar();
while (position < 10 && (ch != '\n')) {
if (ch >= 48 && ch <= 57) {
process_digit(ch - 48, position);
position++;
}
ch = getchar();
}
print_digits_array();
return 0;
}
void clear_digits_array(void) {
int i, j;
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < MAX_DIGITS; j++) {
digits[i][j] = ' ';
}
}
}
void process_digit(int digit, int position) {
int start = position * 4;
int i;
for (i = 0; i < TOTAL_SEGMENTS; i++) {
if (segments[digit][i] == 1) {
switch(i) {
case 0:
digits[0][start + 1] = '_'; break;
case 1:
digits[1][start + 2] = '|'; break;
case 2:
digits[2][start + 2] = '|'; break;
case 3:
digits[2][start + 1] = '_'; break;
case 4:
digits[2][start] = '|'; break;
case 5:
digits[1][start] = '|'; break;
case 6:
digits[1][start + 1] = '_'; break;
}
}
}
}
void print_digits_array(void) {
int i, j;
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < MAX_DIGITS * 4; j++) {
printf("%c", digits[i][j]);
}
printf("\n");
}
}
접기