'Programming Languages/C'에 해당되는 글 7건

  1. 2010.08.31 가변 인자 함수 2
  2. 2010.08.31 가변 인자 함수 1
  3. 2010.04.08 포인터 다루기
  4. 2010.03.14 파일 입/출력
  5. 2010.03.09 재귀 함수
  6. 2010.01.12 fflush.c
  7. 2010.01.12 char_IO.c

출처 : http://wiki.kldp.org/wiki.php/CLanguageVariableArgumentsList

본문보다 더 자세하게 나와있으니 부족한 부분은 출처를 통해 정보를 얻으시기 바랍니다.

 
이번에는 가변인자함수를 이용해서 printf()와 똑같은 wrapper함수를 작성해 보도록 하자.

int my_printf(const char *fmt, ...)
{
    va_list argptr;
    int ret;


    va_start(argptr, fmt);
    ret = vprintf(fmt, argptr);
    va_end(argptr);


    return ret;
}


이해가 되었다면 간단한 디버깅함수로서 아래와 같은 함수도 만들수 있겠다.

 

void error(int status, int ecode, const char *fmt, ...)
{
    va_list argptr;


    fflush(stdout);
    fprintf(stderr, 'error: ');
    if (ecode)
        fprintf(stderr, '%s: ', strerror(ecode));


    va_start(argptr, fmt);
    vfprintf(stderr, fmt, argptr);
    va_end(argptr);


    fputc('\n', stderr);


    fflush(stderr);  /* redundant */


    if (status)
        exit(status);
}

 

에러발생시 에러코드값을 표준에러(stderror)로 출력하며, status값에 따라 프로그램을 종료할 수도 있다.

한편, 커널소스에서 종종 보던 가변인자를 이용한 매크로함수도 구현이 가능하다.

(단, ISO C표준을 지원하는 컴파일러에서만 가능함)

 

#define debug(s, ...)    fprintf(stderr, s, __VA_ARGS__)

void foo(void)
{

    debug('Entered the function, %s\n', __func__);

    /* ... */
}


 

'Programming Languages > C' 카테고리의 다른 글

가변 인자 함수 1  (0) 2010.08.31
포인터 다루기  (0) 2010.04.08
파일 입/출력  (0) 2010.03.14
재귀 함수  (0) 2010.03.09
fflush.c  (0) 2010.01.12
Posted by 독뽀
,

출처 : http://blog.paran.com/mk3358/12232583 (원 출처가 폐쇄되어 링크를 대신합니다.)

 

어떤 함수의 경우에는 인자의 타입 검사를 생략하는 경우가 있다.

C의 printf()와 같이 함수의 인자 개수가 일정하지 않은 가변 인자 함수가 그렇다.

이 함수의 원형은 아래와 같다.


int printf( const char *format, ... );


이 함수의 마지막 인자처럼 생략부호(...)로 적어주면

가변 인자 함수(variadic function)를 나타낸다(생략부호 앞의 콤마는 생략해도 된다).

가변 인자 함수는 인자가 정확히 몇 개 오는지 또 어떤 타입인지 알 수 없기 때문에 타입 검사를 할 수 없다.

그래서 printf() 함수 사용은 전적으로 사용자 책임이다.

다음 예와 같이 엉뚱한 사용으로 돌아오는 결과는 실행 시간에 치명적인 에러로 나타난다.


int a = 10 ;
printf( '%d, %f, %dd, %s', a ) ;


참고적으로 가변 인자 함수를 정의하는 절차에 대해 소개한다.


① 우선 stdarg.h 헤더 파일을 포함한다.


#include <stdarg.h>

 

② 가변 인자 함수의 원형을 정한다.

가변 인자 함수에서 마지막 인자는 생략부호, 첫번째 인자는 보통의 인자로 선언해야 한다.

예로 임의 개수의 실수 합을 구하는 함수 sum()을 정의해 보자. 첫 인자는 가변 인자의 수를 넘긴다.

double sum( int n... ) ; 또는 double sum( int n, ... ) ;



③ 함수 정의 안에서 va_list 타입의 변수를 선언한다. 예를 들어 list라 하자.


va_list list ;

 list는 함수의 실인자열을 가리키는 포인터 역할을 한다.



④ va_start 매크로를 사용하여 인자열의 첫 인자를 포인터에 설정한다. va_start매크로의 첫 인자에 va_list 타입으로 선언한 변수를 넣고, 두 번째 인자는 지금 정의하는 함수의 첫 인자를 넣는다.


va_start(list,n);

 

⑤ va_arg 매크로를 사용하여 리스트에서 인자를 꺼내 쓴다. va_arg 매크로의 첫 인자는 va_list 타입으로 선언한 변수이고, 두 번째 인자는 가변 인자열의 인자 타입이다. 실수에 대한 합을 구하므로 double형을 주자.


double item = va_arg(list, double);

 

⑥ va_end 매크로를 사용하여 가변 인자열 포인터를 리셋(reset) 시킨다.


va_end(list);


 

'Programming Languages > C' 카테고리의 다른 글

가변 인자 함수 2  (0) 2010.08.31
포인터 다루기  (0) 2010.04.08
파일 입/출력  (0) 2010.03.14
재귀 함수  (0) 2010.03.09
fflush.c  (0) 2010.01.12
Posted by 독뽀
,


포인터를 이용해서 함수를 배열에 담아 사용해보자.
원리는 포인터를 저장할 수 있는 함수 배열의 각 원소에 함수 포인터들을 저장하는 것이다.


#include <stdio.h>

void Print0(int number);
void Print1(int number);
void Print2(int number);

int main()
{
void (*ptrA[3])(int) = {Print0, Print1, Print2};
//ptrA[0] = Print0;
//ptrA[1] = Print1;
//ptrA[2] = Print2;

ptrA[0](1);
ptrA[1](1);
ptrA[2](1);

return 0;
}

void Print0(int number)
{
printf("Print0 : %d + 0 = ", number);
number = number;
printf("%d\n", number);
}

void Print1(int number)
{
printf("Print1 : %d + 1 = ", number);
number = number + 1;
printf("%d\n", number);
}


void Print2(int number)
{
printf("Print2 : %d + 2 = ", number);
number = number + 2;
printf("%d\n", number);
}



Output


Print0 : 1 + 0 = 1
Print1 : 1 + 1 = 2
Print2 : 1 + 2 = 3

'Programming Languages > C' 카테고리의 다른 글

가변 인자 함수 2  (0) 2010.08.31
가변 인자 함수 1  (0) 2010.08.31
파일 입/출력  (0) 2010.03.14
재귀 함수  (0) 2010.03.09
fflush.c  (0) 2010.01.12
Posted by 독뽀
,

fseek() : 커서 옮기기, reverse나 rollback처럼 뭐 그런거..
_fcloseall() : 열린 파일 모두 닫기, fclose 여러번 할 필요가 없게 해줌. 리턴 값은 닫은 파일 갯수
참고로 %u는 부호 없는 10진수(부호 있는 10진수는 %d)

C에 올라오는 게시물들을 보면 아시겠지만 너무 찾기도 쉽고 조금만 공부해보면 대부분 아는 내용들 혹은
알 수 있는 내용들에는 전혀 언급을 안합니다. 이렇게 불친절하게 올릴거 왜 올리냐 하지 마시길~

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

#define buf 20

FILE *fp1, *fp2;

int main(void)
{
      int i=0;
      char arr[buf];
      //int numclosed;
      errno_t err;

      err = fopen_s(&fp1, "test.txt", "w");      // fopen() 대신 fopen_s()를 사용하였다.
                                                            // 첫번째 인수가 FILE 포인터인 것을 빼면 별 다를 것 없다.
                                                            // 리턴 값은 errno_t형 err에 저장되었는데, 실패하면 0
      if(!err)    // open에 실패했을 경우 0이 err에 대입되었으니 아래 문장이 실행될 것이다.
            printf_s("1test.txt file was not opened\n",stdout);
      else
      {
            fprintf_s(fp1, "Hello file I/O!?\n");
            //fseek( fp1, 0L, SEEK_SET );
      }
      fclose(fp1);

      err = fopen_s(&fp2, "test.txt", "r");
      if(err)
            printf_s("2test.txt file was not opened\n",stdout);
      else
      {
            while(1)
            {
                  fscanf_s(fp2, "%c", &arr[i], 1);      // %s로 읽으면 공백에서 끊어져버린다.
                  if( arr[i] == '\n' ) break;              // 그래서 %c로 개행문자(\n)이 나올 때까지 읽기
                  i++;
            }
            arr[i] = 0;
            printf("%s\n", arr);
      }

      fclose(fp2);
      /*
      numclosed = _fcloseall();
      printf("Number of closed file : %u\n", numclosed);
      */

      return 0;
}

'Programming Languages > C' 카테고리의 다른 글

가변 인자 함수 1  (0) 2010.08.31
포인터 다루기  (0) 2010.04.08
재귀 함수  (0) 2010.03.09
fflush.c  (0) 2010.01.12
char_IO.c  (0) 2010.01.12
Posted by 독뽀
,

재귀란 반복, 다시 돌아온다는 의미이다.(recursive)

스택을 구현하기 위한 방법에는 어떤 것들이 있을까?
여러 방법들이 있겠지만 일시적으로 스택 구조만를 사용하기 위한 경우라면
재귀적 함수 호출을 사용해보자.

재귀적 함수 호출의 흐름을 생각해보자.

a라는 함수가 있다.
이 함수 내에서 a라는 함수 자기 자신을 또 호출한다.
그러면 a라는 함수는 자기 자신을 호출한 시점에서 자기 자신을 호출한다.

메모리 공간에서 실제로 동일한 함수 공간이 만들어지고 작업 영역이 그 곳으로 옮겨지는 것이다.

그렇다면 나머지 내용은?

당연한 결과겠지만 그 새로운 공간에서의 작업이 끝남과 동시에 그 공간을 반환한 뒤 처리된다.
이 말은 반복문을 굳이 사용하지 않아도 Loop 형태를 띌 수 있음을 의미함과 동시에
무한 루프에 빠질 수도 있다는 뜻이다.

참고 : 쿨 프로그래밍
http://blog.daum.net/_blog/BlogView.do?blogid=0Nu8o&articleno=33&categoryId=1#ajax_history_home

'Programming Languages > C' 카테고리의 다른 글

가변 인자 함수 1  (0) 2010.08.31
포인터 다루기  (0) 2010.04.08
파일 입/출력  (0) 2010.03.14
fflush.c  (0) 2010.01.12
char_IO.c  (0) 2010.01.12
Posted by 독뽀
,

fflush.c

Programming Languages/C 2010. 1. 12. 16:21

/************************************************************/
/* fflush(FILE * stream) 버퍼를 비우는 기능                             */
/* stream = stdout일 경우 버퍼의 내용을 지우는 것이 아니라       */
/* 지정한 스트림으로 fflush 호출 시 보내라는 의미                     */
/* stream = stdin일 경우는 버퍼의 내용을 지우는 것                   */
/************************************************************/
#include <stdio.h>

int main(void) {
    char perID[7];
    char name[10];

    fputs("주민번호 앞 6자리를 입력하세요 : ", stdout);
    fgets(perID, sizeof(perID), stdin);

    fflush(stdin); // 입력 버퍼를 비운다.
    // 처음 입력 fputs에서 123456-1234567 을 입력했을 때 -1234567은 버퍼에 남게 된다.
    // 그래서 버퍼를 비운다. 비우지 않으면 당연히 그 값도 출력된다.
    fputs("이름을 입력하세요 : ", stdout);
    fgets(name, sizeof(name), stdin);

    printf("주민번호 앞자리 : %s \n", perID);
    printf("이           름 : %s \n", name);

    return 0;
}

'Programming Languages > C' 카테고리의 다른 글

가변 인자 함수 1  (0) 2010.08.31
포인터 다루기  (0) 2010.04.08
파일 입/출력  (0) 2010.03.14
재귀 함수  (0) 2010.03.09
char_IO.c  (0) 2010.01.12
Posted by 독뽀
,

char_IO.c

Programming Languages/C 2010. 1. 12. 16:18

/********************************************************/
/* 문자(열)을 입력받아 그대로 출력                                   */
/* 주석 처리된 내용은 현재의 내용과 완전히 동일                */
/* getchar, putchar -> 스트림이 이미 지정되어있음 (콘솔)   */
/* fgetc, fputc -> 스트림을 직접 지정(콘솔 - stdin, stdout)   */
/*******************************************************/

#include <stdio.h>

int main(void) {
    char ch=0;
    while(ch != 'q') {
        //ch=getchar();
        ch=fgetc(stdin);
        //putchar(ch);
        fputc(ch, stdout);
        printf("%d ", 1); // 루프가 몇 번 되었는지 확인
    }
return 0;
}

'Programming Languages > C' 카테고리의 다른 글

가변 인자 함수 1  (0) 2010.08.31
포인터 다루기  (0) 2010.04.08
파일 입/출력  (0) 2010.03.14
재귀 함수  (0) 2010.03.09
fflush.c  (0) 2010.01.12
Posted by 독뽀
,