독도 광고 모금 캠페인

사실 C언어에 대해 심도 깊은 포스팅을 하고 싶었으나...
취미로 이런걸 짜기는 조금 그렇고 과제로 했던것들이나 예전에 짰던 것에 대해 잊지 말자는 의미로 포스팅 하겠다~
개발환경은 MS VC++ 6.0이다.

문제:)
인터프리터를 작성하여라
.
메모리: M[1000]
레지스터: R[10]
입력기: input() = 입력프로그램을 읽어서 메모리에 저장
해석기: interpret() = 명령어 FETCH, DECODE, EXECUTE
결과출력: 실행된 명령어 횟수

인터프리터 내용:)

* STOP
100 : halt
* REGISTER and CONSTANT
2dn : set
register d to n
3dn : add n tp register d
4dn : multiply register d by n
* REGISTER and REGISTER
5ds : set register d to the value of register s
6ds : add the value of register s to register d
7ds : multiply register d by the value if register s
* LOAD
8da : set register d to the value in RAM whose address is in register a
* STORE
9sa : set the value in RAM whose address is in register a to that of register s
* GOTO
0ds : goto the location in register d unless register s contains 0



설계내용:)

A.     main()

                         i.         메모리와 레지스터를 선언하고 함수에서 참조하도록 한다.

                        ii.         Counter 변수를 두고 입력 받은 숫자만큼 시뮬레이션을 하도록 한다.

                       iii.         입력을 위한 input함수와 해석을 위한 interpret함수를 각 시뮬레이션 별로 실행한다.

                      iv.         실행횟수를 출력한다.

B.     void input(int M[], int a)

                         i.         input함수로 메모리 안에 명령어를 입력 받는다.

                        ii.         Int a 는 메모리의 크기로, 패러미터에서 1000의 값을 주었다.

                       iii.         EOF가 나타나면 입력을 중지하도록 하였다.

C.     int interpret(int M[], int a, int R[], int b)

                         i.         패러미터로 메모리(M[])와 메모리 크기(a), 레지스터(R[])와 레지스터의 크기를 받는다.

                        ii.         fr변수는 메모리에서 첫 번째 숫자인 명령어 부분을 의미한다.

                       iii.         se변수는 메모리에서 두 번째 숫자를 의미한다.

                      iv.         th변수는 메모리에서 세 번째 숫자를 의미한다.

                       v.         pc변수는 다음 번에 가리킬 메모리 주소를 의미한다.

                      vi.         count변수는 명령어가 실행된 횟수를 각각 센다.

                     vii.         나누기와 나머지 기호를 적절히 사용하여 fr, se, th 를 각각 한 자리씩 배정하도록 한다.

                    viii.         Switch 문을 이용해 실질적인 명령어인 fr 변수를 구분으로 하여 fr 0이면서부터 9일 때까지의 각각의 명령을 입력해 주었다.

                      ix.         메모리는 무조건 세 자리만 유효하기 때문에 메모리의 값이 변동이 있을 때 (곱하거나 더하기 작업을 할 때) 1000으로 나눈 나머지만 값으로 취한다.

                       x.         fr 0일 때를 제외하고는 모두 pc값이 다음 주소를 가리키기 때문에 pc값을 한번의 for문이 끝날 때 마다 pc값을 증가시키고 fr 0일 때는 th번째 레지스터 값이 0이 아니면 se번째 레지스터가 가진 주소 값을 pc값으로 배정한다.



소스코드:)

#include <stdio.h>

 

void input(int[], int);

int interpret(int[], int, int[], int);

 

main(){

             int M[1000], R[10];

             int i, counter;

 

             printf("몇번의 횟수를 시뮬레이션 하겠습니까?: ");

             scanf("%d", &counter);

            

             for(i = 0; i < counter; i++){

                           printf("\n세자리의 양의 정수를 입력하십시오.\n입력이 끝났을 땐, Ctrl + z 를 눌러 주십시오.\n");

                           input(M, 1000);

                           printf("실행횟수: %d\n", interpret(M, 1000, R, 10));

             }

}

 

void input(int M[], int a){

             int i, flag = 1;

             for(i = 0; i < a; i++){

                           if(flag){

                                        if(scanf("%d", &M[i]) == EOF) flag = 0;

                                        M[i] %= 1000; //만약 세자리가 넘어가면 나머지 세자리만 취한다.

                           }

                           else

                                        M[i] = 0; // 모든 메모리에 000을 초기값으로 주기 위해

             }

}

 

int interpret(int M[], int a, int R[], int b){

             int fr, se, th, count, pc;

 

             for(count = pc = 0; M[pc] != 100; count++){ // 100은 정지를 나타내므로

                           fr = M[pc];

                           th = fr % 10; //맨 마지막 자리를 취한다.

                           fr /= 10; //맨 마지막 자리를 버린다.

                           se = fr % 10; // 그 다음 자리를 취한다.

                           fr /= 10; // 두 번째 자리를 버려 첫 번째 자리를 가지게 한다.

                           switch(fr){

                           case 2:

                                        R[se] = th;

                                        break;

                           case 3:

                                        R[se] += th;

                                        R[se] %= 1000; //1000으로 나눈 값의 나머지만 취해 3자리를 만든다.

                                        break;

                           case 4:

                                        R[se] *= th;

                                        R[se] %= 1000; // 나머지 세 자리만 취한다.

                                        break;

                           case 5:

                                        R[se] = R[th];

                                        break;

                           case 6:

                                        R[se] += R[th];

                                        R[se] %= 1000; // 나머지 세 자리만 취한다.

                                        break;

                           case 7:

                                        R[se] *= R[th];

                                        R[se] %= 1000; // 나머지 세 자리만 취한다.

                                        break;

                           case 8:

                                        R[se] = M[R[th]];

                                        break;

                           case 9:

                                        M[R[th]] = R[se];

                                        break;

                           case 0:

                                        if(R[th]) pc = R[se]-1; //맨 마지막에서 pc값을 증가 시킬 예정이므로 1을 빼준다.

                                        break;

                           case 1: // 명령어가 1으로 시작하나, 100이 아닐 경우 정지를 해주게 하기 위해.

                                        M[pc] = 100;

                                        pc--; // pc가 아까 다시 100으로 바뀐 주소를 가리키게 하기 위해서 1을 빼준다.

                                        count--; // count가 이미 세어 졌으므로 빼준다.

                                        break;

                           }

                           pc++;

             }

 

             return count+1; //count 0부터 세어 졌기 때문에.

}
실행화면:)

299
492
495
399
492
495
399
283
279
689
078
100
000
000
^z
실행횟수: 16