2013년 1월 29일 화요일

헤드퍼스트 OOAD 들어가기 전 워밍업 (상속, 다형성)

일단 아래 그림을 보자.


두 클래스를 표현한 다이어그램이 있다.

부모가 자식에게 내리 사랑이니 화살표가 잘못된거 아니냐고 따질수도 있는데.

원래 표기법이 이렇다고한다 -0- 

자식이 부모에게 속한다고 표현을... 하여간 이리 아시고

자~ 이걸 소스로 표현해보자 (자바로 설명하는 이유는.... 책이 자바로 설명되어 있으니깐!)

pulbic class Jet extends Airplane {
   private static final int MULTIPLIER = 2;
   public Jet() {
      super()
   }
   public void setSpeed(int speed) {
      super.setSpeed(speed * MULTIPLIER);
   }
   public void accelerate() {
      super.setSpeed(getSpeed() * 2);
   }
}

라고 표현을 했다. 

extends b 는 a가 b를 상속 받겠다는 뜻이다.

super() 는 클래스가 상속한 클래스를 가르킨다. 
즉, Jet의 슈퍼 클래스인 Airplane 의 생성자를 호출하겠다는 뜻이다.

1줄 요약: 상속은 다른 클래스를 기반으로 클래스를 만들게 하고, 중복되는 코드를 피할 수 있게 하는 것.

-다형성 이란?-

다형성 역시 아까  윗 그림을 통해 설명할 수 있다. 위로 올리기 귀찮으니 다시 올린다.


다형성은 상속과 관련이 있다. 한클래스가 다른 클래스를 상속하면, 

다형성은 서브 클래스(Jet)가 슈퍼클래스(Airplane)를 대신할 수 있도록 허용한 것이다.

즉, 코드로 표현하자면.....

Airplane plane = new Airplane();  을 

Airplane plane = new Jet(); 로 표현할 수 있다는 것이닷!!

그럼 다형성을 쓰는 이유가 뭘까??

만약 비행기라는 커다란 클래스가 있다면 비행기에는 필수적인 요소가 들어있다.
하지만 세세하게는 없다는 것이다.
하늘을 난다는 것은 같지만 로켓에는 날개가 없고, 아이언맨도 날지만 날개가 없다. 
쓰는 연료도 다르고, 탑승객 수도 다르다.
이런 세세하고 디테일한 모습은 서브클래스를 만들어서 추가를 하면 되는 것이다.
애초에 비행기라는 슈퍼클래스를 이어 받았으니 코드 중복을 막을 수 있다.

상속과 다형성을 쓰는 이유 = 코드 중복을 막자!! 









2013년 1월 27일 일요일

헤드퍼스트 OOAD 들어가기 전 워밍업(UML)

워밍업이라곤 하지만 1강 들어가보니

객체지향이 생소한 놈들은 부록2로 가라는 책님의 말씀에 부록2로 이동해보니

객체지향으로 말하기 라는 항목이 있네~ 이걸 연재해보겠음


뭐를 공부할까 하다가 결론 냈음

결론은 OOAD 임 ^^

자료구조를 먼저하려다가.... 이 책을 먼저 샀기에 이걸 먼저 공부하며 공부한 내용을 올리겠음~

OOAD란??

Object-Oriented Analysis & Design

겍체지향 분석과 디자인? 정도 되겠습돠~

C하고 나서 왠 갑자기 뜬금없이 객체지향이냐?

라고 한다면.......

걍!!


2013년 1월 26일 토요일

후아~~ 이제야 C 정리 헉헉

다음은 뭐를 정리할 지 생각 중~~

아마도 JSP나 자료구조가 될 듯??

C 언어 핵심 정리 -스레드 편-


  1. 스레드를 사용하면 한 프로세스가 한꺼번에 여러 가지 일을 할 수 있음
  2. 스레드는 경량 프로세스 임
  3. pthread(포직스 스레드)는 스레드 라이브러리
  4. pthrread_create()는 함수를 실행하는 스레드를 생성
  5. pthrread_join()은 스레드가 종료할 때가지 기다림
  6. 스레드는 전역 변수를 공유
  7. 두 스레드가 동시에 한 변수를 읽고 쓰면 결과를 예측 불가
  8. 뮤텍스는 공유 데이터를 보호하기 위한 락
  9. pthread_mutex_lock() 는 뮤텍스에 락을 검
  10. pthread_mutex_unlock() 는 뮤텍스에 건 락을 해제

C 언어 핵심 정리 -소켓과 네트워킹편-


  1. 텔넷은 간단한 네트워크 클라이언트
  2. socket() 함수로 소켓을 생성
  3. 서버 블랍(BLAB) 
  4.  B(bind) - 바인딩, L(listen) - 듣기, A(accept) - 접수, B(begin) - 대화시
  5. fork()로 한꺼번에 여러 클라이언트를 처리
  6. DNS = 도메인 이름 시스템
  7. getaddrinfo()는 도메인 이름에 대한 주소를 찾음

C언어 핵심 정리 -프로세스와 통신 편-


  1. system()은 터미널에서 명령을 입력한 것 처럼 문자열을 실행
  2. fork() 는 현재 프로세스를 복제
  3. fork() 와 exec()로 자식 프로세스를 생성
  4. 프로세스들은 파이프로 통신
  5. pipe()는 통신 파이프를 생성
  6. exit()는 프로그램을 바로 종료
  7. waitpid()는 프로세스가 종료할 때까지 가다림
  8. filno() 는 디스크립터 번호를 반환
  9. dup2()는 데이터 스트림을 복제
  10. 시그널은 운영체제가 보내는 메시지
  11. sigaction()은 시그널을 직접 처리
  12. 프로그램은 raise() 로 자신에게 시그널을 보낼 수 있음
  13. alarm() 은 지정한 시간 후에 SIGALRM 시그널을 보냄
  14. kill 명령은 시그널을 보냄
  15. 단순한 프로세스는 한번에 한 가지 일만 함

C언어 핵심 정리 -정적 라이브러리, 동적 라이브러리 편-


  1. #include<>는 /usr/include 와 같은 표준 디렉토리를 찾음
  2. -L <라이브러리 경로>는 디렉토리를 표준 라이브러리 디렉토리에 추가
  3. -I <라이브러리 이름> 은 /usr/lib와 같은 표준 디렉토리의 파일에 링크
  4. -I <인클루드 경로>는 디렉토리를 표준 인클루드 디렉토리에 추가
  5. ar 명령은 오브젝트 파일의 라이브러리 아카이브를 생성
  6. 라이브러리 아카이브는 lib<라이브러리 이름>.a 형태의 이름을 가짐
  7. 라이브러리 아카이브는 정적으로 링크
  8. gcc -shared 는 오브젝트 파일을 동적 라이브러리로 변환
  9. 동적 라이브러리는 실행시에 링크
  10. 동적 라이브러리는 운영체제에 따라 이름이 다름
  11. 동적 라이브러리는 .so, .dylib, .dll, .dll.a 확장자를 가질 수 있음

C언 핵심 정리 -고급 함수 편-

-고급 함수-

  1. 함수 포인터를 사용하면 함수를 데이터처럼 전달할 수 있음
  2. 함수 포인터는 *와 &연산자가 필요 없는 유일한 포인터지만, 원하면 사용가능
  3. 모든 함수의 이름은 함수에 대한 포인터
  4. qsort()는 배열을 정려
  5. 모든 정렬 함수는 비교 함수에 대한 포인터를 필요
  6. 비교 함수는 두 데이터의 순서를 결정
  7. 함수 포인터의 배열을 사용하면 데이터형에 따라 다른 함수를 실행
  8. 인자의 개수가 바뀔 수 있는 함수를 "가변 인자 함수"라고 함
  9. stdarg.h를 사용하면 가변 인자 함수를 만들 수 있음

C언어 핵심 정리 -데이터구조, 동적메모리 편-

-데이터 구조-

  1. 동적 데이터 구조는 재귀적 구조체를 사용
  2. 재귀적 구조체는 자신과 비슷한 데이터에 대한 포인터를 한개 이상 갖고 있음
  3. 연결리스트는 동적 데이터 구조이
  4. 연결 리스트 안에 데이터를 쉽게 삽입할 수 있음
  5. 연결 리스트는 배열보다 확장하기 쉬움

-동적 메모리-

  1. 스택은 지역 변수를 저장하기 위해 사용
  2. 스택과 달리 힙 메모리는 자동으로 해체되지 않음
  3. malloc()는 힙에 메모리를 할당
  4. free()는 힙에 있는 메모리를 해제
  5. strdup()는 문자열을 힙에 복사
  6. 할당된 메모리에 접근할 수 없을 때 메모리 누수가 발생
  7. valgrind로 메모리 누수를 찾아낼 수 있음.

C언어 핵심 정리 -구조체,공용체,비트필드 편-

-구조체-

  1. 구조체는 데이터 형을 한데 묶습니다.
  2. 구조체 필드는 점(.)표기법으로 읽을 수 있습니다
  3. 배열과 같은 표기법으로 구조체를 초기화 할 수 있습니다
  4. -> 연산자를 사용하면 구조체 포인터의 필드를 쉽게 접근할 수 있음
  5. typedef로 데이터형의 별명을 만들 수 있음
  6. 구조체와 공용체의 필드이름을 지정해 초기화 할 수 있음

-공용체와 비트필드-

  1. 공용체는 여러형의 데이터를 한 곳에 보관할 수 있음
  2. 열거형으로 여러 기호를 만들 수 있음
  3. 비트 필드를 사용하면 구조체에 저장된 데이터를 비트 단위로 제어 가능

C언어 핵심 정리 -데이터형, 여러파일-

-데이터 형-

  1. char도 숫자형
  2. 아주 큰 정수에는 long형
  3. 작은 정수에는 short형
  4. 일반적인 정수에는 int형
  5. int형은 컴퓨터의 따라 크기가 달라짐
  6. 일반적인 실수에는 float형
  7. 정교한 실수에는 double형

-여러 파일-

  1. 함수 선언과 정의를 분리
  2. 선언은 헤더 파일에 넣기~
  3. #include<>는 라이브러리 헤더 파일에 사용
  4. #include " "는 지역 헤더 파일에 사용
  5. 오브젝트 코그를 파일에 저장하면 빨리 컴파일 할 수 있음
  6. make 로 컴파일 하긔~

C언어 핵심 정리 -데이터 스트림 편-


  1. printf()나 scanf()같은 C 함수는 표준 출력 및 표준 입력과 통신 합니다
  2. 표준 입력은 기본적으로 키보드를 읽습니다.
  3. 표준 에러는 에러 메시지를 출력하기 위해 따로 만든 출력 스트림입니다
  4. fopen("<파일이름>", mode)로 직접 데이터 스트림을 만들수 있음
  5. 표준 출력은 기본적으로 화면에 출려
  6. 리다이렉션으로 표준 입력, 출력, 에러가 연결된 스트림으로 바꿀수 있음
  7. fprintf(stderr, ...)으로 표준 에러에 출력할 수 있습니다.
  8. mode에서 쓸 때는 "w", 읽을 때는 "r", 추가할 때는 "a"로 열기 모드를 지정
  9. 명령행 인자는 문자열 포인터의 배열로 main()함수에 전달
  10. getopt() 함수를 사용하면 옵션을 쉽게 읽을 수 있음

C 언어 핵심 정리 -문자열-


  1. 문자열 상수는 읽기 전용 메모리에 저장됨
  2. 문자열의 배열은 배열의 배열
  3. strstr(a,b)는 문자열 a안에 있는 문자열 b의 위치를 반환
  4. strcat()는 두 문자열을 하나로 합침
  5. strcpy()는 문자열을 다른 배열에 복사
  6. string.h 헤더 파일은 유용한 문자열 함수들을 가지고 있음
  7. char string[..][..]로 배열의 배열을 만듬
  8. strcmp() 는 두 문자열을 비교
  9. strchr() 은 문자열 안에 있는 문자의 위치를 반환함
  10. strlen()은 문자열의 길이를 반환

C언어 핵심 정리 -포인터와 메모리


  1. scanf("%i", &x)로 사용자가 x에 직접 숫자를 입력할 수 있음
  2. 문자 포인터 변수x는 char* x로 선언
  3. 배열을 문자열로 초기화 하면, 문자열을 배열에 복사
  4. &x를 'x에 대한 포인터'라고 함
  5. &x는 x의 주소를 반환
  6. 배열 변수를 포인터로 사용할수 있음
  7. *a로 a번지에 있는 내용을 읽을 수 있음
  8. fgets(buf, size, stdin)로 간단히 문장을 입력
  9. 지역변수는 스택에 저장 됨

C언어 핵심 정리 -기초편-


    1. 단순문은 명령입니다
    2. 블럭문은 중괄호{}로 에워 쌉니다
    3. if문은 조건이 참일 때 실행됩니다.
    4. switch 문은 사용하면 한변수를 여러 값과 효율적으로 비교가능
    5. 논리 연산자(&&과 ||)로 조건을 결합
    6. 모든 프로그램에는 main()함수가 있어야 함
    7. #include는 입출력 코드와 같은 외부 코드를 연결
    8. 소스 파일은 .c 확장자를 가짐
    9. c 프로그램을 실행하려면 컴파일 해야함
    10. gcc는 가장 인기 있는 컴파일러
    11. 명령행에 && 연산자 사용하면 컴파일이 성공했을 때만 실행
    12. -o 는 컴파일된 파일 이름을 지정
    13. i++ 은 i에 1 더함, i--는 i에 1 뺌
    14. while는 조건이 참이면 루프를 반복
    15. do-while 는 코드를 적어도 한번은 실행
    16. for문을 사용하면 루프를 간략히 작성

부록 1 // 2. 전처리기, 3 static 키워드, 4.sizeof 키워드

2. 전처리기 지시자

#include <stdio.h> 이게 전처리기 지시자

전처리기 헤더 파일의 내용을 파일 안에 넣는거~
언제나 소스코드 제일 앞에 오고 #으로 시작

#define 는 매크로 만드는 지시자
매크로는 프로그램을 실행하는 동안 값이 바뀌지 않기 때문에 변수가 아니고
매크로는 프로그램이 컴파일 되기 전에 바뀜.

3. static 키워드

예제)

int count = 0;
int counter()
{
     return ++count; //호출될 때 마다 값을 증가 시킴
}

이 코드의 문제는 count라는 전역 변수를 사용함.
어떤 함수도 사용해서 값을 바꿀 수가 있음.
전역 변수를 특정 함수나 파일만 사용할 수 있는 변수를 만드는 법~!

int counter()
{
     static int count = 0;
     return ++count;
}

static 키워드를 사용하면 변수를 전역 메모리에 보관하고 다른 함수가 접근하면 에러 발생

함수 앞에 static를 사용하면 같은 소스코드 안에 있는 코드만 이 함수를 사용가능


1줄 요약: static 키워드는 코드의 범위를 통제~

4. sizeof  키워드

어떤 범위를 알고 싶을 때 사용.

예제)

#include <stdio.h>
#include <limits.h>

int main()
{
   printf("이 컴퓨터에서 int 형은 %lu바이트를 차지 합니다. \n", sizeof(int));
   printf("그리고 int형은  %i에서 %i까지 저장할 수 있습니다. \n", INT_MIN, INT_MAX);
   printf("그리고 short형은  %i에서 %i까지 저장할 수 있습니다. \n", SHRT_MIN, SHRT_MAX);
   return 0;
}

매크로 이름은 INT(int), LONG(long), CHAR(char), FLT(float), DBL(double)
에 _MAX 나 _MIN을 붙이면 됨.


















부록 1 중요한 10가지 이야기 중 1. 연산자

1. 연산자


증가과 감소
++i
i의 값을 1 증가시키고, 새 값을 반환

i++
i의 값을 1 증가시키고 이전 값을 반환

--i
i의 값을 1 감소시키고, 새 값을 반환

i--
i의 값을 1 감소시키고, 이전 값을 반환

1줄 요약 ++ -- 가 앞에 있으면 새 값을 반환하고, 뒤에 있으면 원래 값은 그대로


3항 연산자
어떤 값이 참일 때는 1번을 거짓일 때는 2번을 선택하고 싶다면??

(x == 1) ? 2 : 3

이라고 썼다면 x == 1이 참이면 2, 거짓이면 3

비트 조작
~a      a에 있는 각 비트의 반대값을 반환합니다.
a&b     a와 b의 각 비트의 논리곱을 반환합니다.
a|b     a와 b의 각 비트의 논리합을 반환합니다.
a^b     a와 b의 각 비트의 XOR을 반환합니다.
<<     모든 비트를 오른쪽 인자의 수만큼 왼쪽으로 이동
>>     모든 비트를 오른쪽 인자의 수만큼 오른쪽으로 이동

콤마를 사용해 수식을 분리
루프를 돌 때두 개 이상의 연산을 하는법

for(i = 0; i < 10; i++, j++) 콤마(,)로 구분~

12강 보충 - 스레드를 제어해 보장~


#include <stdio.h>
#include <pthread.h>

int beers = 2000000;

void* drink_lots(void* a)
{
int i;
for (i = 0; i < 100000; i++) {
beers = beers - 1;
}
return NULL;
}

int main()
{
pthread_t threads[20];
int t;
printf("벽에 있는 맥주병 개수: %i\n맥주병 개수: %i\n", beers, beers);
for (t = 0; t < 20; t++) {
pthread_create(&threads[t], NULL, drink_lots, NULL);
}

void* result;
for (t = 0; t < 20; t ++) {
pthread_join(threads[t], &result);
}

printf("벽에 %i 병의 맥주가 남아있습니다.\n", beers);
return 0;
}

200 만개의 병을 20개의 쓰레드를 이용하여 10만개씩 동시에 세는 프로그램임.

pthread_create 로 스레드 생성하고, pthread_join로 종료할 때가지 기다리고...

하지만 위의 소스를 실행하면 서로 공유 변수를 쓰기 때문에 계산이 개판이 됨.

고로 스레드를 통제하는 뮤텍스를 이용해 봅시당~


#include <stdio.h>
#include <pthread.h>

int beers = 2000000;
pthread_mutex_t beers_lock = PTHREAD_MUTEX_INITIALIZER;

void* drink_lots(void* a)
{
int i;
pthread_mutex_lock(&beers_lock);
for (i = 0; i < 100000; i++) {
beers = beers - 1;
}
pthread_mutex_unlock(&beers_lock);
printf("맥주 = %i\n", beers);
return NULL;
}

int main()
{
pthread_t threads[20];
int t;
printf("벽에 있는 맥주병 개수: %i\n맥주병 개수: %i\n", beers, beers);
for (t = 0; t < 20; t++) {
pthread_create(&threads[t], NULL, drink_lots, NULL);
}

void* result;
for (t = 0; t < 20; t ++) {
pthread_join(threads[t], &result);
}

printf("벽에 %i 병의 맥주가 남아있습니다.\n", beers);
return 0;
}


굵게 표시한 부분이 스레드를 통제하는 함수(라기보단 전처리기) 입니다.
lock 와 unlock 로 나뉘는데요~
이걸 반복문 전후로 사용법이 있고......


for (i = 0; i < 100000; i++)
{
pthread_mutex_lock(&beers_lock);
beers = beers - 1;
pthread_mutex_unlock(&beers_lock);
}

반복문 안에서 할수도 있습니다.
물론 둘의 과정은 틀리지만 결과는 같습니다.
어느 것이 좋다고는 말할 수는 없지만 최소한 잘못된 참조로 계산이 틀리지는 않습니다.

헤드 퍼스트 C 12강 (thread)


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h> //포직스 스레드 라이브러리 사용

void error(char* msg)
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(1);
}

void* does_not(void *a)
{
int i = 0;
for (i = 0; i < 5; i++) {
sleep(1);
puts("Does not!");
}
return NULL;
}

void* does_too(void *a)
{
int i = 0;
for (i = 0; i < 5; i++) {
sleep(1);
puts("Does too!");
}
return NULL;
}

int main()
{
pthread_t t0;
pthread_t t1;
if (pthread_create(&t0, NULL, does_not, NULL) == -1)
error("t0 스레드를 생성할 수 없습니다.");
if (pthread_create(&t1, NULL, does_too, NULL) == -1)
error("t1 스레드를 생성할 수 없습니다.");

void* result;
if (pthread_join(t0, &result) == -1)
error("t0 스레드를 종료할 수 없습니다.");
if (pthread_join(t1, &result) == -1)
error("t1 스레드를 종료할 수 없습니다.");

return 0;
}

------------------ 이 코드는 스레드가 충동하는 문제가 있음 -----------

2013년 1월 23일 수요일

헤드 퍼스트 C 11강 (노크노크 서버)


#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>

void error(char* msg)
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(1);
}

int open_listener_socket()
{
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s == -1)
error("소켓을 열 수 없습니다.");

return s;
}

void bind_to_port(int socket, int port)
{
struct sockaddr_in name;
name.sin_family = PF_INET;
name.sin_port = (in_port_t)htons(30000);
name.sin_addr.s_addr = htonl(INADDR_ANY);
int reuse = 1;
if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(int)) == -1)
error("소켓에 재사용 옵션을 설정할 수 없습니다.");
int c = bind(socket, (struct sockaddr*)&name, sizeof(name));
if (c == -1)
error("소켓에 바인딩할 수 없습니다.");
}

int catch_signal(int sig, void (*handler)(int))
{
        struct sigaction action;
        action.sa_handler = handler;
        sigemptyset(&action.sa_mask);
        action.sa_flags = 0;
        return sigaction(sig, &action, NULL);
}

int say(int socket, char* s)
{
int result = send(socket, s, strlen(s), 0);
if (result == -1)
fprintf(stderr, "%s: %s\n", "클라이언트에 메시지를 보낼 수 없습니다.", strerror(errno));
return result;
}

int listener_d;

void handle_shutdown(int sig)
{
if (listener_d)
close(listener_d);

fprintf(stderr, "안녕!\n");
exit(0);
}

int read_in(int socket, char* buf, int len)
{
char* s = buf;
int slen = len;
int c = recv(socket, s, slen, 0);
while ( (c > 0) && (s[c-1] != '\n')) {
s += c; slen -= c;
c = recv(socket, s, slen, 0);
}
if ( c < 0 )
return c;
else if (c == 0)
buf[0] = '\0';
else
s[c-1] = '\0';
return len - slen;
}

int main(int argc, char* argv[])
{
if (catch_signal(SIGINT, handle_shutdown) == -1)
error("인터럽트 처리기를 설정할 수 없습니다.");

listener_d = open_listener_socket();
bind_to_port(listener_d, 30000);
if (listen(listener_d, 10) == -1)
error("들을 수 없습니다.");

struct sockaddr_storage client_addr;
unsigned int address_size = sizeof(client_addr);
puts("연결을 기다립니다.");
char buf[255];
while(1) {
int connect_d = accept(listener_d, (struct sockaddr*)&client_addr, &address_size);
if (connect_d == -1)
error("두 번째 소켓을 열 수 없습니다.");
if (say(connect_d, "인터넷 노크노크 프로토콜 서버\r\n버전 1.0\r\nKnock Knock!\r\n") != -1) {
read_in(connect_d, buf, sizeof(buf));
if (strncasecmp("Who's there?", buf, 12))
say(connect_d, "'Who's there?'라고 질문했어야 합니다!");
else {
if (say(connect_d, "Oscar\r\n") != -1) {
read_in(connect_d, buf,sizeof(buf));
if (strncasecmp("Oscar who?", buf, 10))
say(connect_d, "'Oscar who?'라고 질문했어야 합니다!");
else
say(connect_d, "Oscar silly question, you get a silly answer.\r\n");
}
}
}
close(connect_d);
}
return 0;
}

헤드 퍼스트 C 11강 (socket)


#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>

void error(char* msg)
{
        fprintf(stderr, "%s: %s\n", msg, strerror(errno));
        exit(1);
}

int main(int argc, char* argv[])
{
char* advice[] = {
"조금만 드세요.\r\n",
"꽉 끼는 청바지를 입으세요. 뚱뚱해 보이지는 않을 겁니다.\r\n",
"한 마디만 하겠습니다. 옳지 않아요.\r\n",
"오늘만이라도 솔직해지세요. 직장 상사에게 '진정' 생각하고 있는 걸 말하세요.\r\n",
"그 머리 모양은 아니지 싶습니다.\r\n"
};
int listener_d = socket(PF_INET, SOCK_STREAM, 0);

struct sockaddr_in name;
name.sin_family = PF_INET;
name.sin_port = (in_port_t)htons(30000);
name.sin_addr.s_addr = htonl(INADDR_ANY);
if ( bind(listener_d, (struct sockaddr*)&name, sizeof(name)) == -1)
error("포트에 바인딩할 수 없습니다.");
listen(listener_d, 10);
puts("연결을 기다립니다.");
while (1) {
struct sockaddr_storage client_addr;
unsigned int address_size = sizeof(client_addr);
int connect_d = accept(listener_d, (struct sockaddr*)&client_addr, &address_size);
char* msg = advice[rand() % 5];
send(connect_d, msg, strlen(msg), 0);
close(connect_d);
}
return 0;
}




gcc 컴파일러로 해야함 vs로 할 시 헤더 파일이 틀려서 안됨.

헤드 퍼스트 C 11강, 12강

은 귀찮아서 생략한다 -_-

헤드 퍼스트 C 10강


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <signal.h>

int score = 0;

void end_game(int sig)
{
printf("\n최종 점수: %i\n", score);
exit(0);
}

int catch_signal(int sig, void (*handler)(int))
{
struct sigaction action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
return sigaction(sig, &action, NULL);
}

void times_up(int sig)
{
puts("\n시간 초과!");
raise(SIGINT);
}

void error(char* msg)
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(1);
}

int main()
{
catch_signal(SIGALRM, times_up);
catch_signal(SIGINT, end_game);
srandom(time(0));

while(1) {
int a = random() % 11;
int b = random() % 11;
char txt[4];
alarm(5);
printf("\n%i 곱하기 %i는? ", a, b);
fgets(txt, 4, stdin);
int answer = atoi(txt);
if (answer == a * b)
score++;
else
printf("\n틀렸습니다! 점수: %i\n", score);
}

return 0;
}

헤드 퍼스트 C 9강 (log)


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

char* now()
{
time_t t;
time(&t);
return asctime(localtime(&t));
}

/* 주 제어판 프로그램.
   경비원의 점검 시각을 기록한다. */

int main()
{
char comment[80];
char cmd[120];

fgets(comment, 80, stdin);
sprintf(cmd, "echo '%s %s' >> reports.log", comment, now());

system(cmd);
return 0;
}

헤드 퍼스트 C 7강 (Qsort)


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//숫자 정렬(오름차순)
int compare_scores(const void* score_a, const void* score_b)
{
int a = *(int*)score_a;
int b = *(int*)score_b;
return a - b;
}

//숫자 정렬(내림차순)
int compare_scores_desc(const void* score_a, const void* score_b)
{
int a = *(int*)score_a;
int b = *(int*)score_b;
return b - a;
}

typedef struct {
int width;
int height;
} rectangle;

//사각형 크기 정렬(오름차순)
int compare_areas(const void* a, const void* b)
{
rectangle* ra = (rectangle*)a;
rectangle* rb = (rectangle*)b;
int area_a = (ra->width * ra->height);
int area_b = (rb->width * rb->height);
return area_a - area_b;
}

//글씨 정렬(오름차순)
int compare_names(const void* a, const void* b)
{
char** sa = (char**)a;
char** sb = (char**)b;
return strcmp(*sa, *sb);
}

//사각형 크기 정렬(내림차순)
int compare_areas_desc(const void* a, const void* b)
{
return compare_areas(b, a);
}

//이름 정렬 (내림차순)
int compare_names_desc(const void* a, const void* b)
{
return compare_names(b, a);
}

int main()
{
//선언부
int scores[] = { 543, 323, 32, 554, 11, 3, 112 };
int i;
char* names[] = { "카렌", "마크", "브렛", "몰리" };

//구현부
qsort(scores, 7, sizeof(int), compare_scores_desc);
puts("scores를 정렬한 결과:");
for (i=0; i<7; i++) {
printf("점수 = %i\n", scores[i]);
}


qsort(names, 4, sizeof(char*), compare_names);
puts("이름을 정렬한 결과:");
for (i=0; i<4; i++) {
printf("%s\n", names[i]);
}

return 0;
}

헤드 퍼스트 C 7강(find)


#include <stdio.h>
#include <string.h>

int NUM_ADS = 7;
char* ADS[] = {
"윌리엄: 독신흑인남 유머 감각 스포츠, TV, 외식 좋아함",
"매트: 독신백인남 비흡연 미술, 영화, 연극 좋아함",
"루이스: 독신라틴남 비음주 독서, 연극, 미술 좋아함",
"마이크: 이혼백인남 음주흡연 트럭, 스포츠, 비버 좋아함",
"피터: 독신아시아남 체스, 운동, 미술 좋아함",
"조쉬: 독신유태인남 스포츠, 영화, 연극 좋아함",
"제드: 이혼흑인남 연극, 독서, 외식 좋아함"
};

void find()
{
int i;
puts("검색 결과:");
puts("------------------------");
for (i = 0; i < NUM_ADS; i++) {
if ( strstr(ADS[i], "스포츠")
&& !strstr(ADS[i], "비버")) {
printf("%s\n", ADS[i]);
}
}
puts("------------------------");
}

int main()
{
find();

return 0;
}

헤드 퍼스트 C 5강(union_enum)


#include <stdio.h>

typedef enum {
COUNT, POUNDS, PINTS
} unit_of_measure;

typedef union  {
short count;
float weight;
float volume;
} quantity;

typedef struct {
const char *name;
const char *country;
quantity amount;
unit_of_measure units;
} fruit_order;

void display(fruit_order order)
{
printf("이 주문에는 ");

if (order.units == PINTS)
printf("%2.2f 파인트의 %s가 있습니다.\n", order.amount.volume, order.name);
else if (order.units == POUNDS)
printf("%2.2f 파운드의 %s가 있습니다.\n", order.amount.weight, order.name);
else
printf("%i개의 %s가 있습니다.\n", order.amount.count, order.name);
}

int main()
{
fruit_order apples = {"사과", "영국", 114 ,COUNT};
fruit_order strawberries = {"딸기", "스페인", 17.6, POUNDS}; //3번째 값을 넣는 법을 모르겠음.
fruit_order oj = {"오렌지 주스", "미국",  10.5, PINTS};

display(apples);
display(strawberries);
display(oj);
return 0;
}

헤드 퍼스트 C 5강 (struct)


#include <stdio.h>

typedef struct fish{ //구조체 이름 fish
const char *name;
const char *species;
int teeth;
int age;
}turtle; //별명 turtle

void catalog(turtle f) //별명으로 접근
{
printf("%s는  %s종이며, 이빨이 %i개이고, %i살 입니다.\n", f.name, f.species, f.teeth, f.age);
}

void label (struct fish f) //구조체 이름으로 접근
{
printf("이름 : %s\n", f.name);
printf("종 : %s\n", f.species);
printf("이빨 수 : %i\n", f.teeth);
printf("나이 : %i\n", f.age);
}

void happy_birthday(turtle *t) //포인터로 받음
{
(*t).age = (*t).age + 1; //포인터 주소를 통한 연산
printf("생일 축하해 %s! 이제 %i살이 되었네!\n", t->name, t->age); // -> 이 방법도 있음
}

int main()
{
turtle snappy = {"꼬북이", "장수거북", 15, 99};
happy_birthday(&snappy); //포인터 주소 읽기 &
printf("%s의 나이는 이제 %i살 입니다.\n", snappy.name, snappy.age);
catalog(snappy);
label(snappy);
return 0;
}

헤드 퍼스트 C 4강


#include <stdio.h>
#include "totaller_fix.h"

float total = 0.0;
short count = 0;
/* 세금이 6%. 내 에이전트가 떼어가는 돈보다 훨씬 적네... */
short tax_percent = 6;

int main()
{
/* 이봐. 난 발 킬머와 영화 배역을 놓고 경쟁했었다고 */
float val;
printf("항목 가격: ");
while(scanf("%f", &val) == 1) {
printf("지금까지 합산: %.2f\n", add_with_tax(val));
printf("항목 가격: ");
}

printf("\n총계: %.2f\n", total);
printf("\n총 항목수: %hi\n", count);

return 0;
}

float add_with_tax(float f)
{
float tax_rate = 1 + tax_percent / 100.0;
/* 팁은 안주나? 내 목소리는 공짜가 아니라고 */
total = total + (f * tax_rate);
count = count + 1;
return total;
}

헤드 퍼스트 C 3강


#include <stdio.h>

int main()
{
float latitude; //위도
float longitude; //경도
char info[80];
int started = 0;
puts ("data=[");
while (scanf("%f, %f, %79[^\n]", &latitude, &longitude, info) == 3) {
if(started)
printf(",\n");
else
started = 1;
if((latitude < -90) || (latitude > 90)) {
fprintf(stderr, "위도에 %f 들어간거 보소 -_- 꺼져!! \n", latitude);
return 2;
}
if((longitude < -180) || (longitude > 180)) {
fprintf(stderr, "경도에 %f 들어간거 보소 -_- 닭이냐?! \n", longitude);
return 2;
}
printf("{latitude : %f, longitude: %f, info: '%s'}", latitude, longitude, info);
}
puts("\n]");

return 0;
}

헤드 퍼스트 C 3강


#include <stdio.h>

int main()
{
float latitude;
float longitude;
char info[80];

while (scanf("%f, %f, %79[^\n", &latitude, & longitude, info)==3)
if((latitude > 26)&&(latitude < 34))
if((longitude > -64)&&(longitude < -76))
printf("%f, %f, %s\n", latitude, longitude, info);

return 0;
}

헤드 퍼스트 C 2.5강


#include <stdio.h>
#include <string.h>

char tracks [][80] = {
"I left my heart in Harvard Med School",
"Newark, Newark - a wonderful town",
"Dancing with a Dork",
"From here to maternity",
"The girl from Iwo Jima",
};

void find_track(char search_for[])
{
int i;
for (i = 0; i < 5; i++)
{
if (strstr(tracks[i], search_for))
printf("찾은 노래 %i 곡: '%s'\n", i, tracks[i]);
}
}

int main()
{
char search_for[80];
printf("검색할 내용: ");
scanf("%79s", search_for);
search_for[strlen(search_for) -1 ] = '\0';
find_track(search_for);
return 0;
}

헤드 퍼스트 C 2강


#include <stdio.h>

int main()
{
char cards[] = "JQK";
char a_card = cards[2];
cards[2] = cards[1];
cards[1] = cards[0];
cards[0] = cards[2];
cards[2] = cards[1];
cards[1] = a_card;
puts(cards);

return 0;
}

헤드 퍼스트 C 1강


/*
액면가를 계산하는 프로그램.
이 코드는 베가스 공개 라이센스를 적용하여 공개합니다
*/

#include <stdlib.h>
#include <stdio.h>


int main()
{
char card_name[3];
int count = 0;
int val = 0;

while (card_name[0] != 'X') {
puts("카드 이름을 입력하세요: ");
scanf("%2s", card_name);
//switch 문 사용
switch(card_name[0]) {
case 'K':
case 'Q':
case 'J':
val = 10;
break;
case 'A':
val=11;
break;
case 'X':
continue;
default :
val = atoi(card_name);
if((val < 1) || (val > 11)) {
puts("미친 닭그네야!! 값을 이따위로 넣냐?? 쳐 맞을래??!!");
continue; //다시 루프를 돌자 ㄱㄱ
}
}
if((val > 2) && (val < 7)) {
count++;
} else if (val == 10) {
count--;
}
printf("현재 카운트 : %i\n", count);
}
return 0;
}