JC Tailor

블로그 이미지
컴퓨터를 사랑하자.~
dkcjs3

Article Category

분류 전체보기 (52)
프로그램방법론 (0)
Tailor 이야기 (0)
C언어 이야기 (49)
C++ 이야기 (1)
API 이야기 (0)
MFC 이야기 (0)
Window XP 이야기 (0)
컴퓨터정보 (1)
나의 삶 이야기 (1)
UNIX (0)

Recent Comment

Recent Trackback

Calendar

«   2017/08   »
    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    

Archive

  • Total24,765
  • Today0
  • Yesterday3
신고
Trackback 0 and Comment 0

#include < time.h >

/*
clock_t clock( void )
 // 프로그램이 실행된 이후부터 경과된 시간에 대해 최대 근사치를 반환한다

double difftime( time_t t1 , time_t t2 ) ;
 // 두 개의 시간 사이의 차이 ( 즉 t1 - t2 )를 초단위로 반환한다

time_t mktime( struct tm * tmptr )
 // tmptr이 가리키는 tm 타입의 구조체의 시간을 달력 시간으로 반환한다

time_t time( time_t *ptr  );
 // 달력 시간을 반환하고, ptr이 NULL이 아닐 경우네는 ptr이 가리키는 위치에도 달력 시간을 대입한다 .

char * acstime( const struct tm *tmptr ) ;
 // tmptr이 가리키는 구조체의 시간을 "Thu Feb 25 10:00:00 2005\n\0" 형태의 문자열로 변환하고 그걸 가리키는 포인터는 반환한다

char *ctime( const time_t *ptr);
 // ptr이 가리키는 달력시간을 현재 시간(local time)으로 변환하고 그 결과를
 // 다시 asctime()의 결과와 같은 문자열 표기법으로 변환하여 가리킨다.

struct tm * gmtime( const time_t *ptr );
 // ptr이 가리키는 달력시간을 tm구조체의 분리된 시간으로 변환하는데,
 // 세계협정시로 표현하고, 그 구조체를 가리키는 포인터는 반환한다

sturct tm *localtime( const time_t *ptr ) ;
 // ptr이 가리키는 달력 시간을 지역 시간의 tm구조체로 변환하고 그 구조체를 가리키는 포인터는 반환한다.

size_t strftime(char *restrict  s , size_t max , const char *restrict fmt , const struct tm * restrict tptr  );
 // 문자열 fmt를 문자열 s로 복사하는데, fmt안에 있는 서식 지정자를 fmt가 가리키는 분리된 시간 구조체로 교체한다.
 // 최대 max개의 문자가 s로 복사되며, NULL문자를 제외한 복사된 문자의 개수를 반환한다.

 

// strcut_tm 구조체의 변수들

struct tm
{
int tm_sec;  // 초
int tm_min;  // 분
int tm_hour; // 자정을 기준으로 한 시간 ( 0~ 23)
int tm_mday; // 월의 일 (0 - 31 )
int tm_mon;  // 1월부터 나타낸 월 0 - 11
int tm_year; // 1900년부터의 년도
int tm_wday; // 일요일부터 시작하는 요일의 값( 0 - 6 )
int tm_yday; // 1월 1일부터 시간한 년의 일( 0 - 365 )
int tm_isdst; // 썸머타임 ( 0보다 크면 현재 썸머타임이 진행중이라는 것 )
}

  */

//━━━ 예  제 ━━━

void main()
{
 struct tm today;
 time_t tt;

 time(&tt);
 today = *localtime(&tt);

 printf("## 현재 날짜와 시간 ## \n" ) ;
 printf("%d년 " , today.tm_year + 1900 );
 printf("%d월 " , today.tm_mon+1 );
 printf("%d일 " , today.tm_mday ) ;
 printf("%d시 " , today.tm_hour ) ;
 printf("%d분 " , today.tm_min  ) ;
 printf("%d초 \n" , today.tm_sec ) ;

}

신고
Trackback 0 and Comment 0
저수준의 화일 입출력에서는 FILE이란 구조 대신 간단하게 각 화일마다 번호를 사용하는데, 이를 화일 식별자(file descriptor), 또는 핸들(handle)이라고 합니다. 이 핸들은 0 이상의 값을 가지고 있는데 실제로 0과 1, 2 는 고정된 의미(핸들 0은 표준 입력을 위한 번호이며 1은 표준 출력, 그리고 2는 표준 에러로 사용)를 갖고 있어서 화일을 처음 열게 되면 그 화일의 핸들은 3이 됩니다.
핸들의 의미는 이후에 win32 프로그래밍 강좌를 할 때 자세히 다루기로 하고 여기서는 그냥 화일 구별할 수 있는 식별자 정도로 이해 하시면 됩니다.

저수준의 화일 입출력에서도 화일을 사용하기 위해서는 화일을 먼저 열어야 하며, 이때 다음과 같이 open 함수를 사용합니다.
        int fd;
        fd = open("화일 이름", 액세스 방식[, 모드]);

위에서 [ ]는 역시 생략할 수 있는 부분을 의미하며, 화일 이름은 fopen과 같이 열 화일의 이름이고 액세스 방식은 이 화일을 어떻게 열 것인가인데, fopen과는 달리 다음과 같은 형태로 사용합니다.

-----------------------------------------------------------
   모드            값                                     내  용
-----------------------------------------------------------
O_RDONLY    0x0001   읽기 전용으로 화일을 엽니다.
O_WRONLY    0x0002   쓰기 전용으로 화일을 엽니다.
O_RDWR        0x0004   읽고 쓰기 위해 화일을 엽니다.
O_CREAT       0x0100  화일이 없을 경우 새로운 화일을 만듭니다.
O_TRUNC       0x0200  현재 있는 화일의 내용을 0으로(제거) 합니다.
O_EXCL         0x0400   O_CREAT과 함께 사용하며,
                                  화일이 없을 경우에만 엽니다.
O_APPEND     0x0800   화일을 쓰기용으로 열고 화일 포인터를
                                   화일의 끝에 위치시킵니다.
O_TEXT         0x4000   화일을 텍스트 형식으로 엽니다.
O_BINARY      0x8000   화일을 이진 형식으로 엽니다.
-----------------------------------------------------------

위의 O_로 시작하는 것들은 모두 상수로 이의 정의는 fcntl.h(이것은 file control의 약자)에 들어 있기 때문에 include 문을 사용하려면 반드시 fcntl.h를 포함하여야 합니다.
위의 것들은 액세스 방식의 한 조건들로 여러 개를 동시에 같이 사용할 수 있으며 이 때에는 각 조건들을 '|'(비트 연산자 OR)를 이용해서 묶으면 됩니다.
data.dat 란 화일을 읽기 전용으로 열고자 할 때에는 다음과 같이 하면 됩니다.
        fd = open("data.dat", O_RDONLY);

그리고 기존의 화일이 있으며, 이를 지우고 쓰기 전용으로 열 때에는 다음과 같이 하면 됩니다.
        fd = open("data.dat", O_WRONLY | O_TRUNC);

O_TRUNC이 추가 되었는데, 만약 이를 써 주지 않으면 쓰기 전용이라도 화일의 내용은 없어지지 않습니다. 반면에 화일의 끝에 추가하고자 할 때에는 다음과 같이 O_APPEND를 써 주면 됩니다.
        fd = open("data.dat", O_WRONLY | O_APPEND);

fopen 문과 다른 것은 해당 화일이 없는 경우 화일이 만들어지지 않는다는 것입니다. 만약 화일이 없을 때 화일을 만들도록 하고 싶으면 다음과 같이 O_CREAT를 지정하여야 하며, 이 때에는 세번재 인자가 필요합니다.
        fd = open("data.dat", O_WRONLY | O_CREAT | O_TRUNC, 모드);
                    /*  화일이 있으면 그 내용을 지우고 없으면 생성, fopen의 "w"와 같음  */
        fd = open("data.dat", O_WRONLY | O_CREAT | O_APPEND, 모드);
                  /*  화일이 있으면 그 끝으로 이동하고 없으면 생성, fopen의 "a"와 같음  */

세번째 인자인 모드에는 액세스 방식에서 O_CREAT 플래그가 지정된 경우, sys\stat.h(TC의 경우)에 정의되어 있는 다음 기호 중 하나가 사용됩니다(일반적으로 8진수 0700을 주면 됩니다).
        S_IWRITE               /*  써 넣기 가능  */
        S_IREAD                /*  읽어 내기 가능  */
        S_IREAD | S_IWRITE     /*  읽기 / 쓰기 가능  */

읽기용 화일에서는 모드를 생략해도 화일의 사용에는 별 지장이 없습니다.

그밖에 O_RDWR은 읽고 쓰고자 할 때 사용하며 O_EXCL은 O_CREAT하고만 같이 사용하는데, 지정한 화일이 있으면 에러가 납니다. 즉 화일이 없는 상태에서 새로 만들고자 할 때에는 O_EXCL과 O_CREAT를 같이 사용하면 됩니다.
신고
Trackback 0 and Comment 0

사용자 삽입 이미지


신고
Trackback 0 and Comment 0

memset()

 : 메모리 블록의 모든 바이트를 특정한 값으로 초기화.

/*

 주의점 : c 가 int 형이면서도 char 형으로 처리된다는 것. memset()을 사용하여

             int, float, double 형의 배열을 0이 아닌 다른 값으로 초기화 하는데는

             쓸모가 없지만, 모든 배열 요소를 0의 값으로 초기화 할 수는 있다.

*/


_ 이하, MSDN _

Sets buffers to a specified character.

Required Header : or

void *memset( void *dest, int c, size_t count );

Parameters

dest
Pointer to destination ( 메모리블록을 가리킴 )
c
Character to set  ( 설정할 값 )
count
Number of characters ( dest에서 시작하여 설정될 바이트의 개수 )

Libraries

All versions of the C run-time libraries.

Return Values

memset returns the value of dest.

Remarks

The memset function sets the first count bytes of dest to the character c.

Example

/* MEMSET.C: This program uses memset to
 * set the first four bytes of buffer to "*".
 */

#include 
#include 

void main( void )
{
   char buffer[] = "This is a test of the memset function";

   printf( "Before: %s\n", buffer );
   memset( buffer, '*', 4 );
   printf( "After:  %s\n", buffer );
}

Output

Before: This is a test of the memset function
After:  **** is a test of the memset function
신고
Trackback 0 and Comment 0
void와 void*(포인트)
void와 void*(포인트)

1. void

   주1)에서와 같이 void는 비어있다 아무것도 없다는 뜻을 가지는 단어이다. void가 단독으로 사용되는 경우에는 사전적인 의미에서와 같이 "아무것도 없다"로 사용된다.

   - 함수의 인자로 사용

      예1)  함수 선언 : int GetValue( void );

     즉, 입력되는 것이 없다.     

  - 함수의 리턴값으로 사용

      예2) 함수 선언 : void SetValue( int nValue );

     즉, 리턴되는 값이 없다. 비주얼 베이직에서  Sub와 동일하다.


2. void*(포인트)

  void*는 void와 다른 의미를 가진다. void*는 "어떤것이라도 가르킬 수 있다"로 사용된다.

   예3)

       float fValue = 0.0f;

       short nValue = 0;

       short* pnValue = &nValue; // short형 포인트

       float* pfValue = &fValue; // float형 포인트

      void* pValue = ( void* ) &nValue; // short형 포인트(주소)를 void*포인트에 할당

      pValue = ( void* ) &fValue; // float형 포인트(주소)를 void*포인트에 할당

     pfValue = ( float* ) pValue; // pValue는 float형 포인트를 가르키고 있기 때문에 문제가 없다.

     pnValue = ( short* ) pValue; // 컴파일 오류(경고 포함)는 생기지 않지만, 포인트(pValue)가 가르키는 데이타형이 틀리기 때문에 심각한 문제가 발생할 수 있다.

  예3)에서와 같이 void*는 무엇이든 할당할 수 있다. 컴파일러에 따라 틀리지만, 형변환은 반드시 해야 한다.      


3. void*는 무엇이든 할당할 수 있다는 점이 강력한 장점이지만, 심각한 문제를 발생시키는 원인

    예4)

     short nValue[ 10 ];

     float* pfValue = NULL;

     void* pValue = NULL;

     pValue = &nValue;

     pfValue = ( float* ) pValue;

 예4)에서와 같이 pValue를 강제로  pfValue에 할당을 할 경우에 심각한 문제가 생길 수 있다.

시스템 혹은 운영체제에 따라 틀리지만, short는 2바이트, float는 4바이트의 데이타형이다. 위와 같이  pfValue를 사용하게 되면, pfValue[ 5 ]부터 short nValue[ 10 ]에 할당된 메모리 영역을 벗어 나게 된다. 벗어난 메모리 영역에 값을 쓰게 되면 어떤 현상이 생길지는 아무도 모른다. 아무도 모른다는것이 가장 큰 문제이다. 특히, 벗어난 영역이 다른 값을 침범하게 된다면, pfValue를 사용하지 않는 멀쩡한 코드에서 갑자기 오류가 생겨 디버깅이 힘들어지는 경우도 생긴다. 물론, 예4)에서와 같이 할당하는 프로그래머는 없겠지만, 유사한 형태는 나올 수 있다.


주1) void 뜻 : http://endic.naver.com/endic.nhn?docid=1254810

신고
Trackback 0 and Comment 0

문자열 변환 함수 atoi() 구현

 

1. atoi()의 함수에 대하여

- 함수원형 : int atoi(const char *s);       /* ascii to integer */

  - 헤더파일 : stdilb.h

  - 기능 : 문자열을 정수로 변환한다. 문자열은 숫자 및 부호로 이루어져 있어야 하며 앞부분에 TAB 이나 공백이 있어도 상관없다. 그러나 영문자, 불필요한 기호 등이 있을 때는 변환이 중지 된다. Overflow에 대한 에러처리는 하지 않는다. 만약 int형의 범위를 넘는 수가 문자열에 들어있을 경우 65536으로 나눈 나머지를 리턴한다.

- 리턴값 : 문자열로부터 변환된 정수, 변환이 불가능한 경우 0이 리턴된다.

 

2. 소스코드

int atoi(char *st)

{

        int i = 0, j = 0;

 

        if (*st == '-' || isdigit(*st)) {

                if(*st == '-') j = 1, st++;

                while(isdigit(*st))

                {

                        i = i * 10 + (*(st)) - 48;

                        st++;

                }

                if (j == 1) return -i;

                else return i;

        }

        else

                return 0;

}

 

3. 실행결과

dalma[ahriman{85}  ~ ] a.out

atoi함수 구현

input : 12341

output : 12341

dalma[ahriman{86}  ~ ] a.out

atoi함수 구현

input : -123123

output : -123123

dalma[ahriman{87}  ~ ] a.out

atoi함수 구현

input : -123.21312

output : -123

dalma[ahriman{88}  ~ ] a.out

atoi함수 구현

input : 34lkd2312

output : 34

신고
Trackback 0 and Comment 0

strcpy함수는 전체 문자열을 다른 메모리 영역으로 복사한다.


*함수 원형


char *strcpy(char *복사시킬 문자열, char *원래 문자열);


복사시킬 새로운 문자열의 포인터를 돌려준다.



/*'strcpy'의 사용 예*/

#include
#include
#include

char source[]="The source string.";

int main()
{
    char dest1[80];
    char *dest2, *dest3;
   
    printf("source : %s", source);
   
    /*dest1이 80바이트의 할당된 공간을 지적하므로*/
    /*dest1로의 복사는 정상적이다.*/
   
    strcpy(dest1, source);
    printf("\ndest2 :  %s", dest1);
    
    /*dest2로 복사하기 위해서 공간을 할당해야 한다.*/
   
    dest2 = (char*)malloc(strlen(source)+1);
    strcpy(dest2, source);
    printf("\ndest2 :  %s", dest2);
   
    /*대상 공간을 할당하지 않고 복사하는 것은 좋지 않다.
    다음은 심각한 문제를 일으킬 수 있다.*/
   
    /*strcpy(dest3, source);*/
   
    getchar();
   
     return 0 ;

}



strncpy함수는 복사할 문자의 개수를 지정할 수 있다.


*함수 원형


char strncpy(char *복사시킬 문자열, char *원래 문자열, size_t 개수);


역시 복사시킬 문자열의 포인터를 돌려준다.


/*'strncpy'의 사용 예*/

#include
#include

char *dest = "..........................";
char *source = "abcdefghijklmnopqrstuvwxyz";

int main()
{
    size_t n;
   
    while(1)
    {
        puts("Enter the number of characters to copy (1-26)");
        scanf("%d", &n);
       
        if(n>0 && n<27) break;
       
    }
   
    printf("\nBefore strncpy destination = %s", dest);
   
    strncpy(dest, source, n);
   
    printf("\nAfter strncpy destination = %s", dest);
   
    getchar();
   
    return 0;
   
}


.. 이 소스는 될런지 모르겠다.

분명 정확히! 적었는데 아무리 해도 되지를 않고

디버그를 해봐도 segmentation fault로 나와 고생고생 쌩난리를 쳐도 안되더라(..)


결국 마음속으로 '컴파일러가 이상한거야, 그런거야!'를 되풀이하며 묻어버렸다.(...)

에러만 나면 무조건 컴파일러의 탓만 하는 안좋은 습관이 생겼다.OTL


strdup은 알아서 malloc()함수를 호출하여 목적 문자열을 저장하기 위한 메모리 영역을 할당한다.


char *strdup(char *source);


strdup은 목적 문자열에 대한 포인터를 돌려준다.

strdup은 ANSI 표준 함수가 아니다! (그런데도 잘만 되더라,)


/*'strdup'의 사용 예*/
#include
#include
#include

char *source = "The source string";

main()
{
    char *dest;
   
    printf("Source = %s", source);
   
    if((dest = strdup(source)) == NULL){
        fprintf(stderr, "Error allocating memory.");
        exit(1);
    }
   
    printf("\nDestination = %s", dest);
   
    getchar();
   
    return 0;
}


strlib에 있는 exit함수는

'닭치고 종료'의 기능을 한다.

인수가 0이면 '정상 종료'를,

1이면 '비정상적인 종료'를 의미한다.


맨 끝의 getchar은

dev C++에선 Visual C++와는 달리 실행 파일에 'Press any key to continue'따위가 나오지 않고

출력 하자마자 볼 새도 없이 곧장 꺼져버버리길래, 그냥 확인용으로.

Visual C++에선 쓸 필요가 없는 녀석.

신고
Trackback 0 and Comment 1

/*
Q: strcpy 이거에 대한 건데요 ..
   a가 abc이고 b가 def인데 a와 b를 strcpy하고
   a를 출력하면 def가 나와야 하는거에요
   abcdef가 나와야 하는거에요?

A: def가 나와야합니다. 아래 1의 strcpy(...)를 참고하세요

우선 string.h에 있는 함수들에 대한 설명입니다.

1. strcpy(...)
  원형( prototype ) :
      char *strcpy(char *dest, const char *src);

  설명 : src가 지시하는 문자열을 dest라는 포인터가 지시하는 공간에 복사하고
              그 결과 문자열 dest을 리턴합니다..

  예 : char newstr[32];
          char oldstr[] = "coffee";
          strcpy( newstr, oldstr );


  결과 : newstr -> "coffee"

2. strcat(...)
   원형( prototype )
      char *strcat(char *dest, const char *src);

  설명 : src가 지시하는 문자열(src 문자열 )을 dest가 지시하는 문자열의
              끝에 덧 붙이고 결과를 리턴합니다.

  예 : char str1[] = "abc";
          char str2[] = "def";
          strcat( str1, str2 );


  결과 : str1 -> "abcdef"

3. strcmp(..)
  원형( prototype)
      int strcmp(const char *s1, const char *s2);

  설명 : 문자열 s1과 s2를 사전식( 오름차순 )으로 비교하여 결과를 리턴합니다.
  예 : char str1[] = "big";
         char str2[] = "bigger";
         int result;
         result = strcmp( str1, str2 );

         result 가 0 이면 str1과 str2가 같은 문자열
         result가 양수이면 str1이 str2보다 크다 ( str1이 str2의 뒤에 위치 )
         result가 음수이면 str1이 str2보다 작다 ( str1이 str2보다 앞선다 )

        "big"과 "bigger"의 비교
         "big"  "bigger"
         'b'        'b'
         'i'          'i'
         'g'        'g'
        '\0'        'g'

        최초로 일치하지 아니하는 문자의 차(difference)를 strcmp의 결과로 리턴합니다.
        '\0' - 'g' => 0 - 103 = -103를 리턴
*/


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

/*
사용자가 정의함수( user defined function )
함수의 원형( 프로토 타입 = prototype )을 선언합니다.


표준함수와 구별하기 위하여 앞에 "my"라는 접두어를 붙였습니다.
파라메타의 형에 const라는 modifier(수정자)를 붙인 것은 함수를 정의할 때
문자열을 수정하지 않는다는 의미입니다. */


/* 문자열 복사함수 */
char* mystrcpy( char* dest, const char* src );

/* 문자열 덧붙이기 함수 */
char* mystrcat( char* dest, const char* src );

/* 문자열 비교함수 */
int mystrcmp( const char* s1, const char* s2 );

int main(void)
{
   /* 두개의 문자배열을 선언 */
   char first[255], second[255], copy[255];
   int query, result;

   printf( "두개의 문자열을 입력하여 \n함수 mystrcat(..과 mystrcmp(..를 테스트합니다.\n" );
   while( 1 )
   {
      printf( "\n첫번째 문자열 >> " );
      scanf( "%s", first );
      fflush( stdin );

      printf( "두번째 문자열 >> " );
      scanf( "%s", second );
      fflush( stdin );

      /* 복사 테스트 - mystrcpy */
      mystrcpy( copy, first );
      printf( "복사된 첫번째 문자열은 %s입니다.\n", first );
      mystrcpy( copy, second );
      printf( "복사된 두번째 문자열은 %s입니다.\n", second );
      system( "pause" );

      /* 비교 테스트 - mystrcmp */
      result = mystrcmp( first, second );
      printf( "\n" );
      if( result == 0 )
        printf( "두 문자열 %s와 %s는 같은 문자열입니다\n", first, second );
      else if( result < 0 )
        printf( "문자열 %s는 문자열 %s보다 앞 섭니다\n", first, second );
      else
        printf( "문자열 %s는 문자열 %s의 뒤에 위치합니다\n", first, second );
      system( "pause" );

      /* 덧붙이기 테스트  - mystrcat */
      printf( "\n문자열 %s에 ", first );
      mystrcat( first, second );
      printf( "%s를 덧 붙이면 문자열 %s가 생성됩니다.\n", second, first );

      printf( "\n종료하시려면 'Q'나 'q'를 계속하시려면 그 밖의 아무 키나 누르세요 >> " );
      query = getchar();

      if( query == (int)'Q' || query == (int)'q' )
      {
         printf( "프로그램을 종료합니다\n" );
         break;
      }
   }
   return 0;
}

char* mystrcpy( char* dest, const char* src )
{
     int i = 0, j = 0;

       /*
      src 문자열의 요소문자(src[i])가
      끝의 널문자('\0')에 도달하지 아니한 동안 복사합니다.*/

      while( src[i] != '\0' )
          dest[j++] = src[i++];
      dest[j] = '\0';

      return dest;

       /*
       // 보다 빠른 소스
       // dest라는 포인터는 유지하고
       // p에 dest를 저장한 후 p를 이동하면서 조작

       char* p = dest;
       while( *src )
           *p++ = *src++;
       *p = '\0';

       return dest;
     */

}

char* mystrcat( char* dest, const char* src )
{
   int i = 0, j = 0;
   char* p = dest;

   while( p[i] != '\0' ) i++;
   while( src[j] != '\0' )
      p[i++] = src[j++];
   p[i] = '\0';

   return dest;

  /*
  // 보다 빠른 소스
  // dest라는 포인터는 유지하고
  // p에 dest를 저장한 후 p를 이동하면서 조작


  char* p = dest;


  /* 포인터를 문자열 dest의 끝으로 이동시킵니다. */
  while( *p ) p++;
  while( *src )
          *p++ = *src++;
  *p = '\0';

  return dest;
  */
}

int mystrcmp( const char* s1, const char* s2 )
{
   
/*
   s1이 지시하는 문자가 널문자가 아닌 동안 비교
   s2가 지시하는 문자가 널문자인 경우는 아래 if문에서 catch됩니다. */


   while( *s1 )
   {
      if( *s1 != *s2 )
         break;
      s1++;
      s2++;
   }
   return (*s1 - *s2);
}
   

신고
Trackback 0 and Comment 0
프로그래밍언어 과제 하루 한문제 c언어 작성하기..
신고
Trackback 0 and Comment 0

Tag Cloud


티스토리 툴바