1) 지식 창고는 본인이 작성한 콘텐츠(팁/노하우/리소스/강좌 등)을 무료 혹은 가상화폐인 납포인트를 통해 공유하는 공간입니다.
2) 본인이 작성한 콘텐츠에 대해서만 지식 창고에 등록할 수 있으며, 저작권에 위배되는 콘텐츠는 사전경고 없이 삭제될 수 있습니다.
3) 콘텐츠 구매 및 첨부파일 다운로드는 회원그룹 '연구원' 이상 가능하오니, 경험치를 쌓아 진급한 후에 이용 부탁드립니다.
4) 무료 콘텐츠의 본문은 구매절차 없이 즉시 이용할 수 있으며, 판매 납포인트가 있는 콘텐츠는 구매 후 이용할 수 있습니다.
5) 콘텐츠 판매에 따른 납포인트 수익은 지정한 비율(50%)에 따라 판매자에게 지급하며, 납포인트 수익을 통해 진급을 빨리할 수 있습니다.
6) 구매 후 평가를 하면 구매 납포인트의 20%를 돌려 드립니다.
판매자 | 프리미엄 | 판매 납포인트 | 무료 | 평점 | 0점 / 총 0명 참여 |
---|
***************************< 캠퍼스 C 강좌 >******************************
[제목] :
[코드] : campusc1-019 (초급)
[교재] : CAMPUS C (초급, Third edition) [출판사 : 책과스승]
[알림] :이 파일은 "캠퍼스 C"에서 모든 분께 공개한 "초급 강좌"입니다.
이 [알림]의 내용을 지우지 않는다면 누구에게나 임의로 복사해 줄 수
있습니다.그러나 이 강좌 내용에 대한 저작권은 "캠퍼스 C"에 있습니다.
[연락처] : 605-8662 (서울) ("캠퍼스 C", 도서출판 "책과 스승")
천리안 : go campusc
나우콤 : go lcampc
하이텔 ID : campusc
****************************<< 목 차 >>************************************
<1> 구조체 (struct)의 다양한 형태 및 사용법
1> 구조체의 기본 표현법 ( 3 x 3 = 9 가지 )
2> 보통 변수 ( mazinga )에서 3가지
3> 배열로 ( robocop[3] ) 에서 3가지
4> 포인터 ( *asura )에서 3가지
5> 중첩된 구조체
<2> 프로그램 응용
**************************< 내용 시작 >********************************
1> 구조체의 기본 표현법 ( 3 x 3 = 9 가지 )
-----------------------------------------------------------------------
우리는 이제 다음과 같은 표현 3 가지( 보통, 배열, 포인터 ) 정도
는 가볍게 이해 할 수 있을 것입니다.
char lim_chungha; <-- ( 경우 1 )
char rambo[3]; <-- ( 경우 2 )
char *ma_dangbal <-- ( 경우 3 )
그런데 스트락춰 라는건 위와 같은 "보통의 데이타 타입"을 묶음으
로 표현 한것 이기 때문에 아래와 같은 표현이 가능하다고 했다.
struct xxx {
char lim_chungha; <-- ( 경우 1 )
char rambo[3]; <-- ( 경우 2 )
char *ma_dangbal <-- ( 경우 3 )
};
struct xxx mazinga;
위와 같은 표현법은 복잡하게 보이지만, struct xxx 를 한단어로 봐 주면
다음과 같이 char, int, long 따위의 데이타 형과 다를 것이 아무것도 없는
것이다.
struct xxx mazinga;
char mazinga2;
int mazinga3;
long mazinga4;
따라서 스트락춰 에서도 다음과 같은 3가지 표현 ( 보통, 배열, 포인터 )은
지극히 자연스러운 것이다.
struct xxx mazinga; <-- ( 보통 )
struct xxx robocop[3]; <-- ( 배열 )
struct xxx *asura; <-- ( 포인터 )
이제 이걸 종합해 보면 다음과 같이 3 가지 x 3가지 경우가 되는데
struct xxx {
char lim_chungha; <-- ( 경우 1 )
char rambo[3]; <-- ( 경우 2 )
char *ma_dangbal <-- ( 경우 3 )
} mazinga, robocop[3], *asura; <--- ( 경우 3 가지)
아시겠지만, 이걸 전부 표현 하려면 이른바 조합에서 나오는 경우
의 수에 따라 3 x 3 = 9 가지의 표현법이 필요하게 된다.
이 표현법은 스트락춰에서 기본에 해당한다. 그리고 이걸 기본으
로 하여 증가(++), 감소(--) 따위의 연산자와 복합적으로 쓰이는 것을 공부
하면 C 의 연산자를 마스타(정복) 했다고 해도 좋다.
그만큼 우리의 강좌는 종반으로 치닫고 있다는 것이고, 표현법 중
에서는 지금 부터 우리가 다룰 내용이 가장 어려운 마지막 고개에 해당한
다. 이것만 넘으면 사실상 어려운 것은 없다. (표현법에서)
이제 부터 아래 에서는 각 경우의 수를 알아보겠다. 고등학교때 행
렬(matrix)를 공부 하셨겠지만, 3 곱하기 3의 바둑판 그림을 크게 그려 놓
고 다음에 나오는 각 3 가지 경우의 표현법을 나름대로 정리 하시길 바란다
-----------------------------------------------------------------------
2> 보통 변수로 선언 할때
-----------------------------------------------------------------------
보통 변수란 지난 시간에 보았듯이, 아래와 같이 mazinga로 선언되는 경우
이다.
struct robot {
int head;
int arms[2];
int *finger;
} mazinga; <-- 보통 변수 ( 배열이나 포인터가 아닌)
<비교> int atom;
이건 마치 위 <비교>의 atom과 같이 보통 변수 를 의미하고 지난
시간에 스트락춰의 기초로서 살펴 보았다. 이 내용은 다음에 나올 배열, 포
인터 의 기초가 되는 내용이다. 지난 시간에도 언급했지만, 스트락춰의 내용
을 이해 하기 위해서는 [229쪽]의 메모리 구조를 이해 하고 있는것이 제일
좋은 방법이다. 각 변수에 100을 넣어 주려면 다음과 같이 한다.
1) 값을 대입 하고 읽는법
struct robot {
int head;
int arms[2];
int *finger;
} mazinga;
main()
{
mazinga.head = 100; <-- (보통).(보통) (경우 1)
mazinga.arms[0] = 100; <-- (보통).(배열) (경우 2)
mazinga.finger = (int *)100; <-- (보통).(포인터) (경우 3)
printf("%x ",mazinga.head );
printf("%x ",mazinga.arms[0]);
printf("%x ",mazinga.finger );
}
2) 주소를 알아 보려면 다음과 같이 한다.
main()
{
printf("%x ",&mazinga.head );
printf("%x ",&mazinga.arms[0]);
printf("%x ",&mazinga.finger );
}
즉 앞에다 &만 붙이면 되는데, 이제부터 확실히 구별을 해야 한다. 아래를
비교하자
1) printf("%x ", mazinga.&head ); <-- (x)
2) printf("%x ",&mazinga.head ); <-- (o)
내용상은 head의 주소를 찍는것 이기 때문에 위 1)번 표현이 맞을것 같기도
하다. 그러나 & 는 연산자 표에도 있듯이 "<--"의 방향성을 갖는다. 또한 도
트 "." 연산자의 결합성이 더 높기 때문에, 그 사이는 감히 끼어 들지 못
하고, 제일 앞에 표시를 한다. 지금 이 설명은 말이 이상한데, 다음과 같은
의도로 봐달라는 뜻이다.
----------------
& mazinga.head
----------------
3) 포인터가 가리키는 값을 찍는법
main()
{
printf("%x \n", *mazinga.finger );
}
-----------------------------------------------------------------------
3> 배열로 선언 할때
-----------------------------------------------------------------------
배열로 선언 하는 것도 보통 변수의 배열과 거의 유사하다. 아래를 보자.
struct robot {
int head;
int arms[2];
int *finger;
} robocop[3]; <-- 배열 변수
이건 간단하게 말로 하면 " struct robot "라는 설계도로 쌍둥이 로보트 3개
를 만든것과 같다.
이것도 역시 메모리 구조로서 이해 하는것이 가장 좋은 방법이다.
이쯤 되면 우리도 말이 필요 없을 경지에 이르지 않았을까 생각한다.
1) 값을 대입 하고 읽는법
struct robot {
int head;
int arms[2];
int *finger;
} robocop[3]; <-- 배열 변수
main()
{
robocop[0].head = 100; <-- (배열).(보통)
robocop[0].arms[0] = 100; <-- (배열).(배열)
robocop[0].finger = (int *)100; <-- (배열).(포인터)
printf("%x ",robocop[0].head );
printf("%x ",robocop[0].arms[0]);
printf("%x ",robocop[0].finger );
}
2) 주소를 알아 보려면 다음과 같이 한다.
main()
{
printf("%x ",&robocop[0].head );
printf("%x ",&robocop[0].arms[0]);
printf("%x ",&robocop[0].finger );
}
그냥 앞에 & 를 붙인다. (간단)
3) 포인터가 가리키는 값을 찍는법
main()
{
printf("%x \n", *robocop[0].finger );
}
여기서 한가지 상식으로 스트락춰의 형태를 해석하는 순서는
---------------
(좌 --> 우)
---------------
라는 것을 상기 할 필요가 있다. 이것은 굳이 밝히지 않더라도 무의식적으
로 이렇게 생각하고 있을것 이다.
예를 들면 위에서 robocop[0].arms[0]의 경우 먼저 robocop[0]을
찾아가고 그다음에 arms[0] 을 찾는다.
이 순서를 표시 하고 있는 것이 [88쪽]의 "결합성
"에서 제일 위 [] -> . 칸 의 화살표가 의미 하는것이다. 표에서 보다시
피, 주로 --> 방향이다. 이건 주로 "지금 우리가 이 글을 읽는 순서" 대
로 해석 하라는 뜻이다.
참고로 바로 아래 칸에는 그 유명한 " * & (형명) " 그룹이 있는데 이것
은 "결합성" 이 "<---"로 되있다. 이건 아래와 같이 표기하고 해석하라는
뜻이다.
1. madangbal의 주소 --> mazingaadangbal & (x, -->)
2. madangbal의 주소 --> & madangbal (0, <--)
-----------------------------------------------------------------------
4> 포인터로 선언 할때
-----------------------------------------------------------------------
스트락춰는 물론 아래와 같이 포인터 변수 asura 로 선언 할 수도
있다. 내가 이 변수명을 쓴 이유를 눈치 빠른 분들은 아실것이다.
여러분들이 기본 포인터를 다 이해 하셨는지 잘 모르겠는데, 포인
터란 놈은 스트락춰에서 더욱 표현이 복잡해진다. 그리하여 급기야는 여러
분들의 머리속을 아수라장으로 만들 소지가 다분히 있을것이다.
struct robot {
int head;
int body;
char arms;
long legs;
} *asura ; <-- 포인터 변수
그러나 언제나 그렇듯이 "기본 원리" 그것이 우리의 만병통치 주문이다.우
리 이제 양심적으로 다음의 문제를 풀수 있는지 점검해 보자
<문제> 위의 asura의 메모리 구조를 그려 보세요 !
위의 답이 떠오르지 않는 분들은 저에게 양심적으로 메일을 보내 주시기 바
란다. 정답은 [175쪽] 에 있다. 우리의 만병통치 주문이다. 틀리신 분들은
빨간 형광펜으로 밑줄 "쫙" 그어 주시고 주문을 좀 암기해 주시길 바란다.
송창식의 노래처럼 "언제나 그렇듯이" 포인터는 손가락 하나 들어
갈 크기만 있으면 되지, 위 처럼 커다란 스트락춰를 가리킨다고 해서 크기가
다를 이유가 없다.
메모리 구조는 이처럼 지극히 간단해서 나는 개인적으로 포인터를
아주 좋아한다.
특히 정신적 증세가 심각하여 "온 우주 만물"을 하나로 간단하게 통일해 보
고 싶어 하는 사람 일수록 이 포인터를 더욱 좋아 하는 법인데, 왜냐하면,
아시다시피 ,모든 변수 타입이 제각각 크기가 다른데 비해 포인터는 항상
"2 바이트" 로 일정하기 때문이다.
게다가 마치 변신 로보트 처럼 배열, 스트락춰 등 어떤 형태로든
지 슬쩍슬쩍 모습을 바꿔서 그 기능을 수행하니 가히 귀신 같은 놈이 아닌
가 ?
포인터를 이용하여 값을 넣고 빼고 하는 방법은 약간 다르다. 아래
를 보자.
1) 값을 대입 하고 읽는법
struct robot {
int head;
int arms[2];
int *finger;
} *asura <-- 포인터 변수
main()
{
a = &mazinga; <-- 반드시 초기화 후 사용 !
asura->head = 100; <-- (배열).(보통)
asura->arms[0] = 100; <-- (배열).(배열)
asura->finger = (int *)100; <-- (배열).(포인터)
printf("%x ",asura->head );
printf("%x ",asura->arms[0]);
printf("%x ",asura->finger );
}
자 여기서 새로운 연산자가 나왔다. [88쪽]의 "->" 가 그것이다.
이것은 우리가 다뤄야 할 마지막 연산자이다. 그리고 가장 어려운 표현에 속한다.
"->" 연산자를 사용하는 경우는 위와 같이
-------------------------------------------------------
*asura 처럼 포인터형의 "스트락춰 변수"로 선언되었을 때
-------------------------------------------------------
이다. 여기서 혼동하지 말것은 *finger의 포인터와는 아무 상관없다는 것이
다. 이것은 표현법이기 때문에 설명이 필요가 없다. 단지 암기가 필요할 뿐
이다. 즉
---------------------------------------------------
*asura 처럼 선언 되었을때 멤버에 값을 넣으려면
"->"를 쓴다
---------------------------------------------------
포인터라는 놈이 항상 말썽이었는데 기어코 마지막 까지 우리를 괴롭힌다.
하지만 도트"." 가 "->"로 바뀌었다는 것만 빼면 나머지는 별로 차이가 없
다.
2) 주소를 알아 보려면 다음과 같이 한다.
main()
{
printf("%x ",&asura->head );
printf("%x ",&asura->arms[0]);
printf("%x ",&asura->finger );
}
이것도 단순히 앞에 & 만 붙여주면된다.
3) 포인터가 가리키는 값을 찍는법
main()
{
printf("%x \n", *asura->finger );
}
이것도 단순히 앞에 * 만 붙여주면 된다.
-----------------------------------------------------------------------
5> 중첩된 구조체
-----------------------------------------------------------------------
스트락춰는 중첩(nesting)이 허용된다. 아는 사람 입장에서는 지극
히 당연한 것인데, 처음 보는 사람도 그렇게 생각 할지 모르겠다.
지난번 공식 중에
-------------------------------------------
char , int 따위가 들어갈 자리에 struct xxx
를 쓸수 있다
-------------------------------------------
고 했다. 따라서 아래를 보면
struct small {
int head;
int arms[2];
int *finger;
};
struct robot {
int head;
int arms[2];
int *finger;
struct small atom; <-- (요기)
} mazinga;
위의 (요기) 같은 표현이 가능하다. 이 구조체는 큰 로보트 mazinga 가 작
은 로보트 atom을 싣고 다니는 모습이다. 부속품으로서가 아니라 머리와 두
팔을 갖고 있는 완성된 로보트를 중첩해서 갖고 있다는 얘기다.
이런 광경은 많이 볼수 있다. 스타워즈 같은 영화에서도 큰 비행선
안에서 작은 전투기들이 벌떼 같이 쏟아져 나온다. 또 실제로 큰 수송기
안에서는 탱크같은 완전한 무기가 가끔 낙하선을 타고 나오기도 한다. 또
임신부들이 애기를 갖고 있는 모습도 유사하다. 이와같이 중첩된 구조체의
모습이란 지극히 자연스런 모습인 것이다.
1) 값을 대입 하고 읽는법
struct small {
int head;
int arms[2];
int *finger;
};
struct robot {
int head;
int arms[2];
int *finger;
struct small atom; <-- (요기)
} mazinga;
main()
{
mazinga.atom.head = 100; (경우 1)
mazinga.atom.arms[0] = 100; (경우 2)
mazinga.atom.finger = (int *)100; (경우 3)
printf("%x ",mazinga.atom.head );
printf("%x ",mazinga.atom.arms[0]);
printf("%x ",mazinga.atom.finger );
}
이런 표현은 새로운 표현법이라고 "경우의 수"에 추가 시키기가
어렵다. 왜냐하면, 중첩이란건 저 위에서 다룬 9가지 기본원리를 가지고 반
복해서 써먹는것이기 때문이다. 따라서 새로 학습할 것은 없으나, 정리 할
것은 위에서, head, arms[], finger 라는 변수를 참조하는데 그게 누구꺼냐
하는 문제다.
이것도 기껏 해야 mazinga것 아니면 atom것 둘중에 하나 일것이다.
하지만, 해석하는 순서(좌 --> 우)로 읽어 나가면 별 문제는 없을것이다.
이와 같이 다른 스트락춰 안에서는 똑같은 이름이 있어도 상관없
다. 이 원칙도 지극히 당연한 것이지만, 컴파일러가 "누구 head "인지 구별
할 수 있으면 되는것이다.
스트락춰를 쓰기 시작 하면서 "head 야" 이렇게 부르는건 바보 같은
짓이다. 반드시 "마징가의 head 야" 아니면, "아톰의 head 야" 이런식으로
"정확하게" 불러야 된다.
2) 주소를 알아 보려면 다음과 같이 한다.
main()
{
printf("%x ",&mazinga.atom.head );
printf("%x ",&mazinga.atom.arms[0]);
printf("%x ",&mazinga.atom.finger );
}
여기서는 &의 표현이, 너무 멀리 떨어져 있어서 불안할지도 모르겠
다. 하지만, 주문을 외우자
--------------------------------------
& 는 항상 스트락춰명 제일 앞에 붙인다
--------------------------------------
3) 포인터가 가리키는 값을 찍는법
main()
{
printf("%x \n", *mazinga.atom.finger );
}
<문제> 다음은 dos.h 라는 헤더 파일에 선언된 "중첩된 구조체"의 모습입니
다.
struct fcb {
char fcb_drive;
char fcb_name[8];
char fcb_ext[3];
short fcb_curblk;
short fcb_recsize;
long fcb_filsize;
short fcb_date;
char fcb_resv[10];
char fcb_currec;
long fcb_random;
};
struct xfcb {
char xfcb_flag;
char xfcb_resv[5];
char xfcb_attr;
struct fcb xfcb_fcb; /* <-- 중첩된 구조체 */
};
<문1> 다음의 크기는 얼마인가요 ?
sizeof(struct fcb)
<문2> 다음의 크기는 얼마인가요 ?
sizeof(struct xfcb)
<문3> 다음과 같이 선언이 되었을 때 이 구조체의 메모리 구조(아파트 형
태) 를 그려 보세요. (229쪽 참조)
struct fcb xxx;
main()
{
}
<문4> "struct xfcb" 의 메모리 구조(아파트 형태)를 그려 보세요.
struct xfcb yyy;
main()
{
}
***********************************************************************
<2> 프로그램 응용
***********************************************************************
<숙제> 아래의 프로그램을 실행하고 source를 읽어보세요
<숙제> 현재 미친듯이 다니는 공은 4 방향(동서남북)으로 움직이고 있습니
다. 이것을 8 방향(동서남북, 북동,남동,북서, 남서)으로 돌아 다
니 도록 고쳐 보세요.
<숙제} "메뉴선택"에서 좌우측 끝까지 가면 더 못간다. 이것을 돌도록(왼쪽
끝에서 오른쪽끝, 또는 그반대로)바꿔 보세요.
<숙제> 돌아다니는 공의 궤적(돌아다닌 흔적)을 보이도록 바꿔보세요.
<숙제> 공의 속도를 느리게(혹은 빠르게) 조정해 보세요.
-------------------------< 프로그램 시작 >-----------------------------
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <dos.h>
#define SPACE 0x20
#define ESC 0x1b
#define BELL 0x07
#define START_X (R_END - L_END)/2
#define START_Y (D_END - U_END)/2
#define BALL_START_X L_END
#define BALL_START_Y U_END
#define MARK #
#define F10 0x44
#define ENTER 0x0d
#define T_REVERSE 0x70
#define T_NORMAL 0x07
enum { L_BOX = 1, R_BOX = 80, U_BOX = 2, D_BOX = 24 };
enum { L_END = L_BOX + 1,R_END = R_BOX - 1,U_END = U_BOX + 1,D_END
=
D_BOX - 1 };
enum { LEFT = 0X4B, RIGHT = 0X4D, UP = 0X48, DOWN = 0X50 };
int keyin,x,y,new_x,new_y;
char mark[80];
int m_length;
int wait_color = 0;
int menu_x[] = { 1, 16, 31,46,61 };
int i, current_x,before_x;
char *menu_string[] = { "사각의결투",
"음악연주",
"친구주소록",
"작업종료"
};
/*===================< CODE BEGIN >======================*/
main()
{
main_top:;
textattr(T_NORMAL);
clrscr();
draw_main_menu();
current_x = 0;
before_x = 0;
while(1) {
/*----------------------------*/
gotoxy(menu_x[current_x],1);
textattr(T_REVERSE);
cprintf(menu_string[current_x]);
textattr(T_NORMAL);
gotoxy(menu_x[current_x],1);
/*----------------------------*/
if((keyin = getch()) == 0) {
keyin = getch();
switch(keyin) {
case LEFT : if( current_x > 0)
current_x--;
break;
case RIGHT : if( current_x < sizeof(menu_x)/sizeof(int)
-1)
current_x++;
break;
default : putch(BELL);
}
/*-----< string reverse process >-----*/
textattr(T_NORMAL);
cprintf(menu_string[before_x]);
before_x = current_x;
/*------------------------------------*/
} else if(keyin == ENTER) {
switch(current_x) {
case 0: fighting_in_box(); goto main_top;
case 4: textattr(T_NORMAL); return;
default : putch(BELL);
}
}
} /* while */
}
/*====================================================*/
fighting_in_box()
{
int i,j,ball_x, ball_y, ball_old_x, ball_old_y;
long start_time,current_time;
time_t t;
top :;
textattr(T_NORMAL);
clrscr();
draw_box();
gotoxy(1,1);
printf("스트링을 치세요 : ");
gets(mark);
m_length = strlen(mark);
/*-----------< time display >-----------*/
gotoxy(50,1);
printf("Elapsed time : sec");
start_time = time(NULL);
x = new_x = START_X;
y = new_y = START_Y;
ball_x = ball_old_x = BALL_START_X;
ball_y = ball_old_y = BALL_START_Y;
gotoxy(START_X,START_Y);
puts(mark);
gotoxy(START_X,START_Y);
while(1) {
while(!bioskey(1)) {
/*-----<ball zigzag >-----*/
i = random(4);
switch(i) {
case 0 : if(ball_y > U_END)
ball_y--;
break;
case 1 : if(ball_x < R_END)
ball_x++;
break;
case 2 : if(ball_y < D_END)
ball_y++;
break;
case 3 : if(ball_x > L_END)
ball_x--;
break;
}
/*---------<time display >-----------*/
if(start_time != (current_time =
(long)time(NULL))) {
gotoxy(70,1);
cprintf("%d", current_time -
start_time);
}
/*---------< touch ? >-----------*/
if(ball_y == y && (ball_x >= x && ball_x < x
+ m_length))
{
putch(0x07);
getch();
return;
}
gotoxy(ball_x,ball_y);
textattr(wait_color++);
putch('#');
gotoxy(ball_old_x,ball_old_y);
textattr(T_NORMAL);
putch(' ');
ball_old_x = ball_x;
ball_old_y = ball_y;
}
textattr(0x0f);
/*========<if key strike >====*/
if((keyin = getch()) == 0) {
keyin = getch();
switch(keyin) {
case LEFT : if( x > L_END ) new_x--;
else new_x = R_END - m_length;
break;
case RIGHT : if( x < R_END - m_length) new_x++;
else new_x = L_END;
break;
case UP : if( y > U_END ) new_y--;
else new_y = D_END;
break;
case DOWN : if( y < D_END ) new_y++;
else new_y = U_END;
break;
default : putch(BELL);
}
gotoxy(x,y);
for(i=0; i <= m_length; i++)
putch(' ');
gotoxy(new_x, new_y);
puts(mark);
gotoxy(new_x, new_y);
x = new_x;
y = new_y;
} else {
switch(keyin) {
case ESC : clrscr(); return;
default : putch(BELL);
}
} /* else */
} /* while */
} /* main */
/*==================< sub routine >================*/
draw_box()
{
int i;
gotoxy(L_BOX,U_BOX);
for(i= L_BOX; i <= R_BOX; i++)
putch('-');
gotoxy(L_BOX,D_BOX);
for(i= L_BOX; i < R_BOX; i++) /* why "<" rather than
"<=" ? */
putch('-');
for(i= U_BOX + 1; i < D_BOX; i++) {
gotoxy(L_BOX,i);
putch('|');
gotoxy(R_BOX,i);
putch('|');
}
}
draw_main_menu()
{
for(i=0; i < sizeof(menu_x)/sizeof(int); i++) {
gotoxy(menu_x[i],1);
puts(menu_string[i]);
}
for(i=1; i <= 80; i++)
putch('=');
}