출처 - http://whdvy777.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-SQL%EB%AC%B8-%EA%B8%B0%EB%B3%B83-IN-LIKE-ESCAPE-NULL-NOT-ORDER-BY

 

<IN 조건문>

 

- 값의 특정 값 집합 확인

 

 

- 목록에 사용되는 문자 또는 날짜는 작은 따옴표(' ')로 묶어야 합니다.

 

 

 

<LIKE 조건문>

 

- %에는 문자가 오지 않거나 여러 개 올 수 있습니다.

- _ 에는 문자가 하나만 올 수 있습니다. 

 

 

 

 

 

 

<ESCAPE 옵션>

 

- 검색할 문자에 실제로 '%' 및 '_' 문자가 포함된 경우 ESCAPE 옵션을 사용하여 이스케이프 문자를 지정합니다.

 

 

 

 

 

<NULL 조건사용>

 

- is null

- is not null 

- null 값은 비교연산자로 확인할 수 없음.

 

 

 

 

<NOT 연산자>

 

 

 

 

 

 

<우선순위 규칙>

 

 

 계산 순서

연산자

1

 산술 연산자

2

 연결 연산자 ||

3

 비교 조건

4

 IS [NOT] NULL,  LIKE,  [NOT] IN

5

 [NOT]BETWEEN

6

 NOT 논리조건

7

 AND 논리조건

8

 OR 논리 조건

 

 

 

 

 

 

<ORDER BY 절>

 

- where 절 다음에 씀 (가장 마지막)

- ASC : 오름차순 (기본값)

- DESC : 내림차순

- ORDER BY 절에 열 '별칭'을 사용할 수 있습니다.

- 여러 열을 기준으로 정렬 가능 

 

출처 - http://hyeonstorage.tistory.com/289

 

* SQL 문장들의 종류


명령어 종류 

명령어 

설명 

데이터 조작어

(DML :  Data Manipulation Language

SELECT 

 데이터베이스에 들어 있는 데이터를 조회하거나 검색하기 위한 명령어를 말하는 것으로 RETRIEVE 라고도 한다.

INSERT

UPDATE

DELETE 

 데이터베이스의 테이블에 들어 있는 데이터에 변형을 가하는 종류의 명령어들을 말한다. 데이터 삽입, 수정, 삭제

 데이터 정의어

(DDL : Data Definition Language)

CREATE

ALTER

DROP

RENAME

TRUNCATE 

 테이블과 같은 데이터 구조를 정의하는데 사용되는 명령어들로 그러한 구조를 생성하거나 변경하거나 삭제하거나 이름을 바꾸는 데이터 구조와 관련된 명령어들을 DDL이라고 부른다.

데이터 제어어

(DCL : Data Control Language) 

GRANT

REVOKE 

 데이터베이스에 접근하고 객체들을 사용하도록 권한을 주고 회수하는 명령어를 DCL이라고 한다. 

트랜잭션 제어어

(TCL : Transaction Control Language)

COMMIT

ROLLBACK

SAVEPOINT 

 논리적인 작업의 단위를 묶어서 DML에 의해 조작된 결과를 작업단위(트랜잭션) 별로 제어하는 명령어를 말한다. 

 

출처 - http://one-p.tistory.com/entry/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4ERD

ERD(Entity Relationship Diagram)란?

- 계략적으로 데이터 및 데이터들의 관계를 표현한 도식화된 그림(Diagram)
- 분석가들은 조직의 데이터를 이해하고, 이를 응용시스템에 이용하고자 ERD를 작성
- 엔터티(Entity)란 데이터베이스에 저장할 정보의 주체 혹은 대상
- 엔터티의 예로는 고객, 학생, 부서, 계좌 등이 있음
- ERD에서 엔터티는 네모로 표시 함

ERD의 카디넬러티(Cardinality)
 

카디넬러티(Cardinality) : 엔터티들간의 수적 관계를 명시하는 표현

 

 

 


ERD의 예

- 우리 학교에는 학생들이 여러 과목을 수강할 수 있다.
- 한 과목을 여러 학생들이 수강한다.
- 학생들은 각각 한 개의 사물함을 소유하고, 여러 개의 교과서도 갖는다.

 

 

 


키(Key)의 이해

- 기본키(Primary key) : 다른 레코드와(Row) 자신의 레코드를 구별 시켜 주는 키 

 

   ex) 주민등록번호, 자신만이 가지는 고유한 것
- 외래키(Foreign key) : 다른 테이블과의 관계를 표시하는 키

 


데이터 무결성(Data Integrity)의 의미

- 데이터 무결성은 데이터의 정확성 또는 유효성을 의미
- 무결성 파괴의 예
   어떤 학생이 수강 신청을 하려고 했으나, 이 학생의 정보가 존재하지 않는다.
   어떤 학생이 학교를 그만 두었으나, 특정 과목 수강자 명단에 이 학생이 그대로 존재 함
- 일관된 데이터베이스 상태를 정의하는 규칙들을 묵시적 혹은 명시적으로 정의하여 무결성 유지
- 데이터베이스 보안 기능이 권한이 없는 사용자로부터 데이터베이스를 보호하기 위함이라면, 무결성은 권한이 있는 사용자로부터 데이터를
   보호하기 위 함

- 스키마 정의 시 무결성 제약조건을 정의하며, 한 번 정의된 조건은 향후 데이터베이스에 정보가 갱신될 경우 DBMS에 의해 검사가 이루어짐

데이터 무결성의 종류

도메인 제약조건(Domain Constraint)
 

- 각 애트리뷰트의 값이 지정된 데이터형으로 제한 됨
- 애트리뷰트의 기본값, 범위, NULL 허용 여부들도 제한 가능 

 



기본키 

 

제약조건(Primary key Constraint)

- 기본키의 경우 중복된 값 및 NULL 값이 허용 될 수 없음
- 기본키가 아니라도 UNIQUE 설정을 통해 중복 값 불허 가능

 


참조 무결성 제약조건(Referential Integrity Constraint)

- 두 데이터 간에 데이터의 결함을 없애는 제약조건

 

 

 
삽입

(Inset)시 무결성 유지

- 자식테이블에 새로운 레코드가 삽입 될 경우 외래키의 값은 부모테이블에 존재하는 값이거나 NILL 이어야 한다.

삭제(Delete)시 무결성 유지

- 부모테이블의 레코드를 삭제할 경우 자식테이블의 외래키가 참조 하고 있을 경우는 삭제 불가 이거나 연쇄(Cascade) 삭제(On Delete Cascade)

수정(Update)시 무결성 유지

- 자식테이블 레코드의 외래키를 수정할 경우 부모테이블의 해당 키에 존재하는 값 범위 내에서 수정가능 

http://program.egloos.com/1373351



-o
옵션: gcc에서 만들 실행 파일명을 정하는 것. 안지정하면 a.out
%gcc -o filter filter_driver.c define_stack.c global_var.c


-c 옵션 : 컴파일하지만 링크하지는 않는 다는 것을 의미
%gcc -c filter_driver.c


-D 옵션 : 소스코드의 #define 문과 같다. 심볼에 대한 값을 지정
% gcc -c -DDOC_FILE=\"info\" -DUSE_POLL filter_driver.c
첫 번째 -D 옵션은 DOC_FILE 을 info 라는 문자열로 대치한다는 것
두 번째 -D 옵션은 USE_POLL 심볼을 정의한다.


-U 옵션 : 외부에서 #undef ex_ -UDEBUG

-I 옵션 : 헤더파일이 위치한 디렉토리 지정
% gcc -c -I../headers filter_driver.c


-l 옵션 : 라이브러리를 지정. 파일명과 함께 붙여 쓴다.
% gcc -o plot main.o plot_line.o -lm
-lm 옵션은 수학 라이브러리를 포함한다는 것을 지정


-L 옵션 : 라이브러리 폴더를 찾아서 지정
% gcc -o plot -L/src/local/lib main.o plot_line.o -lm


-E 옵션 : 프로그램을 컴파일 하는 대신 전처리된 코드를 표준 출력으로 내보냄 <전처리>

-S 옵션 : 어셈블리 언어로 나온 결과를 저장 .c 대신 .s 가 붙는 파일을 만들어 낸다.<컴파일>

-c 옵션 : .o 로 끝나는 오브젝트 파일 생성 <어셈블>

 


[ C 언어 옵션 ]
-v 옵션 : (verbose) 컴파일러의 버전과 각 단계에서 실행하는 자세한 사항을 출력 (어떤 옵션으로 컴파일 하였는지)

-w 옵션 : 모든 경고 메시지가 나오지 않도록

-W 옵션 : 합법적이지만 다소 모호한 코딩에 대하여 부가적인 경고 메시지를 출력

-Wall 옵션 : 모호한 코딩에 대하여 훨씬 더 자세한 경고 메시지를 출력

 

 

 


[ 라이브러리 지정 옵션 ]

 

 

-static 옵션 : 공유 라이브러리가 아닌 정적 라이브러리와 링크

-shared 옵션 : 가능한 한 공유 라이브러리와 링크하고 공유 라이브러리가 없는 경우에는 정적 라이브러리와 링크

 

 

 


[ 디버깅, 프로파일링 옵션 ]

 

 

-p 옵션 : 프로그램을 prof 로 프로파일링 할 수 있도록 링크. mon.out 파일 생성됨. 프로그램 실행 통계 수치를 담고 있다.

출처 - http://www.devblog.kr/r/8y0gFPAvJ2p9ZANhTI6uJa8XI4jchsrnl9oswwCKNR9D0xIIeR

 

C프로그램의 파라미터 파싱 및 처리

문자열 파싱은 스크래치 상태(아무것도 없는 빈 상태)로부터 구현하기가 만만치 않은데, 이를 도와주는 라이브러리 함수가 있으니 바로 unistd.h에 정의된 getopt() 함수이다.

getopt()

이 함수의 원형은 다음과 같다.

int getopt(int argc, char * const argv[], const char *optstring);

이 함수의 파라미터는 간단한다.

  1. argc, argv : main() 함수가 받은 파라미터를 그대로 전달한다.
  2. optstring : 파싱해야 할 파라미터를 쓴다. 옵션이 별도의 파라미터를 받는 경우 콜론을 함께 쓴다.

예를 들어 -h, -v, -f filename을 받는 세 가지 옵션이 있다고 하면 옵션스트링은 "hvf:"가 된다. 각각의 옵션을 파싱해내기 위해서는 getopt()함수가 0을 리턴할 때까지 계속해서 반복하면 된다.

그외 전역변수

이 함수와 관련된 전역 변수에는 다음과 같은 것들이 있다.

  • optarg : 옵션 뒤에 별도의 파라미터 값이 오는 경우, 이를 파싱한 결과 파라미터 값은 optarg에 문자열로 저장된다.
  • optind : 다음번 처리될 옵션의 인덱스이다. 만약 파싱한 옵션이후에 추가적인 파라미터를 받는다면 (예를 들어 입력 파일 이름 같이) 이 값을 활용할 수 있다. getopt()함수는 한 번 호출될 때마다 이 값을 업데이트한다.
  • opterr : 옵션에 문제가 있을 때, 이 값은 0이 아닌 값이되며, getopt()함수가 메시지를 표시하게 된다.
  • optopt : 알 수 없는 옵션을 만났을 때 해당 옵션이 여기에 들어간다. (이 때 getopt의 리턴값은 ‘?’가 된다.)

샘플 코드

아래 샘플 코드는 간략한 예를 보여준다. 이 코드에서는 a, b, c의 세 옵션을 인식하며 각각의 옵션이 주어지는 경우 해당 플래그 변수를 1로 정의하고 그 결과를 출력한다.

1:  #include <stdio.h>
2:  #include <unistd.h> // for getopt()
3:  
4:  int main(int argc, char * const * argv){
5:      int flag_a = 0, flag_b = 0, flag_c = 0;
6:      int c; // option
7:      while( (c = getopt(argc, argv, "abc")) != -1) {
8:          // -1 means getopt() parse all options
9:          switch(c) {
10:             case 'a':
11:                 flag_a=1;
12:                 break;
13:             case 'b':
14:                 flag_b=1;
15:                 break;
16:             case 'c':
17:                 flag_c=1;
18:                 break;
19:             case '?':
20:                 printf("Unknown flag : %c", optopt);
21:                 break;
22:         }
23:     }
24:     if(flag_a) {printf("flag a is ON \n");}
25:     if(flag_b) {printf("flag b is ON \n");}
26:     if(flag_c) {printf("flag c is ON \n");}
27:     return 0;
28: }

보통 while문으로 루프를 돌면서 옵션들을 하나씩 검사한다. getopt가 optstring으로 정의되지 않은 옵션문자를 만나면 opterr 값이 세팅되고, 동시에 getopt()함수가 해당 문자에 대해 메시지를 출력한다. 이 때 반환값은 '?'가 되고 이때 알 수 없는 옵션 문자는 optopt에 저장된다.

추가 파라미터를 필요로하는 옵션

gcc의 -o와 같이 파일 이름등의 추가 파라미터를 필요로하는 옵션은 다음과 같이 처리한다.

  1. optsting에서 옵션 문자 뒤에 콜론을 붙인다. "abcf:"와 같은 식으로 쓴다.
  2. getopt()함수는 -f를 만나면 자동으로 그 뒤에 붙은 문자열을 공백까지 탐색하여 이를 optarg에 복사한다.
  3. 처리시에는 리턴값이 ‘f’인 경우 optarg의 값을 그대로 액세스하면 된다.

이러한 처리 코드는 아래와 같다.

case 'f':
    memcpy(file_name, optarg, strlen(optarg));
    break;

또한 파라미터가 있다고 정의한 경우, 파라미터 값이 빠진채로 실행되었다면 이 때는 옵션이 인식할 수 없는 옵션으로 처리된다.

case '?':
    if(optopt == 'f') {
        printf("option -f requires FILENAME\n");
    }
    break;

optind

옵션문자들을 모두 처리한 이후에 프로그램 자체의 파라미터를 처리하기 위해서는 optindargv의 인덱스로 사용하여 파라미터를 전달 받을 수 있다.

그외 긴 이름

--output등의 긴 이름 옵션을 사용하기 위해서는 getoptlong함수를 사용한다.

출처 - http://bbolmin.tistory.com/35

 

먼저 system함수를 알아 보겠습니다.

 

원형은 int system(const char* command)이며 command에 해당하는 명령어를 수행하는 함수입니다.

(반환형이 int인데 성공시 0을 반환, 실패시 -1을 리턴합니다.)

 

system함수로 ls명령어를 실행해본 화면입니다.

   ->

 

/bin/ls처럼 절대 경로말고 ls로만 입력해도 ls가 실행됩니다. (환경변수 PATH를 이용하는 듯..)

그리고 옵션을 사용할 때는 단순히 "/bin/ls -a"와 같이 해주면 됩니다.

  ->

 

 


 

 

이제 exec계열의 함수(execl, execv, execle, execve, execlp, execvp)에 대해서 알아 보겠습니다.

 

아래 그림에서 exec계열의 함수에 대해 자세히 설명해줍니다.

 

위의 exec함수들을 보면 exec에다가 l, v, e, p등 여러가지가 붙어 있습니다.

 

정리를 해보면

1. l, v : argv인자를 넘겨줄 때 사용합니다. (l일 경우는 char *로 하나씩 v일 경우에는 char *[]로 배열로 한번에 넘겨줌) 

 

2. e : 환경변수를 넘겨줄 때 사용합니다. (e는 위에서 v와 같이 char *[]로 배열로 넘겨줍니다.)

3. p : p가 있는 경우에는 환경변수 PATH를 참조하기 때문에 절대경로를 입력하지 않아도 됩니다. (위에서 system함수 처럼)

그럼 간단히 execl와 execve를 써보겠습니다.

 

(1) execl

  ->

 

(2) execve 

 ->

( 딱히 환경변수에 넣을게 없네요; )

위와 같이 실행되는 것을 볼 수 있습니다. (만약 /bin/ls라고 안하고 ls라고 하면 실행이 안되겠죠 --> p가 붙어 있다면 PATH에서 찾기 때문에 실행됩니다.)

 

출처  - http://molrayo.tistory.com/entry/Process-abort%ED%95%A8%EC%88%98%EC%97%90-%EA%B4%80%ED%95%9C-%EC%98%88%EC%A0%9C

 

#include<stdlib.h>

#include<process.h>

 

void abort(void);

 

리턴값

 - 함수 자체의 리턴 값은 없지만 이 함수에서 호출한 _exit 함수에서 exit 코드 3을 도스 또는 모 프로그램으로 리턴한다.

 

기능

 - 프로그램을 종료하되 비정상적으로 종료한다. 반면 exit 함수는 프로그램을 정상 종료한다.

abort 함수로 프로그램이 종료되면 stderr(화면)에 다음과 같은 메시지를 출력하며 _exit 함수를 호출하여 코드 3을 반환하면서 프로그램을 종료하게 된다.

 

abnormal program termination

 

참고 함수

exit => 프로그램을 정상 종료한다.

atexit, assert

 

 

예제

 

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

void func(void);

main(int argc, char *argv[])
{
    atexit(func);
    /* atoi는 정수 형태의 문자열을 정수로 변환하는 함수로 argv[1]이 "1"이면 1로 변환.
      argv[1]이 "0"이 되어야 if 조건이 참이 됨 */
    if(!atoi(argv[1]))
      /* 비정상적으로 프로세스를 종료하는데 atexit에 의해 등록된 함수는 실행되지 않음 */
       abort();
    exit(0); /* 정상적으로 프로세스를 종료하는데 atexit에 의해 등록된 함수가 실행 됨 */
}

void func(void)
{
    printf("run function\n");
}

출처 - http://uiandwe.tistory.com/140

 

Race Condition 문서를 읽으면 어김없이 나올수 밖에 없는 함수.


헤더    unistd.h 
형태    pid_t fork(void);  
반환    pid_t 실행에
 실패하면 -1 을 반환. 부모에게는 새로 생성된 자식 프로세스 PID가 반환
          되며, 자식 프로세스에는 0이 반환됩니다. 


fork()함수에 의해서 생성된 프로세서는 부모의 모든 값을 그대로 이어 받지만 프로세서 아이

디만이 틀릴뿐이다. fork()함수는 0으로 자식프로세서에게 아이디를 부여한다.

그러면 첫번째 자식 프로세서는 0이면 두번째 자식은 몇이 올것인가? 라는 문제의 식이다.

간단하게 프로그램을 짜보면 

과연 결과값이 어떻게 나올것인지 곰곰히 생각해봐야한다.(처음이니까~)


결과가 어떠한가!! 

처음엔 부모 프로세서가 다 돌고 두번째로 생성된 프로세서가 돌고 마지막엔 첫번째 프로세서

가 실행되는것을 볼수 있다. 결국 자식의 자식이 아닌 그저 다른 자식일 뿐이다. 

그리고 그 또한 스택 영역으로 들어간다.(늦게 들어갔기 때문에 두번째 자식이 먼저 실행된다)

그 자식 프로세서도 0으로 되는것이다. 

단순히 새로운 프로세서를 생성하고 분기하는것일뿐(동인한 프로세서로 분기) 이다.

대략적으로 그림으로 보자면 요론 그림으로~


!! 쓰레드와 무슨차이인가요??

라고 물어본다면 당연히 프로세서는 프로그램을 실행하기 위한 하나의 단위이다.

쓰레드는 프로세서안에서 실행하기 위한 단위라고 생각하면 된다.

여러 쓰레드가 모여서 프로세서를 만들고 쓰레드는 오직 프로세서 안에서만 존재한다.

fork()는 프로세서를 만드는것이지(복사하는것) 동시에 돌아가지는 않는다.

쓰레드를 쓰는이유는 동시에 처리하기 위함이니까 전혀 틀리게 된다.





출처 - http://microsoft.tistory.com/22

 

2> fseek(), ftell()

-----------------------------------------------------------------------

우리는 모니터 화면에 커서가 있는것을 안다. 이것은 텍스트 모드에

서 뿐만 아니라 그래픽 모드에서도 마찬가지 였다. 글자나 점 하나를 모니터

의 특정한 곳에 찍고 싶으면, 이 커서를 그 곳에다 갖다 놓고 그다음 찍는

행위를 해야한다.

이와같은 개념은 "파일"을 취급할 때도 마찬가지이다. 하지만 파일

은 하드디스크에 들어 있는 것이기 때문에, 모니터처럼 고정된 좌표를 가지

지 못한다는 것에 큰 차이가 있다.

언젠가 파일을 "두루마리 편지"라고 비유한 적이 있는데, 이제 현대

식으로 다시 비유를 해보면, 도트 프린터의 "연속용지"에 파일이 전부 인쇄

된 것과 유사하다고 생각해 볼 수 있다. 아시다시피 이 상태에서는 파일의

크기(프린트 용지의 길이)가 고정적일 수가 없다. 어떤 파일은 한장짜리가

될 수도 있고, 어떤 것은 베게로 베고 잘 수 있을 정도로 두꺼울 수도 있다.

 

파일을 "읽기 위해" fopen() 하면 이 "파일 커서"(사실 이런 용어는

안쓰지만 이해를 돕기위해서 씁니다)는 인쇄된 연속용지 "첫장의 제일 첫글

자"를 가리키고 있다. 이건 어디서나 상식이다.

그리고 이 파일 커서를 움직이려면 fseek()를 쓴다. 이 파일 커서는

돌아 다닐 수 있는 곳이 파일의 크기에 따라 가변적이므로 모니터에서 쓰듯

이 좌표를 줄 수 없다는 것은 당연하다. 그래서 돌아 다니는 방법이 조금 복

잡하다. 말로 하면, "현재 위치에서 5글자 뒤로 가"를 다음과 같이 쓴다.

 

fseek(fp,5L,SEEK_CUR) <--- "현재 위치"에서 5글자 뒤로 가

fseek(fp,5L,SEEK_SET) <--- "파일 제일 처음 글자"에서 5글자 뒤로 가

fseek(fp,-5L,SEEK_END) <--- "파일 제일 끝 글자"에서 5글자 앞으로 가

(뒤로는 더이상 못간다. 상식 !)

 

여기서 "뒤로 " 라는 얘기는 한글자씩 오른쪽 옆으로 움직이는걸 얘기

한다. 즉 우리가 책을 읽어나가는 방향이다. 이 때 물론, 한 줄 끝에 이르면

다음 줄 첫 글자로 이동한다.

이때 "SEEK_" 로 시작되는 이름들은 대문자로 쓴 걸 보아 벌써 어디선

가 정의 되있다는 것을 알것이다. 따라서 우리는 무조건 외어서 써야하는데

그 의미는 위에서 얘기한데로 다음과 같다.

--------------------------------------------------------

SEEK_CUR --> "현재(current) 위치에서"를 의미한다.

SEEK_SET --> ""파일 제일 첫글자 에서"를 의미한다.

SEEK_END --> "파일 제일 끝 글자 에서"를 의미한다.

---------------------------------------------------------

 

<숙제> 이런 상수들은 전부"헤더 파일"에 선언되 있다는 것을 알 수 있을 것

입니다. 어떤 헤더 파일에 정의되 있는지 찾아 보세요. (노턴 유틸

리티를 가지고 있는 분들은 TS( Text Search) 명령을 쓰세요.)

그리고 만일, 아직도 이런 툴(tool)을 안가지고 있는 분들은 빨리

구해서 활용을 해야 합니다. 프로그래머들에게는 이런 툴은 필수적

입니다.

 

실제로 파일을 열어놓고 이 파일 커서가 돌아다니기 시작하면 조금

정신이 없다. 왜냐하면 이건 모니터상에 깜박이는게 아니고 우리 머리속에서

만 움직이는 것이다. 따라서 누가 조금만 정신을 어지럽히면 현재 커서위치

를 놓치고 만다.

큰 파일을 취급할땐, 연속용지로 치면 길이가 무척 길어서 경부고속

도로를 쭉 따라가며 펼쳐 놔야한다. 그러다가 한 순간에 커서를 놓치면 이

놈이 천안에 가있는지 대전에 가있는지 알기 어렵다. 물론 그렇다고 전혀 못

찾는건 아니다.

이 때 "커서야 어디있니 !" 이렇게 외치는게 ftell() 이다. 쓰는법

을 정확히 알아보기 위해 [439쪽]을 참조하자. 이 사용법은

더이상 내가 설명을 안해도 잘 아실 줄로 믿는다. 예를 들면 다음과 같이 쓰

라는 얘기다.

 

#include <stdio.h>

main()

{

int i;

long ll;

FILE *from;

 

ll = ftell(from);

}

 

ftell() 의 대답(리턴 값)은 long형 이므로, long 타입 변수 ll 이

받은게 당연하다. 또 사용법에서 언급하는 ftell(FILE *fp)의 "FILE *fp"는

from 변수의 타입과 같음을 보라.

그러면 여기서, "왜 long형으로 대답하는지" 그 이유를 를 짚고 넘

어가기로 하자. "어디있니 ?"의 대답이 long 형 이면 4 바이트(32 비트) 크

기이다. 즉 4G 바이트 만큼 멀리갈 수 있다는 얘기다.

여러분의 하드디스크가 얼마나 큰지 모르겠는데, 나는 지금 420M(메

가) 짜리 하드 디스크를 쓰고 있다. 이것은 요즘 유행으로 봐서는 그다지 큰

것도 아닌 것 같다. 만일 이런 하드디스에 하나 짜리 파일이 통째로 들어가

있어도 ftell()은 가볍게 대답할 수 있는 거리다.

단 여기서 주의할 것은, 대답하는 거리는 무조건 "파일의 처음"에서

부터 떨어진 거리를 말한다. 여기에는 빨간 형광펜으로 밑줄을 "쫙" 그어두

기로 하자. 그러나 곰곰이 생각해보면 너무 당연한 얘기이기도 하다.

왠가하면 아마 지금도 교통방송에서는 어느 여자 아나운서의 낭랑한

목소리를 들을 수 있을테니까.

 

"경부 고속도로, "서울 기점 200Km 지점"에서 두 차가 장렬하게

닿았습니다."

 

아마도 그 여자 아나운서는 "C 언어"를 모를테지만 그래도 사고지점을 우리

에게 알려주는 방법은 ftell()의 "리턴값"과 같은 것이다.

"서울 기점 200Km" 면 아마 대전 근처가 아닐까 짐작하는데, 아무리

그래도 "대전 북방 2Km"따위로 얘기하지 않고, 기준점을 "서울"로 잡은 것이

다. 그게 "파일의 처음 위치"이다.

이제 다음의 예를 읽어보면서, "파일 커서"가 (개구리 처럼) 어디로

튀는지 잘 쫓아가 보기로 하자.

------------------------------------

#include <stdio.h>

 

main()

{

char c;

int i;

FILE *fp;

 

fp=fopen("a_to_z", "w+b");

 

for (c='A' ; c<='Z' ; c++)

fputc(c, fp);

 

fseek(fp, 0, SEEK_SET);

 

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

printf("\n%c : %d", fgetc(fp), ftell(fp) );

putchar('\n');

 

fseek(fp, -5, SEEK_END);

 

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

printf("\n%c : %d", fgetc(fp), ftell(fp) );

putchar('\n');

 

fseek(fp, -10, SEEK_CUR);

 

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

printf("\n%c : %d", fgetc(fp), ftell(fp) );

fseek(fp, -2, SEEK_CUR);

}

fclose(fp);

}

<문제> 답을 미리 적어보고 실행해보세요.

 

-----------------------------------------------------------------------

3> fread(), fwrite()

-----------------------------------------------------------------------

이 함수들은 특정 자료형을 글자 단위로 입출력하지 않고 "덩어리

단위"로 읽고 쓴다. 다음의 예를 보자.

main()

{

FILE *fp;

char name[20] = "Lim chungha";

 

fp = fopen("xxx.xxx","w");

fwrite(name, 20,1,fp); <-- (요기)

}

(요기)를 말로 하면 "name[] 에 있는 데이타들을 파일 fp에 쓰는

데, 덩어리는 20 바이트가 한묶음이고 그런걸 한 덩어리 쓰라"는 얘기다.

즉, 이 경우에는 한 사람의 이름을 파일에 쓰라는 얘기이다.

여기서 name[]의 크기는 사람 이름을 위한 길이를 임의로 넉넉하게

[20] 바이트로 잡았다. fread() 도 마찬가지다.

main()

{

FILE *fp;

char name[20];

 

fp = fopen("xxx.xxx","r");

fread(name, 20,1,fp); <-- (요기)

}

fread()를 실행하기 전에 name[20]이라는 배열에는 아무 값도 안들

어가 있다. 그러나 위 fwrite()에서 임 청하의 이름을 xxx.xxx 에 성공적으

로 썼다면 위의 (요기)를 실행하고 나면 name[]에 임청하라는 이름이 들어

가 있을 것이다.

이것도 말로 하면 "파일 fp 에서 읽는데 쓸 곳은 name (즉 name[]

배열의 첫집)이다. 크기는 20 바이트짜리 덩어리 한 묶음이다"

이제 다음의 예제를 보자. 친구의 이름과 전화번호를 입력받아 파일에

저장하고 화면에 보여준다.

------------------------------

#include <stdio.h>

main(int argc, char *argv[])

{

int c;

FILE *fp;

struct {

char name[20];

char tel_no[20];

} entry;

 

char yn;

 

clrscr();

/*------------< write record to file >--------------*/

if((fp = fopen("friends.tel","w")) == NULL) {

printf(" can't open ..");

exit(1);

}

 

do {

printf("\n 이름 : ");

gets(entry.name);

printf(" 전화번호 : ");

gets(entry.tel_no);

fwrite(&entry, sizeof(entry),1,fp);

 

printf("\n 계속할까요 (y/n) ? ");

yn = getch();

} while ( yn == 'y' || yn == 'Y');

 

fclose(fp);

 

/*----------< display records >--------------*/

clrscr();

 

if((fp = fopen("friends.tel","r")) == NULL) {

printf(" Can't open file \n");

putch(0x07);

exit(1);

}

while(fread(&entry, sizeof(entry),1,fp) == 1) {

printf(" %s %s\n", entry.name, entry.tel_no);

}

fclose(fp);

getch();

 

}

출처 - http://soooprmx.com/wp/archives/4993

 

C프로그램의 파라미터 파싱 및 처리

문자열 파싱은 스크래치 상태(아무것도 없는 빈 상태)로부터 구현하기가 만만치 않은데, 이를 도와주는 라이브러리 함수가 있으니 바로 unistd.h에 정의된 getopt() 함수이다.

getopt()

이 함수의 원형은 다음과 같다.

int getopt(int argc, char * const argv[], const char *optstring);

이 함수의 파라미터는 간단한다.

  1. argc, argv : main() 함수가 받은 파라미터를 그대로 전달한다.
  2. optstring : 파싱해야 할 파라미터를 쓴다. 옵션이 별도의 파라미터를 받는 경우 콜론을 함께 쓴다.

예를 들어 -h, -v, -f filename을 받는 세 가지 옵션이 있다고 하면 옵션스트링은 "hvf:"가 된다. 각각의 옵션을 파싱해내기 위해서는 getopt()함수가 0을 리턴할 때까지 계속해서 반복하면 된다.

그외 전역변수

이 함수와 관련된 전역 변수에는 다음과 같은 것들이 있다.

  • optarg : 옵션 뒤에 별도의 파라미터 값이 오는 경우, 이를 파싱한 결과 파라미터 값은 optarg에 문자열로 저장된다.
  • optind : 다음번 처리될 옵션의 인덱스이다. 만약 파싱한 옵션이후에 추가적인 파라미터를 받는다면 (예를 들어 입력 파일 이름 같이) 이 값을 활용할 수 있다. getopt()함수는 한 번 호출될 때마다 이 값을 업데이트한다.
  • opterr : 옵션에 문제가 있을 때, 이 값은 0이 아닌 값이되며, getopt()함수가 메시지를 표시하게 된다.
  • optopt : 알 수 없는 옵션을 만났을 때 해당 옵션이 여기에 들어간다. (이 때 getopt의 리턴값은 ‘?’가 된다.)

샘플 코드

아래 샘플 코드는 간략한 예를 보여준다. 이 코드에서는 a, b, c의 세 옵션을 인식하며 각각의 옵션이 주어지는 경우 해당 플래그 변수를 1로 정의하고 그 결과를 출력한다.

1:  #include <stdio.h>
2:  #include <unistd.h> // for getopt()
3:  
4:  int main(int argc, char * const * argv){
5:      int flag_a = 0, flag_b = 0, flag_c = 0;
6:      int c; // option
7:      while( (c = getopt(argc, argv, "abc")) != -1) {
8:          // -1 means getopt() parse all options
9:          switch(c) {
10:             case 'a':
11:                 flag_a=1;
12:                 break;
13:             case 'b':
14:                 flag_b=1;
15:                 break;
16:             case 'c':
17:                 flag_c=1;
18:                 break;
19:             case '?':
20:                 printf("Unknown flag : %c", optopt);
21:                 break;
22:         }
23:     }
24:     if(flag_a) {printf("flag a is ON \n");}
25:     if(flag_b) {printf("flag b is ON \n");}
26:     if(flag_c) {printf("flag c is ON \n");}
27:     return 0;
28: }

보통 while문으로 루프를 돌면서 옵션들을 하나씩 검사한다. getopt가 optstring으로 정의되지 않은 옵션문자를 만나면 opterr 값이 세팅되고, 동시에 getopt()함수가 해당 문자에 대해 메시지를 출력한다. 이 때 반환값은 '?'가 되고 이때 알 수 없는 옵션 문자는 optopt에 저장된다.

추가 파라미터를 필요로하는 옵션

gcc의 -o와 같이 파일 이름등의 추가 파라미터를 필요로하는 옵션은 다음과 같이 처리한다.

  1. optsting에서 옵션 문자 뒤에 콜론을 붙인다. "abcf:"와 같은 식으로 쓴다.
  2. getopt()함수는 -f를 만나면 자동으로 그 뒤에 붙은 문자열을 공백까지 탐색하여 이를 optarg에 복사한다.
  3. 처리시에는 리턴값이 ‘f’인 경우 optarg의 값을 그대로 액세스하면 된다.

이러한 처리 코드는 아래와 같다.

case 'f':
    memcpy(file_name, optarg, strlen(optarg));
    break;

또한 파라미터가 있다고 정의한 경우, 파라미터 값이 빠진채로 실행되었다면 이 때는 옵션이 인식할 수 없는 옵션으로 처리된다.

case '?':
    if(optopt == 'f') {
        printf("option -f requires FILENAME\n");
    }
    break;

optind

옵션문자들을 모두 처리한 이후에 프로그램 자체의 파라미터를 처리하기 위해서는 optindargv의 인덱스로 사용하여 파라미터를 전달 받을 수 있다.

그외 긴 이름

--output등의 긴 이름 옵션을 사용하기 위해서는 getoptlong함수를 사용한다.

+ Recent posts