728x90
/*
  중첩된 구조체의 정의
 Point 구조체(x, y pos), Circle 구조체(Point cen, double rad)
 center, radius를 보여주는 함수를 정의하고 메인함수에서 출력
 */
#include <stdio.h>
typedef struct
{
 int xpos;
 int ypos;
}Point;
typedef struct
{
 Point cen;
 double rad;
}Circle;
Circle GetCircleInfo(void)

 Circle cir;
 printf("원의 중심 입력: ");
 scanf("%d %d", &cir.cen.xpos, &cir.cen.ypos);
 printf("반지름 입력: ");
 scanf("%f", &cir.rad);
 return cir;
}
void ShowPosition(Circle pos)
{
 printf("[%d %d] \n %g", pos.cen.xpos, pos.cen.ypos, pos.rad);
}
int main()
{
 Circle Cir = GetCircleInfo();
 ShowPosition(Cir);
  
 return 0;
}/* 문자열 형태의 '종업원 이름'과 '주민번호', 정수형태의 '급여정보'를 저장할
employee 구조체 정의하고 변수 하나 선언

프로그램 사용자에게 입력받고 구조체의 데이터 출력
*/

#include <stdio.h>

struct employee
{
 char name[20];
 char num[20];
 int pay;
};

int main()
{
 struct employee arr[3];
 int i;

 for (i = 0; i<3; i++)
 {
  printf("종업원%d 이름 : ", i+1);
  scanf("%s", &arr[i].name);
  printf("종업원%d 주민번호 : ", i+1);
  scanf("%s", &arr[i].num);
  printf("종업원%d 월급 : ", i+1);
  scanf("%d", &arr[i].pay);
 }

 for (i = 0; i<3; i++)
  printf("[이름 : %s 주민번호 : %s 월급 : %d] ", arr[i].name, arr[i].num, arr[i].pay);

 return 0;
}



/*
 point(x-y pos) 구조체와 circle 구조체를 정의하고
 circle구조체(radius, center)의 center멤버는 포인터 변수를 활용해 point 구조체 멤버를 가리키도록 하라.

 그리고 두 구조체의 내용(반지름과 원의 중심)을 출력
*/

#include <stdio.h>

struct point
{
 int xpos;
 int ypos;
};

struct circle
{
 double radius;
 struct point * center;
};

int main()
{
 struct point centerXY = { 1,3 };
 double rad = 4.4;
 
 struct circle ring = { rad, &centerXY };
 printf("원 반지름 : %g \n", ring.radius);
 printf("원의 중심 : %d %d \n", ring.center->xpos, ring.center->ypos);
 
 return 0;
}




/*
 함수로의 구조체 변수 전달과 반환
*/

#include <stdio.h>

typedef struct
{
 int xpos;
 int ypos;
}Point;

void ShowPosition(Point pos)
{
 printf("[%d %d] \n", pos.xpos, pos.ypos); 
}

Point GetCurrentPosition(void)
{
 Point cen;
 printf("현재 x-y좌표 입력: ");
 scanf("%d %d", &cen.xpos, &cen.ypos);
 
 return cen;
 // 구조체를 생성하여 멤버를 초기화하고 그 구조체를 반환(Point형 cen)
}

int main()

 Point curpos = GetCurrentPosition(); // GetCur-()함수의 반환값을 curpos로 복사
 ShowPosition(curpos);
 /* 29-30 == ShowPosition(GetCurrentPosition());   
 구조체 변수 curpos가 ShowPosition 함수의 인자가 됨. */
 return 0;
}




/*
 구조체 멤버로 선언된 배열의 복사
*/

#include <stdio.h>

typedef struct
{
 char name[20];
 char phoneNum[20];
 int age;
}Person;

void ShowPersonInfo(Person man)
{
 printf("name: %s \n", man.name);
 printf("phone: %s \n", man.phoneNum);
 printf("age: %d \n", man.age);
}

Person ReadPersonInfo()
{
 Person man;
 printf("name? ");
 scanf("%s", man.name);
 
 printf("phone number? ");
 scanf("%s", man.phoneNum);

 printf("age? ");
 scanf("%d", &man.age);

 return man;
}

int main()

 Person Man = ReadPersonInfo(); 
 // ReadPer-함수를 호출하면 구조체 변수 man에 값이 담긴다. 반환된 man은 메인함수의 구조체 변수 Man에 복사된다.
 ShowPersonInfo(Man);

 return 0;
}



/*
 구조체 변수를 대상으로 하는 Call-by-ref.
*/

#include <stdio.h>

typedef struct
{
 int xpos;
 int ypos;
}Point;

void OrgSymTrans(Point *ptr) // 원점대칭이동
{
 ptr->xpos = (ptr->xpos)*-1;
 ptr->ypos = (ptr->ypos)*-1;
}

void ShowPosition(Point pos)
{
 printf("[%d, %d] \n", pos.xpos, pos.ypos);
}

int main()

 Point pos = { 7,-5 };
 printf("원래 값 "); ShowPosition(pos);

 OrgSymTrans(&pos);
 printf("원점 대칭이동 "); ShowPosition(pos);

 OrgSymTrans(&pos);
 printf("원점 대칭이동 "); ShowPosition(pos);

 return 0;
}



/*
 구조체 변수간 대입연산 (멤버 대 멤버 복사)
*/

#include <stdio.h>

typedef struct
{
 int xpos;
 int ypos;
}Point;

void ShowPosition(Point pos)
{
 printf("[%d, %d] \n", pos.xpos, pos.ypos);
}

int main()

 Point pos1 = { 7,-5 };
 Point pos2;
 pos2 = pos1; // pos1에서 pos2로 대입연산(멤버 대 멤버 복사)

 printf("pos1 size: %d \n", sizeof(pos1));
 ShowPosition(pos1);

 printf("pos2 size: %d \n", sizeof(pos2));
 ShowPosition(pos2);

 return 0;
}




/*
 구조체 변수를 대상으로 하는 +,- 연산
 */
#include <stdio.h>

typedef struct
{
 int xpos;
 int ypos;
}Point;

Point AddPoint(Point pos1, Point pos2)
{
 Point pos_Sum = { pos1.xpos + pos2.xpos, pos1.ypos + pos2.ypos };
 return pos_Sum;
}
Point MinPoint(Point pos1, Point pos2)
{
 Point pos_Min = { pos1.xpos - pos2.xpos, pos1.ypos - pos2.ypos };
 return pos_Min;
}

void ShowPosition(Point pos)
{
 printf("[%d %d] \n", pos.xpos, pos.ypos);
}

int main()
{
 Point pos1 = { 7,-5 };
 Point pos2 = { 2,9 };
 Point result;

 result = AddPoint(pos1, pos2);
 ShowPosition(result);
 
 result = MinPoint(pos1, pos2);
 ShowPosition(result); 
 return 0;
}




/*
  구조체 두 변수를 대상으로 저장된 값을 바꿔주는 함수를 정의하고 이를 호출하는 예제 작성
 */
#include <stdio.h>

typedef struct
{
 int xpos;
 int ypos;
}Point;


void SwapPoint(Point *ptr1, Point *ptr2)
{
 Point temp = *ptr1;
 *ptr1 = *ptr2;
 *ptr2 = temp;
}


int main()
{
 Point pos1 = { 2, 4 };
 Point pos2 = { 5, 7 };
 printf("pos1 : [%d %d] ", pos1.xpos, pos1.ypos);
 printf("pos2 : [%d %d] \n", pos2.xpos, pos2.ypos);

 SwapPoint(&pos1, &pos2);
 printf("pos1 : [%d %d] ", pos1.xpos, pos1.ypos);
 printf("pos2 : [%d %d] \n", pos2.xpos, pos2.ypos); 
 
 return 0;
}



/*
       구조체를 통해 연관있는 데이터를 하나로 묶을 수 있는 자료형을 정의,

 데이터 표현 및 관리가 용이해진다.

*/

#include <stdio.h>

typedef struct
{
 char name[20];
 char num[20];
 char major[20];

}Student;

void ShowStudent(Student *ptr)
{
 printf("이름 : %s \n", ptr->name);
 printf("학번 : %s \n", ptr->num);
 printf("전공 : %s \n", ptr->major);
}

int main()
{
 Student arr[3];
 int i;

 for (i = 0; i < 3; i++)
 {
  printf("이름 : "); scanf("%s", arr[i].name);
  printf("학번 : "); scanf("%s", arr[i].num);
  printf("전공 : "); scanf("%s", arr[i].major);
 }
 puts("");

 for (i = 0; i < 3; i++)
  ShowStudent(&arr[i]);

 return 0;
}



/*
  중첩된 구조체의 정의
 Point 구조체(x, y pos), Circle 구조체(Point cen, double rad)
 center, radius를 입력받는 함수, 보여주는 함수를 정의하고 메인함수에서 출력
 */

#include <stdio.h>

typedef struct
{
 int xpos;
 int ypos;
}Point;

typedef struct
{
 Point cen;
 double rad;
}Circle;

Circle GetCircleInfo(void)

 Circle cir;
 printf("원의 중심 입력: ");
 scanf("%d %d", &cir.cen.xpos, &cir.cen.ypos);
 printf("반지름 입력: ");
 scanf("%lf", &cir.rad);
 return cir;
}

void ShowPosition(Circle cir_info)
{
 puts("");
 printf("원의 중심 : [%d %d] \n", cir_info.cen.xpos, cir_info.cen.ypos);
 printf("반지름 : %g \n", cir_info.rad);
}

int main()
{
 Circle Cir = GetCircleInfo();
 ShowPosition(Cir);
  
 return 0;
}



/*    ul (0, 0)    (100, 0)  

 (0, 100) (100, 100) lr  

Rectangle 구조체 변수를 인자로 전달받아 직사각형 넓이를 계산해서 출력하는 함수,

직사각형 네 점의 좌표정보 출력 함수 각각 정의.

Rectangle 변수내에는 두 점의 정보만 존재 (좌표평면상 직사각형을 표현하기 위해 필요한 점의 갯수는 ul, lr 2개만 있으면 되므로)

*/

#include <stdio.h>

typedef struct

{

int xpos;

int ypos;

}Point;


typedef struct

{

Point ul; // upper left

Point lr; // lower right

}Rectangle;


void ShowRecArea(Rectangle rec)

{

printf("넓이 : %d \n",

(rec.lr.xpos - rec.ul.xpos)*(rec.lr.ypos - rec.ul.ypos)); // (가로) * (세로)

}


void ShowRecPos(Rectangle rec)

{

printf("좌 상단: [%d %d] \n", rec.ul.xpos, rec.ul.ypos);

printf("좌 하단: [%d %d] \n", rec.ul.xpos, rec.lr.ypos);

printf("우 상단: [%d %d] \n", rec.lr.xpos, rec.ul.ypos);

printf("우 하단: [%d %d] \n", rec.lr.xpos, rec.lr.ypos);

/*(1,1) (4,1)

 (1,4) (4,4)*/

}


int main()

{

Rectangle rec1 = { {1,1},{4,4} };

Rectangle rec2 = { {0,0},{7,5} };

ShowRecArea(rec1);

ShowRecPos(rec1);


ShowRecArea(rec2);

ShowRecPos(rec2);

return 0;

}



/*
 공용체의 필요성
 */

#include <stdio.h>

typedef struct // 상, 하위 각 2바이트
{
 unsigned short upper;
 unsigned short lower;
}UpLowShort;

typedef union uniBuf
{
 int iBuf;
 char arrBuf[4]; // 아스키 코드 1바이트씩 뽑아내기 위한 배열
 UpLowShort ULBuf;
}UniBuf;

int main()
{
 UniBuf buf;
 printf("정수 입력: ");
 scanf("%d", &(buf.iBuf)); // int형 정수 입력받음

 printf("상위 2바이트 : %u \n", buf.ULBuf.upper);
 printf("하위 2바이트 : %u \n", buf.ULBuf.lower);

 printf("최상위 1바이트 아스키 코드: %c \n", buf.arrBuf[0]);
 printf("최하위 1바이트 아스키 코드: %c \n", buf.arrBuf[3]);

 return 0;
}



#include <stdio.h>

typedef enum syllable
{
 Do = 1, Re = 2, Mi = 3, Fa = 4, So = 5, La = 6, Ti = 7
} Syllable;

void Sound(Syllable sy)
{
 switch (sy)
 {
 case Do:
  puts("도는 하얀 도라지 ♪"); return;
 case Re:
  puts("레는 둥근 레코드 ♩"); return;
 case Mi:
  puts("미는 파란 미나리 ♩♪"); return;
 case Fa:
  puts("파는 예쁜 파랑새 ♪♭"); return;
 case So:
  puts("솔은 작은 솔방울 ♩♪♪"); return;
 case La:
  puts("라는 라디오고요~ ♪♩♭♩"); return;
 case Ti:
  puts("시는 졸졸 시냇물 ♩♭♩♪"); return;
 }
 puts("다 함께 부르세~ 도레미파 솔라시도 솔 도~ 짠~");
}

int main(void)
{
 int tone; // == Syllable tone;
 for (tone = Do; tone <= Ti; tone++)
  Sound(tone);
 return 0;
}

728x90

하나의 문자를 출력하는 함수


int putchar(int c);

int fputc(int c, FILE * stream);

 // *stdout은 모니터 출력, putchar함수와 동일한 결과


하나의 문자를 입력받는 함수


int getchar(void);

int fgetc(FILE * stream);  

// *stdin은 키보드로 문자 입력받음


파일의 끝에 도달하거나 함수호출 실패 시 EOF(End Of File) 반환

EOF는 파일의 끝을 알리기 위한 상수 -1 로 정의된다.



/*

  문자열 관련 입출력 함수

*/


#include <stdio.h>


int main()

{

  int ch1 = getchar();  // 문자 입력

  int ch2 = fgetc(stdin);  // 엔터 키 입력


  putchar(ch1);    // 문자 출력

  fputc(ch2, stdout);  // 엔터키 출력

  

  return 0;

}


/* ouput : 

p

p

두 번째 문자가 엔터 키이므로 하나의 문자가 입력되고 출력된것처럼 착각할 수 있음

(아스키 코드값이 10인 "\n")

*/



/*

  문자열 입출력에서의 EOF

  함수 호출 실패 또는 윈도에서 CTRL+Z 가 입력되는 경우(linux : Ctrl+D)

*/


#include <stdio.h>


int main()

{

  int ch;


  while (1)

  {

    ch = getchar();

    if (ch == EOF)

      break;

    putchar(ch);

  }


  return 0;

}



int getchar(void);

int fgetc(FILE * stream);


1바이트 크기 문자를 반환하는데, 반환형이 int인 이유

: char를 unsigned char로 처리하는 컴파일러도 존재


하지만 EOF는 -1로 정의된 상수

변환의 과정에서 양수로 형 변현될 수 있으므로

int형 변수는 기본적으로 signed int이므로 -1 반환에 문제없음



int getchar(void);

int fgetc(FILE * stream);


1바이트 크기 문자를 반환하는데, 반환형이 int인 이유?

: char를 unsigned char로 처리하는 컴파일러도 존재

하지만 EOF는 -1로 정의된 상수인데 

변환의 과정에서 양수로 형 변현될 수 있다.


int형 변수는 기본적으로 signed int이므로 -1 반환에 문제없음



/*

getchar,putchar 함수 이용


소-대문자 변환 출력 (알파벳 이외의 문자는 오류메시지 출력)

*/


#include <stdio.h>


int ConvCase(int ch);


int main()

{

  int ch;


  printf("대<-소문자 변환 : ");

  ch = getchar();

  ch = ConvCase(ch);


  if (ch == -1)  // 예외처리 (문자 아닐때)

  {

    puts("오류");

    return -1;

  }

  putchar(ch);

  puts("");

  

  return 0;

}


int ConvCase(int ch)

{

  int ASCII_Diff = 'a' - 'A';  

  // 아스키 코드에서 모든 영문 대소문자 차가 32로 같음 /  97-65  a-A,  98-66  b-B


  if (ch >= 'A' && ch <= 'Z')

    return ch + ASCII_Diff;

  if (ch >= 'a' && ch <= 'z')

    return ch - ASCII_Diff;

  else

    return -1;

}



/*

문자열 출력함수 puts, fputs


int puts(const char * s);   개행이 포함됨 ("\n")


int fputs(const char * s, FILE * stream);  

두번째 인자 stdout쓸 때 차이는 fputs에는 개행 ("\n")이 포함되지 않음

*/


#include <stdio.h>


int main()

{  

  char * str = "simple string";


  printf("1. puts test \n");

  puts(str);

  puts("So Simple String");


  printf("2. fputs test \n");

  fputs(str, stdout); 

  printf("\n");  //  fputs에는 개행이 포함되지 않음


  printf("3. END \n");


  return 0;

}



/*

  gets, fgets

  char * gets(char * s);

  char * fgets(char * s, int n, FILE * stream);  

  

  // int n은 총 문자열의 길이 / sizeof(str)

  NULL문자를 저장할 공간도 필요

*/


#include <stdio.h>


int main()

{  

  char str[7];  // 6 + NULL


  int i;

  for (i = 0; i < 3; i++)

  {

    fgets(str, sizeof(str), stdin);  // stdin 문자열 입력

    printf("Read %d: %s \n", i + 1, str);

  }


  return 0;

}


// fgets함수는 \n을 만날때까지 문자열을 읽어들이며,

 \n을 버리지않고 문자열의 일부에 포함시킨다.


중간에 삽입된 공백문자도 문자열의 일부로 받아들인다.



출력버퍼를 비우는 fflush 함수

int fflush(FILE * stream);


fflush(stdout);


출력 버퍼를 비운다는 것은 저장된 데이터를 지우는 것이 아님.

출력버퍼에 저장된 데이터를 목적지로 최종전송하는 것.


입력버퍼를 비운다는 것은 삭제의 의미에 가까움.


fflush(stdin); // 컴파일러에 따라 허용되는 경우도 있으나 사용하지 않는 것이 좋다.


입력버퍼를 비우는 함수가 따로 존재하지 않는 것은

read하면 비워지기 때문


이를 이용해 아래와 같은 함수를 정의할 수 있다.



void ClearLineFromReadBuffer(void)

{

while(getchar()!='\n');    // 개행문자를 만날때까지 읽어들임, 읽어들인 문자는 따로 저장하지않고 비워지게 된다.

}



/*

입력버퍼를 비우는 예제

*/

#include<stdio.h>


void ClearLineFrom_ReadBuffer(void);


int main(void)

{

char perID[7];

char name[10];


fputs("주민번호 앞 6자리 입력 : ", stdout);

fgets(perID, sizeof(perID), stdin);

ClearLineFrom_ReadBuffer();


fputs("이름 입력 : ", stdout);

fgets(name, sizeof(name), stdin);

printf("주민번호 : %s \n", perID);

printf("이름 : %s \n", name);


return 0;

}


void ClearLineFrom_ReadBuffer(void)

{

while (getchar() != '\n');

}




/*
문자열 길이를 반환하는 함수 strlen
strlen을 활용하고 문자열의 마지막에 삽입되는 null을 없앤 길이 출력
*/
#include<stdio.h>

void RemoveNULL(char str[]);

int main(void)
{
char str[100];
printf("문자열 입력 : ");
fgets(str, sizeof(str), stdin);
printf("길이 : %d, 내용: %s \n", strlen(str), str);

RemoveNULL(str);
printf("RemoveNULL : %d, 내용: %s \n", strlen(str), str);

return 0;
}

void RemoveNULL(char str[])
{
int lengh = strlen(str);
str[lengh - 1] = 0;
}



문자열을 복사하는 함수 strcpy (string copy)

char * strcpy(char * dest, const char * src);


src에서 dest로 복사 (복사된 문자열의 주소 값 반환)


char * strncpy(char * dest, const char * src, size_t n);

복사되는 문자열의 길이를 n으로 제한


메모리 공간의 효율적인 사용과 프로그램 안정성을 위해 strncpy를 더 많이 쓴다.




/*

문자열을 복사하는 함수 strcpy (string copy)

strncpy (복사되는 문자열의 길이를 n으로 제한)

char * strncpy(char * dest, const char * src, size_t n);

*/

#include<stdio.h>


int main(void)

{

char str1[20] = "1234567890";

char str2[20];

char str3[5];

// str1의 문자열이 str1에 복사됨

strncpy(str2, str1);

puts(str2);


// str1의 문자열이 str3에 복사됨(str3의 길이만큼 제한)

strncpy(str3, str1, sizeof(str3));

puts(str3);


strncpy(str3, str1, sizeof(str3) - 1); // null문자 넣어줄 공간을 빼고 복사

str3[sizeof(str3) - 1] = 0; // null문자를 넣어줌

puts(str3);


return 0;

}



/*

문자열을 덧붙이는 함수 strcat  (STRing conCATenation)

strncat (복사되는 문자열의 길이를 n으로 제한)

char * strncat(char * dest, const char * src, size_t n);

*/

#include<stdio.h>


int main(void)

{

char str1[20] = "First~";

char str2[20] = "Second";


char str3[20] = "Simple num: ";

char str4[20] = "1234567890";


//str2를 str1 뒤에 덧붙임

strcat(str1, str2);

puts(str1);


//n만큼 덧붙이되 null문자 맨뒤에 붙여짐

strncat(str3, str4, 7); // 1~7까지 붙여지고 끝에 NULL이 포함

puts(str3);


return 0;

}




문자열 비교함수 strcmp (string compare)

int strcmp(const char * s1, const char * s2);
int strncmp(const char * s1, const char * s2, size_t n);

두 문자열의 내용이 같으면 0, 같지않으면 0이 아닌값 반환

s1이 더 크면 0보다 큰 값 반환, s2가 더 크면 0보다 작은 값 반환

크고 작음은 아스키 코드값을 근거로 함 
(아스키코드 값이 더 크면 더 큰 문자열로 인식)

문자열에선 가장 앞의 문자를 가지고 비교
(문자열의 끝에는 null이 포함)

/*
문자열 비교함수 strcmp (string compare)

int strcmp(const char * s1, const char * s2);
int strncmp(const char * s1, const char * s2, size_t n);
*/

#include<stdio.h>

int main(void)
{
char str1[20];
char str2[20];
printf("문자열 입력 1: ");
scanf("%s", str1);
printf("문자열 입력 2: ");
scanf("%s", str2);

if (!strcmp(str1, str2)) // 0이 아닌 값은 true, 같을 때 0(false) 반환 == if(strcmp(str1, str2)==0
{
puts("두 문자열 일치");
}
else
{
puts("두 문자열 불일치");

if (!strncmp(str1, str2, 3)) // 3글자까지만 비교
puts("그러나 앞 세 글자는 동일");
}

return 0;
}


문자열의 내용을 변환해주는 함수들


int atoi(const char * str); // atoi : 문자열의 내용 -> int형 변환

long atol(const char * str); // atol : 문자열의 내용 -> long형 변환

double atof(const char * str); // atof : 문자열의 내용 -> double형 변환


/*

그 이외의 변환함수 atoi, atol, atof

*/


#include<stdio.h>


int main(void)

{

char str[20];


fputs("정수 입력: ", stdout);

fgets(str, sizeof(str), stdin);

int result = atoi(str);

printf("%d \n", result*result);


return 0;

}

'Study > C' 카테고리의 다른 글

파일 입출력 공부  (0) 2016.08.25
구조체 공부  (0) 2016.08.23
c 복습-문제풀이2  (0) 2016.08.22
섭씨->화씨 변환, 최대 공약수 구하기  (0) 2016.05.03
2016-04-07-업무일지_구조체 및 함수  (0) 2016.04.07
728x90


/*  Pointer Swap (double pointer 이용)  반드시 포인터에 저장된 값을 swap하도록! */

#include<stdio.h>


void SwapPtr(int* *dptr1, int* *dptr2)

{  

  int *temp = *dptr1;  // type이 일치해야 함

  *dptr1 = *dptr2;

  *dptr2 = temp;  

  //(*dptr1 = &num1 = ptr1 / *dptr2 = &num2 = ptr2) 

}


int main(void)

{

  int num1 = 10;

  int num2 = 20;


  int *ptr1;

  int *ptr2;


  ptr1 = &num1;

  ptr2 = &num2;

  printf("*ptr1, *ptr2 : %d  %d \n", *ptr1, *ptr2);


  SwapPtr(&ptr1, &ptr2);

  printf("*ptr1, *ptr2 : %d %d \n", *ptr1, *ptr2);

  return 0;

}



/*  Pointer Array Type 


// int ** dptr = &ptrArr[0]; / *(dptr[0]) = *(ptrArr[0]) = *(ptr1) = num1

// *ptr1=&num1;

*/

#include<stdio.h>


int main(void)

{

  int num1 = 10;

  int num2 = 20;

  int num3 = 30;


  int *ptr1 = &num1;

  int *ptr2 = &num2;

  int *ptr3 = &num3;

  

  int *ptrArr[] = { ptr1, ptr2, ptr3 }; 

  int ** dptr = ptrArr; // ptrArr이 double pointer,  ptrArr의 주소값에 대입하는 것

    

  printf("%d %d %d \n", *(ptrArr[0]), *(ptrArr[1]), *(ptrArr[2]));

  printf("%d %d %d \n", *(dptr[0]), *(dptr[1]), *(dptr[2]));


  return 0;

}



ptrArr은 int형 포인터를 요소로 갖는 배열의 이름이기 때문에 더블 포인터형


따라서 

 int **dptr = ptrArr;





/*  

  int * maxPtr;  int * minPtr;  int arr[5];

  함수 MaxAndMin, 위 배열과 두 포인터 변수에 대한 정보 전달

  maxPtr에 가장 큰값이 저장된 배열요소 주소 값, minPtr에 가장 작은 값이 저장된 배열요소 주소값 저장

*/


#include <stdio.h>


void MaxAndMin(int *arr, int size, int **MaxPtr, int **MinPtr);


int main()

{  

  int * maxPtr;

  int * minPtr;

  int arr[5];


  int i;

  for (i = 0; i < 5; i++)

  {

    printf("%d번째 정수 입력 : ", i + 1);

    scanf("%d", &arr[i]);

  }  


  MaxAndMin(arr, sizeof(arr) / sizeof(int), &maxPtr, &minPtr);

  printf("최대 : %d, 최소 : %d \n", *maxPtr, *minPtr);


  return 0;

}


void MaxAndMin(int *arr, int size, int **MaxPtr, int **MinPtr)

{

  int *max;

  int *min;  

  max = min = &arr[0];


  int i;

  for(i=0; i<size; i++)

  {

    if (*max < arr[i])

      max = &arr[i];


    if (*min > arr[i])

      min = &arr[i];    

  }


  *MaxPtr = max;

  *MinPtr = min;

}


/*  

  2d Array Address

*/


#include <stdio.h>


int main()

{

  int arr2d[3][3];

  printf("%p \n", arr2d);

  printf("%p \n", arr2d[0]);

  printf("%p \n \n", &arr2d[0][0]);


  printf("%p \n", arr2d[1]);  // +12  sizeof(int) x 3

  printf("%p \n", &arr2d[1][0]);  // +12


  printf("sizeof(arr2d): %d \n", sizeof(arr2d));  // 배열 이름의 size는 배열 전체의 크기

  printf("sizeof(arr2d[0]): %d \n", sizeof(arr2d[0]));  // 각 행의 size반환 (12)

  printf("sizeof(arr2d[1]): %d \n", sizeof(arr2d[1]));

  printf("sizeof(arr2d[2]): %d \n", sizeof(arr2d[2]));


  return 0;

}


2차원 배열이름의 포인터 형은 가리키는 대상과 가로 길이에 의존적이다. int [4][2]  [6][2]


int arr[3][4]의 포인터 형은

int (*ptr) [4];  //  [4]는 가로길이

포인터 연산시 4칸씩 건너뛰는 int형 변수 포인터


포인터 연산(+,-)을 했을 때의 주소값을 생각하면 된다.



/*  

  2차원 배열의 포인터 형

*/


#include <stdio.h>


int main()

{

  int arr1[2][2] = {

    {1,2},{3,4}

  };


  int arr2[4][2] = {

    {1,2,},{3,4},{5,6},{7,8}

  };


  int(*ptr)[2];

  int i;


  ptr = arr1;  // arr은 상수, ptr은 변수이므로 ptr이 arr1도 arr2도 가리킬 수 있다.

  printf("** Show 2,2 arr1 **\n");

  for (i = 0; i < 2; i++)

    printf("%d %d \n", ptr[i][0], ptr[i][1]);


  ptr = arr2;

  printf("** Show 2,2 arr1 **\n");

  for (i = 0; i < 4; i++)

    printf("%d %d \n", ptr[i][0], ptr[i][1]);


  return 0;

}


int* whoA [4];  // 포인터 배열 : 포인터 변수로 이루어진 배열

int (*whoB) [4];  // 배열 포인터 : 배열을 가리킬 수 있는 포인터 변수



함수포인터 


(매개변수)(반환형)


무엇을 전달받고 

무엇을 반환하는지 이해


/*  Function Pointer

num1,num2값을 더해서 보여주는 함수

string을 보여주는 함수를 메인함수에서 함수 포인터 변수로 호출

*/

#include<stdio.h>


void ShowAdd(int n1, int n2);

void ShowString(char * str);


int main(void)

{

  int num1 = 10, num2 = 20;

  char * str = "String";


  void(*Add_FuncPointer)(int, int) = ShowAdd;  // (int n1, int n2)

  void(*String_FuncPointer)(char *) = ShowString;


  Add_FuncPointer(num1,num2);

  String_FuncPointer(str);

  

  return 0;

}


void ShowAdd(int n1, int n2)

{

  printf("%d + %d = %d \n", n1, n2, n1 + n2);

}


void ShowString(char * str)

{

  printf("%s \n", str);

}



/*  Useful Function Pointer

*/

#include<stdio.h>


int WhoIsFirst(int age1, int age2, int(cmp)(int n1, int n2));

int OlderFirst(int age1, int age2);

int YoungerFirst(int age1, int age2);


int main(void)

{

  int age1 = 20;

  int age2 = 30;

  int first;


  printf("늙은 사람이 먼저 입장 \n");

  first = WhoIsFirst(age1, age2, OlderFirst);

  printf("%d세와 %d세중 %d세가 먼저 입장 \n\n", age1,age2,first);


  printf("젊은 사람이 먼저 입장 \n");

  first = WhoIsFirst(age1, age2, YoungerFirst);

  printf("%d세와 %d세중 %d세가 먼저 입장\n\n", age1,age2,first);


  return 0;

}


int WhoIsFirst(int age1, int age2, int(cmp)(int n1, int n2))

{

  return cmp(age1, age2);

}


int OlderFirst(int age1, int age2)

{

  if (age1 > age2)

    return age1;

  else if (age1 < age2)

    return age2;

  else

    return 0;

}


int YoungerFirst(int age1, int age2)

{

  if (age1 < age2)

    return age1;

  else if (age1 < age2)

    return age2;

  else

    return 0;

}



/*  

  18-1

*/


#include <stdio.h>


int main()

{

  int * arr1[5];

  int * arr2[3][5];


  int **ptr = arr1;

  int (*ptr2)[5] = arr2;  


  return 0;

}



arr[1][0][1]

== ( (*arr)+1) [0][1]

== (* (* (arr+1) +0 ) )[1]

== *( * ( * ( arr+1) + 0 ) +1 ) )

== ( * ( arr[1]+0 ) )[1]

==  *(*(arr[1]+0)+1) 

==  *(arr[1][0]+1)



/*  

   argument count, argument vector

*/


#include <stdio.h>


int main(int argument_count, char *argument_vector[])

{

  int i = 0;

  printf("전달된 문자열 수 : %d \n", argument_count);


  for (i = 0; i < argument_count; i++)

    printf("%d번째 문자열: %s \n", i + 1, argument_vector[i]);

      

  return 0;

}


/*

output:

전달된 문자열 수 : 4

1번째 문자열: E:\Visual Studio 2015\Projects\C_Study\Debug\C_Study.exe

2번째 문자열: I

3번째 문자열: Hate

4번째 문자열: You!

*/




/*  

   Argument Vector Parameter Type

*/


#include <stdio.h>


void Show_All_String(int argc, char *argv[]);


int main()

{

  char *str[3] = {

    "수박수박쑤",

    "씨발라먹을",

    "씨프로그래밍"

  };

  Show_All_String(4, str);

        

  return 0;

}


void Show_All_String(int argc, char *argv[])

{

  int i;

  for (i = 0; i < argc; i++)

    printf("%s \n", argv[i]);

}



/*

  end of argument vector (null)

*/


#include <stdio.h>


int main(int argument_count, char *argument_vector[])

{

  int i = 0;

  printf("전달된 문자열 수 : %d \n", argument_count);


  while (argument_vector[i] != NULL)

  {

    printf("%d번째 문자열: %s \n", i + 1, argument_vector[i]);

    i++;

  }

  return 0;

}



728x90

ATmega128 포트가 범용 디지털 I/O로 사용될 경우, Read-Modify-Write 기능을 수행할 수 있음

:     I/O포트 입출력 변경하지않고도 동시에 입력과 출력의 기능을 수행할 수 있다.

입출력 방향의 변경없이 포트의 동작 방향이 달라질 수 있음


DDRx 레지스터 : 입출력의 방향을 설정, 각 비트를 1로 설정하면 출력, 0으로 설정하면 입력으로 결정

0 : PORTxn = 입력 -> 입력된 데이터가 PINxn에 저장.

1 : PORTxn = 출력 -> PORTxn의 데이터가 출력됨.


PORTx 레지스터 : 데이터 출력

PINx 레지스터 : 포트 입력 핀, 읽기만 가능하고 쓰기 불가



ATmega128에서 PORTG는 5개의 비트만 사용 (다른 PORT는 0-7까지 8개의 비트 사용)



Atmel/avr tools/avr toolchain/avr/include/avr/iom128.h

 /io.h

에서 SFR 등 비트 정의를 볼 수 있다.




PORT초기화 예)


DDRB = 0xFF;    // 포트 B 출력 설정

PORTB = 0x00;    // 출력 0 설정

DDRD = 0x00;    // 포트 D 입력 설정

PORTD = 0x00;    // 포트 D 내부 풀업 저항을 사용하기 위해 0으로 설정

SFIOR |= 1<<2;    // PUD 비트 1로 설정(풀업 저항 사용안함)



SFIOR의 PUD(Pull-up Disable) 비트를 1로 설정하면 ATmega128 내부에 있는 풀업저항을 사용하지 않는것이고 

PUD를 0으로 설정하면 내부 풀업저항을 사용하는 것이다. 


SFIOR의 PUD 비트의 초기값은 0으로 되어 있기 때문에 이 레지스터를 설정하지 않으면 내부 풀업저항을 사용하도록 설정되는 것과 같다. 





WIn32 API 수업


// 그림판

#include <Windows.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hInst;

LPCTSTR lpszClass = TEXT("Text Out 124");  // Title 명


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)

{

HWND hWnd;

MSG Message;

WNDCLASS WndClass;

g_hInst = hInstance;


WndClass.cbClsExtra = 0;

WndClass.cbWndExtra = 0;

WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

WndClass.hInstance = hInstance;

WndClass.lpfnWndProc = WndProc;

WndClass.lpszClassName = lpszClass;

WndClass.lpszMenuName = NULL;

WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

RegisterClass(&WndClass);


hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);

ShowWindow(hWnd, nCmdShow);


while (GetMessage(&Message, NULL, 0, 0))

{

TranslateMessage(&Message);

DispatchMessage(&Message);

}

return (int)Message.wParam;

}


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT pa;

static int x = 100;

static int y = 100;

static int a = 0;


static BOOL bNowDraw = FALSE;


switch (iMessage)

{

case WM_DESTROY:

PostQuitMessage(0);    // 종료

return 0;


case WM_PAINT:

hdc = BeginPaint(hWnd, &pa);

TextOut(hdc, x, y, TEXT("A"), 1);

EndPaint(hWnd, &pa);

return 0;


case WM_KEYDOWN:

switch (wParam)

{

case VK_LEFT:

x -= 8;

break;

case VK_RIGHT:

x += 8;

break;

case VK_UP:

y -= 8;

break;

case VK_DOWN:

y += 8;

break;

case VK_SPACE:

a++;

a %= 2;

break;

}

InvalidateRect(hWnd, NULL, FALSE);

return 0;


case WM_LBUTTONDOWN:

x = LOWORD(lParam);

y = HIWORD(lParam);

bNowDraw = true;

return 0;

case WM_MOUSEMOVE:

if (bNowDraw == TRUE)

{

hdc = GetDC(hWnd);

MoveToEx(hdc, x, y, NULL);

x = LOWORD(lParam);

y = HIWORD(lParam);

LineTo(hdc, x, y);

ReleaseDC(hWnd, hdc);

}

return 0;

case WM_LBUTTONUP:

bNowDraw = FALSE;

return 0;

case WM_LBUTTONDBLCLK:

MessageBox(hWnd, TEXT("더블클릭"), TEXT("메세지박스"), MB_YESNO);

return 0;

}

return(DefWindowProc(hWnd, iMessage, wParam, lParam));

}





// 타이머

#include <Windows.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hInst;

LPCTSTR lpszClass = TEXT("Timer");  // Title 명


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)

{

HWND hWnd;

MSG Message;

WNDCLASS WndClass;

g_hInst = hInstance;


WndClass.cbClsExtra = 0;

WndClass.cbWndExtra = 0;

WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

WndClass.hInstance = hInstance;

WndClass.lpfnWndProc = WndProc;

WndClass.lpszClassName = lpszClass;

WndClass.lpszMenuName = NULL;

WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

RegisterClass(&WndClass);


hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, 300, 400, 400, 300, NULL, (HMENU)NULL, hInstance, NULL);

ShowWindow(hWnd, nCmdShow);


while (GetMessage(&Message, NULL, 0, 0))

{

TranslateMessage(&Message);

DispatchMessage(&Message);

}

return (int)Message.wParam;

}


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT pa;

SYSTEMTIME st;

static TCHAR sTime[128];


switch (iMessage)

{

case WM_CREATE:

SetTimer(hWnd, 1, 1000, NULL);

return 0;

case WM_TIMER:

GetLocalTime(&st);

wsprintf(sTime, TEXT("지금 시간은 %d:%d:%d입니다."), st.wHour, st.wMinute, st.wSecond);

InvalidateRect(hWnd, NULL, TRUE);

return 0;


case WM_DESTROY:

PostQuitMessage(0);    // 종료

return 0;


case WM_PAINT:

hdc = BeginPaint(hWnd, &pa);

TextOut(hdc, 100, 100, sTime, lstrlen(sTime));

EndPaint(hWnd, &pa);

return 0;

}

return(DefWindowProc(hWnd, iMessage, wParam, lParam));

}



// 3초에 한번 덧셈문제 출제


#include <Windows.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hInst;

LPCTSTR lpszClass = TEXT("Timer");  // Title 명


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)

{

HWND hWnd;

MSG Message;

WNDCLASS WndClass;

g_hInst = hInstance;


WndClass.cbClsExtra = 0;

WndClass.cbWndExtra = 0;

WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

WndClass.hInstance = hInstance;

WndClass.lpfnWndProc = WndProc;

WndClass.lpszClassName = lpszClass;

WndClass.lpszMenuName = NULL;

WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;

RegisterClass(&WndClass);


hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, 300, 400, 400, 300, NULL, (HMENU)NULL, hInstance, NULL);

ShowWindow(hWnd, nCmdShow);


while (GetMessage(&Message, NULL, 0, 0))

{

TranslateMessage(&Message);

DispatchMessage(&Message);

}

return (int)Message.wParam;

}


LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT pa;

SYSTEMTIME st;

static TCHAR sTime[128];


int a = rand() % 30;

int b = rand() % 30;


switch (iMessage)

{

case WM_CREATE:

SetTimer(hWnd, 1, 3000, NULL);

return 0;

case WM_TIMER:

GetLocalTime(&st);

wsprintf(sTime, TEXT("%d+%d=?"), a, b);

InvalidateRect(hWnd, NULL, TRUE);

return 0;


case WM_DESTROY:

KillTimer(hWnd, 1);

PostQuitMessage(0); // 종료

return 0;


case WM_PAINT:

hdc = BeginPaint(hWnd, &pa);

TextOut(hdc, 100, 100, sTime, lstrlen(sTime));

EndPaint(hWnd, &pa);

return 0;

}

return(DefWindowProc(hWnd, iMessage, wParam, lParam));

}




'Study > Embedded' 카테고리의 다른 글

아두이노 기초  (0) 2017.05.25
ATMEGA USART-C# App 연동  (0) 2016.12.12
7/8 LCD제어2  (0) 2016.07.08
7/5 LCD 제어  (0) 2016.07.05
5/26 업무일지 PC PWM을 이용한 LED 밝기 조절  (0) 2016.05.26
728x90

LCD 모듈 제어에 기본적으로 수행되야하는 기능


- IR에 명령 쓰기

- DR에 데이터 쓰기

- 명령 처리 시간을 고려한 시간 지연



LCD 컨트롤러 명령어 표


신호 제어선 정의 예


#define  CLR   0x01      //Clear Display 명령
#define  HOME  0x02      //Return Home 명령 
#define  FNC   0x38      //Function Set 명령
                		 //Data Length = 8bit. 행수 2행


void LCD_PortSetting(void)
{
  DDRC = 0xFF;        //데이터 라인
  DDRD = 0xFF;        //0~2 제어핀 사용
  //D0: RS ,D1: R/W ,D2: EN
}


명령 레지스터에 명령어 쓰기 함수


위의 명령어 표와 같은 명령을 수행할 함수이다. 수행결과는 함수를 호출하는 함수에 반환될 필요가 없다.


void IR_Write(unsigned char Data) { PORTD &= 0xFC; // RS = 0, RW = 0 (Write Enable), 0xFC = 1111 1100) _delay_us(1); // Enable 까지 최소 대기 시간 40ns PORTD |= 0x04; // En _delay_us(1); PORTC = Data; _delay_us(1); PORTD = 0b00000010; // Disable. Read Mode }

PORTD &= 0XFC // PORTD= PORTD & 0XFC



데이터 레지스터에 데이터 쓰기 함수


DDRAM 또는 CGRAM에 데이터를 쓰는 함수로서 사용되는 여러가지 명령어가 제시되어 있다.

void DR_Write(unsigned char Data)
{
  PORTD = 0x01;    //RS = 1, Write Enable
  _delay_us(1);    //Enable 까지 최소 대기 시간 40ns
  PORTD |= 0x04;    //Enable 활성화
  _delay_us(1);    //
  PORTC = Data;    //Data
  _delay_us(1);
  PORTD = 0b00000010;  //Disable, Read Mode  
}













'Study > Embedded' 카테고리의 다른 글

ATMEGA USART-C# App 연동  (0) 2016.12.12
7/21 Atmega128 포트/ win32 api  (0) 2016.07.21
7/5 LCD 제어  (0) 2016.07.05
5/26 업무일지 PC PWM을 이용한 LED 밝기 조절  (0) 2016.05.26
2016-05-19 업무일지-Atmega2560_LCD출력  (0) 2016.05.19
728x90

IR (명령 레지스터) : LCD 모듈 환경 설정

DR (데이터 레지스터) : LCD 모듈에 글자를 나타내기 위한 데이터 값 기록



LCD 컨트롤러 내부는 IR,DR과 문자를 표시하기 위해 사용되는 DDRAM, CGRAM, CGROM으로 구성



LCD 모듈은 보통 총 14핀 또는 16핀 구성 (16핀은 백라이트 구동을 위한 전원단자 2핀 추가)


1,2번 : LCD 모듈 구동전원 인가

3번 : LCD 표시장치 밝기 조절 (밝기 조절시 가변저항 연결, 필요없으면 GND 연결)


4-6 : LCD 제어 (RS, R/W, E) 

RS (4번) - 입력단자로서 LCD 모듈의 명령 또는 데이터 레지스터 선택

0이면 IR, 1이면 DR 선택


R/W (5번) - 데이터 또는 명령을 읽고, 쓰기할때 사용

0이면 쓰기 (CPU에서 LCD 모듈로 데이터 씀)

1이면 읽기 (LCD모듈에서 CPU로 데이터 읽음)


E (6번) - 활성화되어있으면 데이터 교환이 이루어짐

HIGH (1 입력) 일때 데이터 교환 가능, 0일때는 데이터 교환 불가능


7-14 : Data Bus (4비트 방식 제어시 11-14번만 이용됨)

마이크로 컨트롤러와 인터페이스를 할 경우에는 읽기 쓰기 타이밍을 고려해야 함(데이터 시트 타이밍도 참고)




IR (명령 레지스터)

: LCD의 제어에 필요한 명령 저장, 표시 데이터 DDRAM 위치주소와 문자발생기 CGRAM 위치 지정하기 위한 주소정보 저장


DR (데이터 레지스터)

: 화면에 표시할 데이터 또는 새로운 글꼴에 대한 데이터 임시 저장

데이터를 쓸 때는 IR에 의해 지정된 DDRAM 또는 CGRAM 주소로 데이터 전달

읽을때는, IR에 의해 지정된 DDRAM 또는 CGRAM 주소의 데이터가 마이크로 컨트롤러로 전달



제어 명령어는 데이터 시트를 참고

HY-1602W-204-LCD.pdf

케릭터 LCD 명령어 설명.pdf




비지 플래그 

: 연속적으로 LCD 모듈에 제어명령이 입력될 때, LCD 모듈이 이 명령을 처리할 수 있는가를 나타내는 상태 표시 플래그 

RS가 0 (IR), R/W가 1(읽기)일때 출력된다.


BF = 0 : LCD 모듈로 다음 명령을 쓸 수 있다.

BF = 1 : LCD 컨트롤러가 현재 IR로 입력된 명령어 처리하는 상태, 다음 제어 명령을 쓸수 없는 상태를 나타냄.








DDRAM (Display Data RAM)

화면에 표시할 8비트 문자를 저장 (표시되지 않는 영역의 RAM은 일반적 데이터 저장용 메모리로 사용가능)


CGROM (Character Generator ROM)

문자 패턴을 저장




 HY-1602W-204-LCD.pdf (CGROM에 저장된 내용은 데이터 시트 11p 참고)




CGRAM (Character Generator RAM)

사용자가 원하는 문자 패턴을 만들때 사용



화면 클리어

#define CLR    0x01 // 화면 전체 클리어 후, Return Home 명령


커서 홈

#define HOME  0x02 // 커서만 홈 위치로 보내는 명령


엔트리 모드 셋

: LCD 모듈에 데이터를 쓰기/읽기 수행할 경우 DDRAM주소 즉, 커서 위치를 오른쪽으로 증가 또는 왼쪽으로 감소시킬것인가를 결정하는 기능 수행

또한, 커서 위치는 변하지 않고 화면을 이동시킬지(shift) 결정



DB2 bit를 1로 설정 


1비트=I/D

I/D = 1일때 커서 또는 깜박임 위치가 우측 이동 (주소 +1)

I/D = 0일때 커서 또는 깜박임 위치가 좌측 이동 (주소 -1)


0비트=S    

S = 1, I/D=1일 때, 좌로 쉬프트

S = 1, I/D=0일 때, 우로 쉬프트

S = 0, 화면 쉬프트 되지 않음


* CGRAM도 같은 방법으로 적용



Display ON/OFF Control

: 화면의 ON/OFF, 커서의 ON/OFF, 커서위치에 있는 문자 점멸 등의 기능 설정

예) IR_Write(0x0E); // Display on/off DDRAM, 커서를 화면에 표시


* 더 자세한 명령어 설정은 데이터 시트 참고


커서 표시 시프트

: 커서의 위치 또는 표시할 데이터의 읽기 또는 쓰기없이 (DDRAM 내용 변경없이)

오른쪽/왼쪽으로 이동.


2줄을 표시할 경우 첫번째줄의 끝을 넘을 경우 두번째 줄 이동


* 첫번째줄과 두번째 줄이 동시 이동

데이터 쉬프트해도 두번째 줄 데이터는 첫번째 줄에 표시안됨

쉬프트 해도 AC는 변하지 않음



Function Set

: Function Set은 LCD를 사용하기 앞서 선행되어야 한다.

(busy flag와 어드레스 명령을 제외한 다른 명령이 실행되기전에 프로그램 앞 부분에 실행되어야 함)



DL : 인터페이스 길이

1이면 데이터 길이 8비트 설정

0이면 데이터 길이 4비트 설정 (DB7-DB4사용), 이 경우 두번에 나누어 먼저 상위 4비트 전송하고, 하위 4비트 전송해야 함


N : 표시줄의 숫자 (0이면 1줄, 1이면 2줄)


F : 문자 폰트 설정 (0이면 5x8, 1이면 5x10)




CGRAM, DDRAM 주소 설정



CGRAM에 새로운 문자를 만들고자 할 경우 IR레지스터의 DB6 비트를 1로 설정(AC는 주소로서 전달)


DDRAM에 주소를 설정한 후에 데이터를 송수신하려면 DB7 비트를 1로 설정

N=0이면 한개의 라인을 가지며, 7비트 (AC0-AC6)는 0x00~0x4F로 설정


N=1이면, 두개의 줄을 가지며

첫번째 줄의 주소는 0x00~0x27

두번째 줄의 주소는 0x40~0x67까지로 설정

'Study > Embedded' 카테고리의 다른 글

7/21 Atmega128 포트/ win32 api  (0) 2016.07.21
7/8 LCD제어2  (0) 2016.07.08
5/26 업무일지 PC PWM을 이용한 LED 밝기 조절  (0) 2016.05.26
2016-05-19 업무일지-Atmega2560_LCD출력  (0) 2016.05.19
2016-05-17 업무일지-7 segment  (0) 2016.05.17
728x90
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
 
//이름/국영수 점수 입력받고 이름/국영수점수/총점/평균/석차 출력
 
namespace SScore
{
    class Student
    {
        public string Name;
        public int Kor;
        public int Eng;
        public int Math;
 
        public int input(object[] arr, int Cnt)
        {
            //이곳에 이름, 국영수 점수 입력받고 총점과 평균을 구한다  
            Console.Write("이름 입력 : ");
            Name = Console.ReadLine();
 
            while (true)
            {
                Console.Write("첫번째 점수 : ");
                Kor = int.Parse(Console.ReadLine());
                if (Kor < 0 || Kor > 100)
                    continue//반복문을 리셋하세요(반복문의 처음 위치로 이동)
 
                ReInput://Label statement
                Console.Write("두번째 점수 : ");
                Eng = int.Parse(Console.ReadLine());
                if (Eng < 0 || Eng > 100)
                    goto ReInput;//지정된 label statement로 이동
                do
                {
                    Console.Write("세번째 점수 : ");
                    Math = int.Parse(Console.ReadLine());
                } while (Math < 0 || Math > 100);
 
                int Sum = Kor + Eng + Math;
                Double Avg = Sum / 3;
 
                arr[Cnt] = Name + "\t" + Kor + "\t" + Eng + "\t" + Math + "\t" + Sum + "\t" + Avg + "\t";
 
                return Sum;
            }
        }
 
        class Program
        {
            static void Exception(int arg)
            {
                if (arg < 2)
                    Console.WriteLine("arg : {0}", arg);
                else
                    throw new Exception("arg가 10보다 큽니다.");
            }
 
            static void Main(string[] args)
            {
                object[] arr = new object[20];
                int[] arr_sum = new int[20];
                int[] rank = new int[20];
 
                Student std = new Student();
 
                char select;
                int Cnt = 0;
 
                while (true)
                {
                    Console.WriteLine("=====================================학생 성적 관리 프로그램=====================================");
                    Console.WriteLine("1. 학생성적 입력 ");
                    Console.WriteLine("2. 학생성적 보기 ");
                    Console.WriteLine("Q. 프로그램 종료 ");
                    Console.WriteLine("=================================================================================================");
 
                    Console.Write(" 메뉴선택 ( 1,2 또는 Q 입력 ) : ");
                    try
                    {
                        select = char.Parse(Console.ReadLine());
 
                        if (select == '1')
                        {
                            arr_sum[Cnt] = std.input(arr, Cnt);
                            Cnt++;
                        }
                        else if (select == '2')
                        {
                            Console.WriteLine();
                            Console.WriteLine("==============종합결과===============");
                            Console.WriteLine("성명\t국어\t영어\t수학\t총점\t평균\t순위");
 
                            for (int i = 0; i < Cnt; i++)
                            {
                                rank[i] = 1;
                                for (int a = 0; a < Cnt; a++)
                                {
                                    if (arr_sum[i] < arr_sum[a])
                                    {
                                        rank[i]++;
                                    }
                                }
                                Console.WriteLine("{0}{1}", arr[i], rank[i]);
                            }
                            break;
                        }
                        else if (select == 'q')
                        {
                            Console.Write("프로그램이 종료됩니다.");
                            break;
                        }
                        else if (select == 'Q')
                        {
                            Console.Write("프로그램이 종료됩니다.");
                            break;
                        }
                    }
 
                    catch (Exception e)
                    {
                        Console.WriteLine("올바른 값을 입력하세요");
                    }
                }
            }
        }
    }
}


'Study > C#' 카테고리의 다른 글

c# 복습  (0) 2017.03.31
headfirst c#-wpf  (0) 2016.11.19
c# 클래스 복습2  (0) 2016.05.23
c# 스터디일지 -클래스  (0) 2016.05.22
2016-05-20-C#복습  (0) 2016.05.20
728x90

PC PWM을 이용한 LED 밝기 조절




WGMn2~0 비트에 의한 동작모드

모드1 : Phase Correct PWM / TOP(0xFF)


/************************************************
* PC PWM을 이용한 LED 밝기 조절 프로그램
* 2016년 5월 26일
************************************************/

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  unsigned char i, duty;

  //PWM 출력을 뽑을 GPIO설정(OC0A(PB7))
  DDRB=0xFF; // PB7 PWM 출력, PB 0~6 사용안함
  //Time / Counter0의 설정 (PC PWM 모드)
  TCCR0A = 0b10000001; // 0x81, 상향카운터 compare match 0, 하향 1로 set
  TCCR0B = 0x01; // 1분주

  while(1)
  {
    for(i=0, duty=0; i<6; i++, duty +=51)
    {
      OCR0A = duty;
      _delay_ms(500);
    }

  }
  return 0;
}




/************************************************
* PC PWM을 이용한 LED 밝기 조절 프로그램
* 2016년 5월 26일
************************************************/

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  unsigned char i, duty;

  //PWM 출력을 뽑을 GPIO설정(OC0A(PB7))
  DDRB=0xFF; // PB7 PWM 출력, PB 0~6 사용안함
  //Time / Counter0의 설정 (PC PWM 모드)
  TCCR0A = 0b10000001; // 0x81, 상향카운터 compare match 0, 하향 1로 set
  TCCR0B = 0x01; // 1분주

  while(1)
  {
    for(i=0, duty=0; i<6; i++, duty +=51)
    {
      OCR0A = duty;
      _delay_ms(500);
    }

  }
  return 0;
}




switch문으로 변경

/************************************************
* PC PWM을 사용한 DC 모터 속도 제어용 프로그램

* 속도 조절 단계 15단계, 출력 0C0A 또는 OC0B
* 입력 스위치 입력 2개(UP, Down)
* 최대 속도 도달시 UP키 동작 안함, 회전하지 않을 때 DN키 동작 안함.
************************************************/
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  unsigned char duty = 0;
  
  
  DDRB  =  0xFF;            

  DDRA  =  0xFC;    //0,1번 포트를 스위치 입력으로                      
  
  TCCR0A  =  0x81;    //OC0A를 출력으로 사용                
  TCCR0B  =  0x01;          

   while(1)
  {
    key = (PINA & 0x03)
    switch(key)
    {
      case 1:
        while(PINA & 0x01 );
        if(i < 15)
          i++;
        break;
      case 2:
        while(PINA & 0x02);
        if(i > 0)
          i--;
        break;
    }
    OCR0A = 17*i;
  }
  return 0;
}


'Study > Embedded' 카테고리의 다른 글

7/8 LCD제어2  (0) 2016.07.08
7/5 LCD 제어  (0) 2016.07.05
2016-05-19 업무일지-Atmega2560_LCD출력  (0) 2016.05.19
2016-05-17 업무일지-7 segment  (0) 2016.05.17
7 Segment 출력(proteus시뮬)  (0) 2016.05.16
728x90

기반 클래스와 파생클래스 사이의 형 변환



안전한 형변환을 위한 is, as 연산자


is 연산자

객체가 해당형식에 해당하는지 검사하여, 결과를 bool값으로 반환

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TypeCasting
{
    class TestClass { }
    class Program
    {
        static void Main(string[] args)
        {
            Object obj=1004;
            Object obj2 = "천사";
            Console.WriteLine(" {0} is string -> {1}", obj, obj is string);
            Console.WriteLine(" {0} is string -> {1}", obj2, obj2 is string);
            Console.WriteLine("");
        }
    }
}

Output : 

 1004 is string -> False

 천사 is string -> True


계속하려면 아무 키나 누르십시오 . . .



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;

namespace TypeCasting
{
    class TestClass { }
    class Program
    {
        static void Main(string[] args)
        {
            Object obj = "This is string";

            if (obj is int)
                Console.WriteLine("obj는 string");
            else // else문이 없으면 화면에 아무것도 출력되지 않고 실행됨
                Console.WriteLine("obj는 string이 아님");
        }
    }
}

Output : 

obj는 string이 아님

계속하려면 아무 키나 누르십시오 . . .



as 연산자

형변환 연산과 다른 점은 변환이 가능하지 않는 경우 예외를 발생하지 않고 null이 반환됨.

               as 연산자는 오직 참조 형식에 대해서만 사용 가능


즉, as 연산자는 as 뒤에 나오는 타입이 아니면 null을 반환.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TypeCasting
{
    class Program
    {
        static void Main(string[] args)
        {
            object obj1= "alpha";
            object obj2 = 273;
            object obj3 = 52.273;

            string alpha = (string)obj1;
            string beta = (string)obj2;
            string gamma = (string)obj3;

            Console.WriteLine("alpha : " + alpha);
            Console.WriteLine("beta : " + beta);
            Console.WriteLine("gamma : " + gamma);
        }
    }
}

Output :

위와 같이 강제 형 변환을 하게 되면 처리되지 않은 예외가 뜨면서 프로그램이 종료된다.



아래는 as연산자를 쓴 소스이다.  변환이 가능하지않은 A는 null을 반환하게 된다.

using System;

namespace TypeCasting
{
    class Program
    {
        static void Main(string[] args)
        {
            object obj1 = 1004;
            object obj2 ="STRING!";

            string A = obj1 as string;
            string B = obj2 as string;

            Console.WriteLine("(string아니면 null) A: " + A);
            Console.WriteLine("(string아니면 null) B: " + B);
        }
    }
}

Output :

(string아니면 null) A:

(string아니면 null) B: STRING!

계속하려면 아무 키나 누르십시오 . . .

'Study > C#' 카테고리의 다른 글

c# 복습  (0) 2017.03.31
headfirst c#-wpf  (0) 2016.11.19
5/27 업무일지 c#학생성적관리(콘솔)  (0) 2016.05.27
c# 스터디일지 -클래스  (0) 2016.05.22
2016-05-20-C#복습  (0) 2016.05.20
728x90

try~catch 문


try 블록과 각각 다른 예외의 처리기를 지정하는 하나 이상의 catch 절로 구성



아래의 소스는 실행시 에러와 함께 종료된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;
 
namespace TryCatchText
{
    class Program
    {
        static void Main(string[] args)
        {
            int a, b, c;
            a = 10;
            b = 0;
            c = a / b;
            Console.WriteLine(c);
        }
    }
}
cs



실행시 에러가 뜨면서 프로그램 종료 



try~catch문을 통해 예외문구를 출력하게하고 비정상 종료를 막을 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
 
namespace TryCatchText
{
    class Program
    {
        static void Main(string[] args)
        {
            int a, b, c;
            a = 10;
            b = 0;
            try
            {
                c = a / b;
                Console.WriteLine(c);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}
cs


Output : 


0으로 나누려 했습니다.

계속하려면 아무 키나 누르십시오 . . .




c#에서의 접근 한정자

 public

 클래스의 내부/외부 모든 곳에서 접근 가능



 protected

 클래스의 외부에서는 접근할수 없지만, 파생 클래스에서는 접근 가능.

 private

 클래스의 내부에서만 접근가능.(파생클래스도 접근불가)



멤버에 접근 한정자가 명시되어 있지 않으면 암시적으로 private으로 지정된다.

아래는 protected접근자에 대한 예제이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using System;
 
namespace AccessModifier
{
    class WaterHeater
    {
        int a;
        protected int temperature;
 
        public void SetTemperature(int temperature)
        // 변수가 protected이므로 public메소드로 접근. 
        
        {
            if (temperature < -5 || temperature > 42// -5~42사이의 값을 받음
            {
                throw new Exception("Out of temperature range");
                // 값이 범위를 벗어나면 위의 Exception문구를 출력
            }
 
            this.temperature = temperature;
        }
 
        internal void TurnOnWater()
        {
            Console.WriteLine("Turn on water : {0}", temperature);
        }
    }
 
    class MainApp
    {
        static void Main(string[] args)
        {
            try
            {
                WaterHeater heater = new WaterHeater();
                heater.SetTemperature(20);
                heater.TurnOnWater();
 
                heater.SetTemperature(-2);
                heater.TurnOnWater();
 
                heater.SetTemperature(50);
                // try~catch문을 쓰지않으면 컴파일시 처리되지않은 예외가 뜸
                heater.TurnOnWater();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}
cs

Turn on water : 20
Turn on water : -2
Out of temperature range

실행결과 : http://ideone.com/CgGv4G



c#에서의 상속


상속(Inheritance)은 부모(기반) 클래스의 멤버를 자식(파생) 클래스가 물려받는것이다.


기반클래스 -> 파생클래스 또는 슈퍼클래스 -> 서브클래스

라고도 한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Base //기반 클래스
{
    //멤버 선언
 
    public void BaseMethod(){};
 }
 
class Derived : Base //기반 클래스 : 파생 클래스
{
    //기반 클래스의 모든 것을 상속 받음.
    //단, private으로 선언된 것 제외.
 
    public void DerivedMethod()
    {
        base.BaseMethod(); //base키워드를 통해 기반 클래스에 접근 가능.(this키워드는 자기 자신)
    }
}
cs


상속시 멤버의 접근 지정자는 아래와 같다. 

 - 기반클래스의 public 멤버는 파생클래스에서도 public

 - 기반클래스의 protected 멤버는 파생클래스에서도 protected

 - 기반클래스의 private은 상속 불가


아래는 상속을 활용한 예제이다. 

실제적으로는 파생클라스가 기반클래스의 개념들을 물려받아 더 넓은 개념을 가지게 된다.


(참고 예제 : http://rintiantta.blog.me/40113370865)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace food
{
    class Food
    {
        public void Maked()
        {
            Console.WriteLine("(만들어짐)");
        }
        public void Selled()
        {
            Console.WriteLine("(팔림)");
        }
        public void Eatted()
        {
            Console.WriteLine("(먹힘)");
        }
    }
 
    class Pizza : Food
    {
        public string TypeOfPizza;
    }
    class Chiecken : Food
    {
        public string TypeOfChicken;
    }
    class Program
    {
        static void Main(string[] args)
        {
            Pizza pizza = new Pizza();
            Chiecken chinnim = new Chiecken();
            
            pizza.TypeOfPizza = "포테이토 피자";
            Console.WriteLine("{0}", pizza.TypeOfPizza);
            pizza.Maked();
            pizza.Selled();
            pizza.Eatted();
 
            chinnim.TypeOfChicken = "갈릭 치킨";
            Console.WriteLine("{0}", chinnim.TypeOfChicken);
            chinnim.Maked();
            chinnim.Selled();
            chinnim.Eatted();
        }
    }
}
cs

Output : (http://ideone.com/fDrY8D)


포테이토 피자
(만들어짐)
(팔림)
(먹힘)
갈릭 치킨
(만들어짐)
(팔림)
(먹힘)


음식은 만들어지고 팔리고 먹힌다는 공통속성을 가지고 있다. 

위와같이 "상속"을 통해 기반 클래스의 코드를 재사용하거나, 자식 클래스에서 기반클래스를 바탕으로 클래스를 확장할 수 있다.



'Study > C#' 카테고리의 다른 글

c# 복습  (0) 2017.03.31
headfirst c#-wpf  (0) 2016.11.19
5/27 업무일지 c#학생성적관리(콘솔)  (0) 2016.05.27
c# 클래스 복습2  (0) 2016.05.23
2016-05-20-C#복습  (0) 2016.05.20

+ Recent posts