2011년5월17일...Eltima Software Virtual Serial Port Driver, C과제2풀이, C과제3

 

image

이 때까지 DK128보드로 실습할 때 ATmega128부트섹터에 있는 부트로더를 이용하여 PC와 시리얼통신을 하였다.
COM1포트를 통해 코드를 전송하여 DK128의 ATmega128에 프로그래밍하였던 것이다.
이 때 사용한 COM1포트는 실제 존재하는 통신포트이다.

 

가상 시리얼 포트

 

image

보통 PC에는 COM포트가 하나이거나 최근에 나오는 모델은 보통 없다.
그래서 PC 한 대로 통신실습을 할 수 없으니 가상포트를 사용하는 것이다.

 

image

Eltima Software Virtual Serial Port Driver 6.0.1.115를 이용해 가상포트를 만들고,
가상포트끼리 짝을 지어 통신을 하여 보자.

 

image  <- 설치파일을 클릭하여 실행

 

image

몰라 Next…

 

image

동의하고 Next…

 

image

설치경로 지정하고 Next…

 

image

폴더 만들겠냐? 예!

 

image

시작메뉴…Next

 

image

바탕화면 단축아이콘만 체크…빠른 실행 필요하면 하고…Next

 

image

설치시작!

 

image

너무 빠르다;

 

image

프로그램 실행체크해제하고 Finish

 

image

구멍난 과자를 복사하고…

 

image <-바탕화면의 아이콘을 클릭하여 실행

 

image

Second port를 COM5로 바꾼뒤에 Add pair 버튼을 클릭

 

image

좌측 시리얼포트탐색기를 보니 물리적포트로 COM1이 있고,
가상포트로 이번에 추가한 COM2와 COM5가 서로 연결되어 있다.

image

장치관리자에서도 추가된 포트들의 확인이 가능하다.

 

image

시작메뉴 – 모든 프로그램 – 보조프로그램 – 통신 – 하이퍼터미널을 클릭

 

image

아무 이름이나 적고 확인

image

COM2선택

 

image

9600bps, 8bit데이터, 패리티없음, 1bit정지비트, 흐름제어없음을 선택한 뒤 확인

 

image

수화기를 올린 전화기 모양의 아이콘을 클릭하여 연결을 끊는다.

 

image

맨우측 사람손모양의 속성아이콘을 클릭하여 속성창을 열어 설정탭을 클릭함.

 

image

ASCII설정버튼을 클릭

 

image

줄 끝에 LF붙여 보냄과 입력된 문자를 터미널창에 표시를 체크한 다음 확인

하이퍼터미널을 하나 더 실행하여 COM5도 만든다.

image

터미널창에서 알파벳을 입력하여 COM2 –> COM5로 문자가 잘 전송되는 것을 확인

 

image

터미널창에서 한글을 입력하여 COM5 –> COM2로 문자가 잘 전송되는 것을 확인

 

image <- COM2를 열어 놓은 하이퍼터미널을 닫거나 연결을 끊고 선생님의 main.exe를 실행

 

image

main.exe에서 COM2를 열어 “Hello world”라는 문자열과 개행문자를 보내고,
하이퍼터미널은 COM5를 열어 COM2에서 보내온 문자들을 수신하여 터미널창에 표시하고 있다.
컴퓨터 한 대로 통신실습을 할 수 있다니…
가상시리얼포트드라이버는 좋은 프로그램이다.

 

C과제2 풀이

1번...모두 나의 답과 같아 생략.
2번...printf( )함수에 바로 인자로 (~Num) + 1,
      나는 Num = ~Num;  Num = Num + 1; 한 다음에 Num을 인자로 넘겨줌.
3번...분은 time / 60, 초는 time % 60
      나는 iMin = iSec / 60, 초는 iSec = iSec – iMin * 60;
4번...( i / 8 ) * 10 + ( i % 8)
      나는 위의 식과 비슷하게 했으나 대신 반복문으로 큰 수도 처리가능하게 하였음. 복잡함. @_@
5번...N / 100 = 100의 자리 수
      (N % 100) / 10 = 10의 자리 수
      N % 10 = 1의 자리 수 
      간단하네!
      나는 복잡해!

 

 

C과제3

 

1. 다음 질문들에 맞는 if문의 조건식을 구성하세요.
1) N이 0보다 크거나 같다.
답: if(0 <= N)

2) N이 -5보다 작거나 5보다 크다.
답: if(-5 > N || 5 < N)

3) N이 0보다 크거나 같고 10보다 작거나 같다.
답: if(0 <= N && 10 >= N)

4) ch는 대문자이다.
답: if(65 <= ch && 90 >= ch)

5) ch는 소문자이다.
답: if(97 <= ch && 122 >= ch)

6) N이 K와 같거나 M보다 크다.
답: if(K == N || M < N)

 

 

2. 키보드로부터 한 문자를 입력 받아서 입력 문자에 해당하는 아스키 코드값을 출력하세요.
출력) 문자 입력 : A
값 : 65

   1:  /****************************************************
   2:      2. 키보드로부터 한 문자를 입력 받아?
   3:       입력 문자에 해당하는 아스키 코드값을 출력하세요.
   4:  
   5:      소속: 내장형하드웨어
   6:      작성자: 김수만
   7:      작성일자: 2011년 5월 17일
   8:      
   9:  ****************************************************/
  10:  #include <stdio.h>
  11:   
  12:  int main()
  13:  {
  14:      char ch;
  15:      
  16:      printf("문자 입력: ");
  17:      scanf("%c", &ch);
  18:   
  19:      printf("%d", ch);
  20:          
  21:      return 0;
  22:  }

 

clip_image002

 

 

3. 키보드로부터 소문자를 입력 받으면 대문자로, 대문자를 입력 받으면 소문자로 변환하세요.

출력) 알파벳 입력 : a
대문자로 변환 : A
알파벳 입력 : 1
알파벳을 입력하세요.
알파벳 입력 : B
소문자로 변환 : b
알파벳 입력 : (엔터)
프로그램 종료!

   1:  /****************************************************
   2:      3. 키보드로부터 소문자를 입력 받으면 대문자로,
   3:          대문자를 입력 받으면 소문자로 변환하세요.
   4:          
   5:      소속: 내장형하드웨어
   6:      작성자: 김수만
   7:      작성일자: 2011년 5월 17일
   8:      
   9:  ****************************************************/
  10:  #include <stdio.h>
  11:   
  12:  int main()
  13:  {
  14:      char ch;
  15:      
  16:      while(1)
  17:      {
  18:          printf("알파벳 입력: ");
  19:          scanf("%c", &ch);
  20:   
  21:          if(65 <= ch && 90 >= ch)        //대문자이면
  22:          {
  23:              ch = ch + 32;                //소문자로 변환
  24:              printf("소문자로 변환 : %c\n", ch);
  25:          }
  26:          else if(97 <= ch && 122 >= ch)    //소문자이면
  27:          {
  28:              ch = ch - 32;                //대문자로 변환
  29:              printf("대문자로 변환 : %c\n", ch);
  30:          }
  31:          else if(10 == ch)                //엔터키이면
  32:          {
  33:              break;                        //탈출
  34:          }
  35:          else                            //그 외
  36:          {
  37:              printf("알파벳을 입력하세요.\n");
  38:          }
  39:          
  40:          fflush(stdin);
  41:      }
  42:          
  43:      printf("프로그램 종료!\n");
  44:          
  45:      return 0;
  46:  }

 

clip_image002[7]  image

 

 

 

  ASCII표를 보면 대문자 A는 소문자a보다 32가 작다.

이는 A~Z까지 동일하게 적용이 가능하다.

대문자를 소문자로 바꾸려면 대문자에 +32를 하면 되고,
소문자를 대문자로 바꾸려면 소문자에 –32를 하면 된다.

 

 

 

 

 

4. 정수의 자릿수를 구하세요.

출력) 정수 입력 : 325
자 릿 수 : 3
정수 입력 : –1
종료하시겠습니까?(Y/N) : n
정수 입력 : 4589
자 릿 수 : 4
정수 입력 : –1
종료하시겠습니까?(Y/N) : y
프로그램 종료!

 

<해법찾기>
32bit 부호있는 정수형인 int형 변수로 입력받는다고 하고,
그 변수의 최대값은 2^32 – 1이 될 것이다. 그러니 10억단위까지만 처리하면 되겠다.
최상위 10억자리 부터 나누어 나온 수가 0이 아니면 그 자리가 자릿수이므로 그 때 나눈 수의 자릿수를 출력하면 되겠다.

<해법표현>
iNum / 10억 → 0이 아닌가? → 자릿수는 10
0이었나?
iNum / 1억 → 0이 아닌가? → 자릿수는 9
0이었나?
iNum / 1000만 → 0이 아닌가? → 자릿수는 8
0이었나?
iNum / 100만 → 0이 아닌가? → 자릿수는 7
0이었나?
iNum / 10만 → 0이 아닌가? → 자릿수는 6
0이었나?
iNum / 1만 → 0이 아닌가? → 자릿수는 5
0이었나?
iNum / 1000 → 0이 아닌가? → 자릿수는 4
0이었나?
iNum / 100 → 0이 아닌가? → 자릿수는 3
0이었나?
iNum / 10 → 0이 아닌가? → 자릿수는 2
0이었나? → 자릿수는 1

이런 의사코드대로 한다면 코드가 너무 노가다식이니 반복문을 이용함.

image


  iCount에 10이 아닌 9를 넣은 이유는,
  exp(N)라는 10 ^ N을 구하는 함수에 넣기 위해,
  10을 넣으면 100억이 되어 버림

  iCount가 0이 될 때까지 반복을 하고,
  iNum을 10 ^ iCount으로 나누어,
  0아니면 반복을 끝내고 아니면 계속 반복.(나눔)

  iCount의 값을 1감소시켜 한 단위 낮게 함.


  마지막에 iCount의 값을 1증가시키는 이유는 exp( ) 함수땜시

 

 

 

   1:  /****************************************************
   2:      4. 정수의 자릿수를 구하세요.
   3:          
   4:      소속: 내장형하드웨어
   5:      작성자: 김수만
   6:      작성일자: 2011년 5월 17일
   7:      
   8:  ****************************************************/
   9:  #include <stdio.h>
  10:   
  11:   
  12:  int exp(int iNum);
  13:   
  14:   
  15:  int main()
  16:  {
  17:      int iNum;
  18:      int iCount;
  19:      char cNum;
  20:      
  21:      while(1)
  22:      {
  23:          printf("\n정수 입력: ");
  24:          scanf("%d", &iNum);
  25:          fflush(stdin);
  26:          
  27:          if(-1 == iNum)
  28:          {
  29:              printf("종료하시겠습니까?(Y/N) : ");
  30:              scanf("%c", &cNum);
  31:              
  32:              if('y' == cNum || 'Y' == cNum)
  33:              {
  34:                  break;
  35:              }
  36:              else if('n' == cNum || 'N' == cNum)
  37:              {
  38:                  //아무 것도 하지 않음.
  39:              }
  40:          }
  41:          else
  42:          {
  43:              for(iCount = 9 ; 0 < iCount ; --iCount)
  44:              {
  45:                  //그 자리를 나누어 0이 아니면 중단
  46:                  if(0 != (iNum / exp(iCount)))        
  47:                  {
  48:                      //iNum = iCount + 1;
  49:                      //iCount = 1;
  50:                      break;
  51:                  }
  52:              }
  53:              
  54:              iNum = iCount + 1;
  55:              printf("자 릿 수 : %d\n", iNum);
  56:          }
  57:      }
  58:          
  59:      printf("프로그램 종료!\n");
  60:          
  61:      return 0;
  62:  }
  63:   
  64:   
  65:  /************************************************************
  66:          10^N을 구하는 프로그램. 계산기의 Exp와 같음.
  67:  ************************************************************/
  68:  int exp(int iNum)
  69:  {
  70:      int result = 1;        //0을 받았을 때의 반환값
  71:                          //10^0은 1이다.
  72:      while(iNum--)        //0이 될 때까지 반복
  73:      {
  74:          result = result * 10;        //10을 계속 곱해줌.
  75:      }
  76:      
  77:      return result;
  78:  }

 

clip_image002[11]

 

 

 

 

 

10억단위를 넘어서는 정수값을 입력하면,
10으로 고정되어 출력이 되는데 이유는 당연히
32bit 부호있는 정수형 타입 int의 경우 10억단위가 한계이고,
10억 단위를 넘어서는 100억단위이상이 들어와도,
대입시에 짤려서 10억단위의 정수값만 들어가므로,
10억 단위의 숫자이상을 입력시엔 자릿수가 10으로 고정되어,
출력이 되는 것이다.
이를 해결하려면 더 큰 자료형을 선언해야 한다.

 

 

 

 

[도전] 피보나치 수열이란 1, 1, 2, 3, 5, 8, … 과 같이 앞의 연속된 2개 항을 합한 수열이다.
피보나치 수열의 일반식 : an+2 = an + an+1

입력 받은 항 개수만큼의 피보나치 수열의 합을 구하여라.
(항 개수를 9로 입력받으면 합 Sum = 1+1+2+3+5+8+13+21+34)
출력)
**** 피보나치 수열의 합 ****
항의 개수 입력 : 5
피보나치 수열 5개 항의 합은 12
항의 개수 입력 : –1

종료하시겠습니까?(Y/N) : y
프로그램 종료!

<해법찾기>

image

우리의 막강한 계산프로그램인 엑셀로 피보나치수열의 값과 합을 입력하여 차트를 그린 다음에,
추세선을 그리고 그 식을 얻었으나…
식이 너무 복잡하다…그리고 6차까지 갔다…이런 복잡한 식은 별로 좋아하지 않는다.
그래서 생각했다.
일단 수열을 구하여 배열에 넣은 다음 그 배열의 합을 구하면 쉽게 해결될 것이라는 것.
그러나 이 방법은 피보나치수열의 합만 구하면 되는 프로그램에서 너무 많은 메모리를 차지하고 나는 그것이 불필요하다고 생각한다.
(합만 구하면 되는데 수열까지 구해서 합을 구한다는 것이 왠지 내키지 않는다.)

 

<해법표현>
1.입력받은 항의 수만큼 피보나치 수열을 생성.
  iPorg[100] = {1, 1}; 
  iProg[2] = iPorg[1] + iProg[0];
  iProg[3] = iPorg[2] + iProg[1];
  만약 입력된 항의 수와 현재 생성되는 항의 수가 같을 경우 생성을 중단함.
2.입력된 항의 수까지 iProg[]의 합을 구함.

   1:  /****************************************************
   2:      [도전] 피보나치 수열이란 1, 1, 2, 3, 5, 8, … 
   3:      과 같이 앞의 연속된 2개 항을 합한 수열이다. 
   4:      피보나치 수열의 일반식 : an+2 = an + an+1
   5:          
   6:      소속: 내장형하드웨어
   7:      작성자: 김수만
   8:      작성일자: 2011년 5월 17일
   9:      
  10:  ****************************************************/
  11:  #include <stdio.h>
  12:   
  13:  int main()
  14:  {
  15:      int iNum;
  16:      int iSum;
  17:      int iLoop;
  18:      int iProg[100] = {1,1};
  19:      char cNum;
  20:   
  21:   
  22:      while(1)
  23:      {
  24:          printf("항의 갯수 입력: ");
  25:          scanf("%d", &iNum);
  26:          fflush(stdin);            //버퍼비움
  27:          
  28:          if(-1 == iNum)
  29:          {
  30:              printf("종료하시겠습니까?(Y/N) : ");
  31:              scanf("%c", &cNum);
  32:              
  33:              if('y' == cNum || 'Y' == cNum)
  34:              {
  35:                  break;
  36:              }
  37:              else if('n' == cNum || 'N' == cNum)
  38:              {
  39:                  //아무 것도 하지 않음.
  40:              }
  41:          }
  42:          else
  43:          {
  44:              //피보나치수열을 입력한 항의 범위만큼 생성합니다.
  45:              for(iLoop = 2 ; iLoop < iNum ; ++iLoop)
  46:              {
  47:                  iProg[iLoop] = iProg[iLoop - 1] + iProg[iLoop - 2];
  48:              }
  49:              
  50:              //생성된 수열의 합을 구합니다.        
  51:              for(iLoop = 0 ; iLoop < iNum ; ++iLoop)
  52:              {
  53:                  iSum = iSum + iProg[iLoop];
  54:              }
  55:          
  56:              printf("피보나치 수열 %d개항의 합은 %d\n", iNum, iSum);
  57:          }
  58:          
  59:          iSum = 0;    //iSum을 초기화 합니다.
  60:      }
  61:      
  62:      printf("프로그램 종료!\n");
  63:          
  64:      return 0;
  65:  }
clip_image002[15]