0. 사전 지식

더보기

 

리눅스 표준 입출력 스트림

  • 표준 스트림 : stdin, stdout, stderr  별도의 스트림 생성 없이 바로 사용 가능
  • 표준 입출력 함수 : C, C++ 등에서 제공하는 함수로, 함수 내부에 stdin, stdout 표준 스트림과 버퍼를 사용하도록 구현
  • 파일, 소켓, DB 사용 : 개발자가 명시적으로 스트림을 생성하여 사용

 

get 

  • 함수 실행 결과가 변수, 반환값 이면 get, scan, input 함수명 사용
  • input 의미는 소스코드로 가져오는 것이다.
  • 키보드, 텍스트 파일(원본) → 함수 반환값, 변수(목적지) 등으로 가져올 때
  • 원본에서 데이터를 가져오는 이미지

 

put

  • 함수 실행 결과가 변수, 반환값 이 아니라면 put, print, output 함수명 사용
  • output 의미는 소스코드 밖으로 내보내는 것이다.
  • 모니터, 텍스트 파일로 저장(목적지) 등이 로직의 변수가 아닐 때
  • 저장된 데이터를 목적지로 던져 놓는 이미지

 


C 언어 표준 입출력 함수 분류 

  • [ 윈도우 전용 입출력 함수 ]
    1. 버퍼 사용 안함 - getch( ), putch( ), getche( )

 

  • [ "문자" C언어 표준 입출력 함수 ]
    2. 표준 입출력 스트림 사용 - getchar( ), putchar( )
    3. 임의 생성한 스트림 사용 - fgetc( ), fputc( )

 

  • [ "문자열"  C언어 표준 입출력 함수 ]
    4. 표준 스트림, 임의 배열 버퍼 사용, 입력 크기 제한 없음, 개행 제외, 널 추가 - gets( ), puts( )
    5. 지정 스트림, 임의 배열 버퍼 사용, 입력 크기 제한 있음, 개행 포함, 널 추가 - fgets( ), fputs( ) 

 

  • [ "자료형 지정"  C언어 표준 입출력 함수 ]
    6. 표준 스트림,  format 자료형 지정, 입력 크기 제한 없음, 개행 제외, 널 추가 - scanf( ), printf( )
    7. 지정 스트림,  format 자료형 지정, 입력 크기 제한 없음, 개행 제외, 널 추가 - fscanf( ), fprintf( ) 
    8. 지정한 버퍼,  format 자료형 지정, 입력 크기 제한 없음, 개행 제외, 널 추가 - sscanf( ), sprintf( )

 

개행과 널문자

  • C 언어의 표준 입출력 함수의 이해는 "개행"과 "널 문자"가 버퍼에 어떻게 저장되는지에 대한 이해다.
  • 0x0A(10), #LF: 개행(Line Feed), 줄바꿈 \n
  • 0x00(0), #NUL: 널 문자


문자와 문자열 그리고 개행 입력

  • '문자', "문자열"은 다르다.
    'a', "a" 는 다르다.
  • 문자와 문자열의 차이는 널문자가 포함되느냐의 차이다.
    그렇기 때문에, 문자열 입력은 연속되는 문자 데이터의 마지막에 널문자가 추가된다.

 

1. getch( ), putch( ), getche( )

더보기

 

  1. 문자 1개의 입출력에 사용하는 함수다.
  2. 리눅스나 OS X에서는 사용할 수 없다.
    C 언어 표준도 아니고, POSIX 함수도 아니다.
  3. conio.h (CONsole and port I/O)는 MS-DOS 콘솔 입출력을 위해 만들어졌다.
    윈도우 기반의 Visual Studio에서 주로 사용한다. 
  4. 버퍼를 사용하지 않는다.
    키보드를 눌렀다가 떼는 동시에 변수에 바로 저장한다. 
    그렇기 때문에 잘못 입력한 값을 수정할 수 없고, 백스페이스를 누르면 백스페이스 값도 입력된다.
  5. 윈도우에서 Visual Studio C언어 학습에서 getch( ) 함수는 콘솔(명령 프롬프트) 창이 닫히지 않도록 하기 위해 처음 사용하는 경우가 많다.

 

getch( )

  • get character
  • 키보드 입력한 문자 하나를 반환하는 함수다. 출력하지 않는다.
  • 엔터를 입력하지 않고, 키보드를 눌렀다가 떼는 동시에 입력된 값을 반환한다. 
  • 버퍼를 사용하지 않는다.

 

putch( )

  • put character
  • 매개변수로 넘겨받은 문자 하나를 모니터로 출력하는 함수다.
  • 버퍼를 사용하지 않는다.

 

getche( )

  • get character echo
  • 키보드 입력한 문자 하나를 반환하는 함수다. getch( )와 달리 출력(echo)한다.
  • 버퍼를 사용하지 않는다.

 

윈도우 getch( ), putch( ) 예제

#include <stdio.h>
#include <conio.h>
void main ( )
{
	int c;

	printf("한 문자를 키보드에서 입력 받음 : ");
	c = getch();
	putch(c);
}

 

리눅스 getch( ) 임의 구현 예제

#include <stdio.h>
#include <unistd.h>
#include <termios.h>

int getch();

int main(void)
{
	char ch;

	printf("한 문자를 키보드에서 입력 받음 : ");
	ch = getch();
	printf("%c\n", ch);

}

int getch()
{
    int c;
    struct termios oldattr, newattr;

    tcgetattr(STDIN_FILENO, &oldattr);           // 현재 터미널 설정 읽음
    newattr = oldattr;
    newattr.c_lflag &= ~(ICANON | ECHO);         // CANONICAL과 ECHO 끔
    newattr.c_cc[VMIN] = 1;                      // 최소 입력 문자 수를 1로 설정
    newattr.c_cc[VTIME] = 0;                     // 최소 읽기 대기 시간을 0으로 설정
    tcsetattr(STDIN_FILENO, TCSANOW, &newattr);  // 터미널에 설정 입력
    c = getchar();                               // 키보드 입력 읽음
    tcsetattr(STDIN_FILENO, TCSANOW, &oldattr);  // 원래의 설정으로 복구
    return c;
}

 

2. getchar( ), putchar( )

더보기

 

  1. C 언어 표준 입출력 함수다.
  2. 문자 하나를 입출력할때 사용하는 함수다.
  3. 표준 입출력 스트림과 스트림의 버퍼를 사용한다.

 

getchar( )

  • get character
  • 키보드 입력한 문자 하나를 반환하는 함수다. 
  • 표준 입출력 스트림 버퍼를 사용한다.

 

putchar( )

  • put character
  • 매개변수로 넘겨받은 문자 하나를 모니터로 출력하는 함수다.
  • 표준 입출력 스트림 버퍼를 사용한다.

 

#include <stdio.h>
void main ( )
{
	int c;
	printf("버퍼에 문자를 입력 받아 한 문자를 리턴 : ");
	c = getchar();
	putchar(c);
	c = getchar();
	putchar(c);
	c = getchar();
	putchar(c);
}

// 이 예제에서 3문자 이상 입력하게 되면, 버퍼에 사용되지 않은 나머지 입력값이 남아 있게 된다.

 

 

 

 

 

getchar( ), putchar( ) 사용 시 빈번한 실수

 

  • 보통  while((ch = getchar()) != '\n') 과 같은 코드를 작성해 출력하는데, 표준 입출력 함수들은 대부분 엔터까지 버퍼에 입력한다.
  • 하지만 표준 입력 스트림(stdin) 버퍼에 입력된 '\n'을 출력하지 않는 실수를 한다.
  • 단순히 해결하자면, putchar(ch)를 한 번 더 실행해 '\n' 버퍼에서 제거하면 해결된다.

 

#include <stdio.h>

void main ( )
{
    char ch, cnt;
    while((ch = getchar()) != '\n') // 버퍼에 입력한 '\n'을 putchar()로 가져오지 않는다.
    {
        putchar(ch);
            cnt++;
    }
    printf("\n입력문자 수: %d", cnt); // 문자의 수만 카운트한다. 버퍼에 남은 '\n' 카운트 제외 되었다.
    printf("\n버퍼에 남은 아스키값: %d", putchar(ch)); //버퍼에 남은 '\n'(10)의 아스키 값을 보여준다.
    //  fflush 대신 putchar(ch) 한번 더 실행하면 '\n' 로 발생한 문제는 대부분 해결된다.
}

 

3. fgetc( ), fputc( )

더보기

 

  1. C 언어 표준 입출력 함수다.
  2. 문자 하나 입출력하는 함수다.
  3. 파일 입출력 스트림 등, 명시한 스트림을 사용해 문자 하나를 입출력한다.
  4. 입출력이 성공하면, 해당 문자를 반환한다.
  5. 파일 포인터를 사용한다.

 

fgetc( )

  • file get character
  • 파일에서 문자 하나를 가져와 반환하는 함수다.
  • 파일 외, 명시된 스트림을 사용할 수 있다.
  • 출력이 성공하면, 해당 문자를 반환한다.

 

fputc( )

  • file put character
  • 파일에 문자 하나를 입력하는 함수다. 
  • 파일 외, 명시된 스트림을 사용할 수 있다.
  • 입력이 성공하면, 해당 문자를 반환한다.

 

#include <stdio.h>
void main ( )
{
	int c;

	printf("버퍼에 문자를 입력 받아 한 문자를 리턴:");
	c = fgetc(stdin);
	fputc(c, stdout);
}

 

#include <stdio.h>

int main()
{
    FILE *file;

    file = fopen("test.txt", "w");

    printf("%c", fputc('M', file)); // 파일포인터가 한칸씩 넘어간다.
    printf("%c", fputc('a', file));
    printf("%c", fputc('s', file));
    printf("%c", fputc('t', file));
    printf("%c", fputc('e', file));
    printf("%c", fputc('r', file));
    printf("\n");

    fclose(file);
}

 

#include <stdio.h>

int main()
{
    FILE *file;

    file = fopen("test.txt", "r");

    printf("%c", fgetc(file));
    printf("%c", fgetc(file));
    printf("%c", fgetc(file));
    printf("%c", fgetc(file));
    printf("%c", fgetc(file));
    printf("%c", fgetc(file));

    printf("\n");

    fclose(file);
}

 

 

5.1 파일포인터 이해

#include <stdio.h>

int main()
{
    FILE *file;


    file = fopen("test1.txt", "w");
    printf("파일 스트림 생성, 최초 파일포인터 %ld\n", ftell( file ));

    // 파일포인터가 한칸씩 넘어간다.
    printf("%c 파일포인터 %ld\n", fputc('M', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('a', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('s', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('t', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('e', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('r', file), ftell( file )); 
    
    // 파일포인터 초기화
    fseek( file, 0L, SEEK_SET ); 
    printf("파일포인터 초기화 %ld\n", ftell( file ));

    fclose(file);
}

 

#include <stdio.h>

int main()
{
    FILE *file;


    file = fopen("test1.txt", "r+");
    printf("파일 스트림 생성, 최초 파일포인터 %ld\n", ftell( file ));

    // 파일포인터가 한칸씩 넘어간다.
    printf("%c 파일포인터 %ld\n", fputc('M', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('a', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('s', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('t', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('e', file), ftell( file )); 
    printf("%c 파일포인터 %ld\n", fputc('r', file), ftell( file )); 

    // 파일포인터 초기화
    fseek( file, 0L, SEEK_SET ); 
    printf("파일포인터 초기화 %ld\n", ftell( file ));

    printf("%c 파일포인터 %ld\n", fgetc(file), ftell( file ));
    printf("%c 파일포인터 %ld\n", fgetc(file), ftell( file ));
    printf("%c 파일포인터 %ld\n", fgetc(file), ftell( file ));
    printf("%c 파일포인터 %ld\n", fgetc(file), ftell( file ));
    printf("%c 파일포인터 %ld\n", fgetc(file), ftell( file ));
    printf("%c 파일포인터 %ld\n", fgetc(file), ftell( file ));

    fclose(file);
}

 

 

5.2 fseek 사용

 

fseek( ) 함수 : 명시한 파일 스트림에서 파일 포인터의 위치를 설정한다.

 

fseek( ) 함수 원형 및 설명

int fseek( FILE *stream, long offset, int origin );
//stream : 개방된 FILE 구조체의 포인터
//offset : origin으로부터의 오프셋, 양수 또는 음수 가능
//origin : SEEK_SET, SEEK_CUR, SEEK_END 중 하나의 값
//SEEK_SET : 파일 시작점(BOF)에서 offset만큼 이동
//SEEK_CUR : 파일 포인터의 현재 위치에서 offset만큼 이동
//SEEK_END : 파일의 끝(EOF)에서 offset만큼 이동
//반환값 : 0 (실패 시 0이 아닌 값)

 

파일 크기 구하는 방법

fseek( stream, 0L, SEEK_END );
int nFileSize = ftell( stream );

 

fseek( ) 함수 사용 예제

#include <stdio.h>

int main()
{
    FILE *file;

    file = fopen("test1.txt", "r+");
    if(file == NULL){/*에러 처리*/}
    else
    {
        printf("파일 스트림 생성, 최초 파일포인터 %ld\n", ftell( file ));
        printf("%c", fputc('M', file));
        printf("%c", fputc('a', file));
        printf("%c", fputc('s', file));
        printf("%c", fputc('t', file));
        printf("%c", fputc('e', file));
        printf("%c\n", fputc('r', file));

        fseek( file, 6L, SEEK_SET );    //처음 위치에서 6번 뒤로 설정
        printf("파일포인터 %ld\n", ftell(file) );//fseek 후 파일 포인터 위치 확인

        fseek( file, -2L, SEEK_CUR );    //현재 위치(6)에서 2번 앞으로 이동
        printf("파일포인터 %ld\n", ftell(file) );//fseek 후 파일 포인터 위치 확인

        fseek( file, 0L, SEEK_END );    //파일 끝으로 이동
        printf("파일포인터 %ld\n", ftell(file) );//fseek 후 파일 포인터 위치 확인

        fclose( file );
    }

}

 

4. gets( ), puts( )

더보기

 

  1. C 언어 표준 입출력 함수다.
  2. "문자열"을 입출력하는 함수다.
  3. 표준 입출력 스트림과 스트림의 버퍼를 사용한다.
  4. 0x0A(10), #LF: 개행(Line Feed), 줄바꿈 \n, 적용을 비교한다.
  5. 입력되는 문자열의 길이를 제한하지 못하여 메모리 문제가 발생한다
    >> 최신 C언어 표준에서 제외되었으며, 가능하면 gets, puts 대신 fgets, fputs를 사용한다. 

 

gets( )

 

  • get string
  • 입력받을 버퍼의 시작 주소를 매개변수로 준다.
  • 엔터로 입력시, 개행 문자('\n') 제외하고 배열에 입력된다.
  • 엔터로 입력시, 널 문자('\0') 추가하여 배열에 문자열 상태로 입력된다.

 

puts( )

 

  • put string
  • 출력할 버퍼의 시작 주소를 매개변수로 준다.
  • 출력시, 널 문자('\0') 제외하여 문자열만 출력된다.
  •  출력시, 개행 문자('\n') 추가하여 출력된다.

 

충분한 입출력 버퍼 길이가 있는 경우

  • 문자열 입출력에 배열[20] 사용하고, 배열 크기 이하를 입력(abcdefg)하는 경우
    마지막 문자열에 사용자가 입력한 개행(  '\n'  )대신 널문자( '\0' )가 포함된다.

 

#include <stdio.h>

int main ( )
{
    char temp[20] ={0,};

    printf("문자열 입력:");
    gets(temp);
    puts(temp);   
}

 

 

충분한 입출력 버퍼 길이가 없는 경우

  • 문자열 입출력에 배열[5] 사용하는 경우
    버퍼 크기 이상의 메모리 공간에, 사용자가 입력한 문자열이 저장된다.

 

#include <stdio.h>

int main ( )
{
    char temp[5] ={0,};

    printf("문자열 입력:");
    gets(temp); //abcdefg 입력
    // puts(temp); 
    
    putchar(temp[0]); // a 입력 | idx:0
    putchar(temp[1]); // b 입력 | idx:1
    putchar(temp[2]); // c 입력 | idx:2
    putchar(temp[3]); // d 입력 | idx:3  
    putchar(temp[4]); // e 입력 | idx:4 << 배열의 마지막
    putchar(temp[5]); // f 입력 | idx:5 << 메모리 침범
    putchar(temp[6]); // g 입력 | idx:6
    printf("%d", putchar(temp[7])); // \0 입력 | idx:7 << nul 문자 추가
    printf("%d", putchar(temp[8])); // 쓰레기  | idx:8 << 입력되지 않음
    printf("\n");  
}

 

 

 

 

 

 


 

5. fgets( )fputs( ) 

더보기

 

  1. C 언어 표준 입출력 함수다.
  2. "문자열"을 입출력하는 함수다.
  3. 표준 입출력 스트림과 스트림의 버퍼를 사용한다.
  4. 0x0A(10), #LF: 개행(Line Feed), 줄바꿈 \n, 적용을 비교한다.

 

fgets( )

  • file get string
  • 입력받을 버퍼의 시작 주소를 매개변수로 준다.
  • 입력받을 버퍼의 크기를 매개변수로 준다.
  • 엔터로 입력시, 문자열 마지막에 개행 문자('\n') 포함하고 배열에 입력된다.
  • 엔터로 입력시, 문자열 마지막에 문자('\0')를 추가하여 배열에 문자열 상태로 입력된다.
  • 입력한 문자열 길이가 버퍼보다 길다면,
    명시한 크기만큼의 "문자열 +  문자( '\0' )"가 배열에 문자열 상태로 입력된다.
    그렇기 때문에, 사용자의 마지막 입력인 개행 문자('\n')가 잘린다.

 

fputs( )

  • file put string
  • 출력할 버퍼의 시작 주소를 매개변수로 준다.
  • 출력시,  문자('\0') 제외하여 문자열만 출력된다.
  • 출력시, 개행 문자('\n') 추가하여 출력된다.

 

#include <stdio.h>
void main ( )
{
	char temp[20];

	printf("문자열 입력:");
	fgets(temp, 20, stdin);
	fputs(temp, stdout);
}

 

#include<stdio.h>
int main()
{
    //write mode로 파일 스트림 생성
    FILE* pFile = fopen("test.txt", "w");
    
    //fputs로 문자열 입력, 입력된 길이를 반환
    int len = fputs("Input String",pFile);
    printf("length return : %d", len);

    fclose(pFile);
}

 

#include<stdio.h>
int main(void)
{
    //read mode로 파일 스트림 생성
    FILE* pFile = fopen("test.txt", "r");
    
    char str[100];
    
    //fgets (길이-1('\0') 만큼 버퍼로 입력)
    char* pChar = fgets(str, 5, pFile);
    printf("return : %s\n", pChar);
    printf("buffer : %s", str);
        
    fclose(pFile);
}

 


 

6. 문자열 표준 입출력 추가 비교

더보기

 

6.1  "문자열" 단위의 입력 - gets( ), fgets( )

 

#include <stdio.h>

char *gets(char *buffer);
char *fgets (char *string, int n, FILE *stream);

 

문자열을 엔터, 개행 문자('\n'), 로 입력했다면

gets( )는 개행 문자('\n') 제거, NUL('\0') 추가하여, 지정한 버퍼 배열에 저장한다. 

fgets( )는 개행 문자('\n')  포함, NUL('\0') 추가하고, 지정한 버퍼 배열에 저장한다. 

 

gets( )와 fgets( )는 사용자가 지정한 배열 버퍼의 입력 마지막 바이트에 자동으로 NUL('\0')이 추가된다.

fgets( )에서 설정한 길이에 따라 개행('\0') 추가 또는 NUL ('\0') 문자와 개행 문자('\0') 교환할 필요가 있다.

 

#include <stdio.h>
void main ( )
{
	char temp[20];

	printf("문자열 입력:"); 
	fgets(temp, 20, stdin); //abc
    
	printf("%d ", putchar(temp[0])); //a
	printf("%d ", putchar(temp[1])); //b
	printf("%d ", putchar(temp[2])); //c
	printf("%d ", putchar(temp[3])); //'\n'
	printf("%d ", putchar(temp[4])); //'\0'
}

 

 

6.2 "문자열" 단위의 출력 - puts( ), fputs( ) 

#include <stdio.h>

int puts(const char *string);
int fputs(const char *string, FILE *stream);

 

문자열을 엔터, 개행 문자('\n'), 로 입력했다면

puts( )는 개행 문자('\n') 추가하여, 출력한다.

fputs( )는 개행 문자('\n') 추가하지 않고, 출력한다.

 

puts( )는 개행 문자('\n')가 추가되어, 두 번 개행되지 않도록 신경 써야 하며,

fputs( )는 기존에 저장된 "문자열" 출력 시, 개행 문자('\n')와 NUL('\0' ) 문자가 추가되지 않아, 문자열 끝에 NUL('\0' )  이 없다면 문제가 된다. 문자열[길이]='\0' , 과 같이 임의로 추가해야 한다.

 

 

 

 

6.3 fgets( ) 개행('\0')과 NULL 처리 

 

fgets( ) 경우, 설정한 크기만큼 읽어 들여, buffer의 오버플로에 대해 안전하다.

 

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

int main(void)
{
    char buf[5];

    printf("최대 입력 크기는 5입니다.\n");
    printf("입력 >> ");
    fgets(buf, sizeof(buf), stdin); //입력 스트림에서 문자열 읽기

    printf("출력 >> [0] [1] [2] [3] [4]\n");
    printf("출력 >> %d  %d  %d  %d  %d\n", buf[0], buf[1], buf[2], buf[3], buf[4]);
    printf("출력 >> %s \n", buf);
    printf("길이 >> %d \n", strlen(buf));

    return 0;
}

 

충분한 입출력 버퍼 길이가 없는 경우

12345를 입력하는 경우, 마지막 입력인 개행이 잘리면서, 개행 문자( '\n'  )가 포함되지 않는다.

 

충분한 입출력 버퍼 길이가 없는 경우

하지만 123을 입력하는 경우, 123\0 아닌, 123\n\0 이 저장된다. '\n' 개행 이 포함된다.

 

 

'\n' 개행 문자를 '\0' NULL 문자로 변경하는 방법

buf[strlen(input) - 1] = '\0'; 

// 입력에 포함된 '\n' 개행문자를, '\0' NULL 로 변경

 

7. scanf( ), printf( )

더보기

 

gets( ), puts( ), scanf( ), prinf( ), fscanf( ), fprinf( ), sscanf( ), sprintf( )는 동일한 동작을 한다.

scanf( ), prinf( )의 차이점은 형식(format) 가변 인자를 통해, 데이터 타입을 지정할 수 있다.

 

 

scanf( )

  • scan formatted (input from stream)

printf( )

  • print formatted (output from stream)

 

일반적인 사용 예제

#include <stdio.h>
void main ( )
{
    char temp[20];
    
    printf("가변 인자를 이용한 문자열 입력: ");

    scanf("%s", temp);
    printf("%s\n", temp);
}

 


충분한 입출력 버퍼 길이가 있는 경우

  • gets( ) 함수와 동일한 동작을 한다.
  • gets( ) 와의 차이점은 형식(format) 가변 인자를 통해, 데이터 타입을 지정할 수 있다.
  • 문자열 입출력에 배열[20] 사용하고, 배열 크기 이하를 입력(abcdefg)하는 경우
    마지막 문자열에 사용자가 입력한 개행(  '\n'  )대신 널문자( '\0' )가 포함된다.
#include <stdio.h>
void main()
{
    char temp[20];

    printf("가변 인자를 이용한 문자열 입력: ");

    scanf("%s", temp); // abcdefg 입력
    // printf("%s\n", temp);

    putchar(temp[0]);               // a  입력 | idx:0
    putchar(temp[1]);               // b  입력 | idx:1
    putchar(temp[2]);               // c  입력 | idx:2
    putchar(temp[3]);               // d  입력 | idx:3
    putchar(temp[4]);               // e  입력 | idx:4 << 배열의 마지막
    putchar(temp[5]);               // f  입력 | idx:5 << 메모리 침범
    putchar(temp[6]);               // g  입력 | idx:6
    printf("%d", putchar(temp[7])); // \0 입력 | idx:7 << nul 문자 추가
    printf("%d", putchar(temp[8])); // \0 자동 초기화 | idx:8 << 입력되지 않음
    printf("\n");
}



충분한 입출력 버퍼 길이가 없는 경우

 

  • gets( ) 함수와 동일한 동작을 한다.
  • 문자열 입출력에 배열[5] 사용하고, 배열 크기 이상을 입력(abcdefg)하는 경우
    • 마지막 문자열에 사용자가 입력한 개행(  '\n'  )대신 널문자( '\0' )가 포함된다.
    • 버퍼 크기 이상의 메모리 공간에, 사용자가 입력한 문자열이 저장된다.
      >> 메모리 문제 발생한다.

 

#include <stdio.h>
void main()
{
    char temp[5];

    printf("가변 인자를 이용한 문자열 입력: ");

    scanf("%s", temp); // abcdefg 입력
    // printf("%s\n", temp);

    putchar(temp[0]);               // a  입력 | idx:0
    putchar(temp[1]);               // b  입력 | idx:1
    putchar(temp[2]);               // c  입력 | idx:2
    putchar(temp[3]);               // d  입력 | idx:3
    putchar(temp[4]);               // e  입력 | idx:4 << 배열의 마지막
    putchar(temp[5]);               // f  입력 | idx:5 << 메모리 침범
    putchar(temp[6]);               // g  입력 | idx:6
    printf("%d", putchar(temp[7])); // \0 입력 | idx:7 << nul 문자 추가
    printf("%d", putchar(temp[8])); // \0 자동 초기화 | idx:8 << 입력되지 않음
    printf("\n");
}

 

 

8. fscanf( ), fprinf( )

더보기

 

gets( ), puts( ), scanf( ), prinf( ), fscanf( ), fprinf( ), sscanf( ), sprintf( )는 동일한 동작을 한다.

fscanf( ), fprinf( ) 차이점은 입출력 스트림을 지정할 수 있다.


문자열 배열 >> 모니터 출력 : print

키보드 입력 >> 문자열 변수 : scan
문자열 배열 >> 텍스트 파일 : print

텍스트 파일 >> 문자열 변수 : scan

 

 


fscanf( )

  • file scan formatted (input from named stream)

fprintf( )

  • file print formatted (output from named stream)

 

 

 



일반적인 사용 예제

#include <stdio.h>
void main ( )
{
    char temp[20];
    
    printf("가변 인자를 이용한 문자열 입력");

    fscanf(stdin,"%s", temp);
    fprintf(stdout,"%s\n", temp);
}

 

 


문자열 값을 텍스트 파일로 내보내는 예제

#include <stdio.h>
void main ( )
{
    char temp[20] = "abcdefg";

    //write mode로 파일 스트림 생성
    FILE* pFile = fopen("test.txt", "w");

    //fputs로 문자열 입력, 입력된 길이를 반환
    int len = fprintf(pFile,"%s", temp);
    fprintf(stdout,"%s, length return : %d\n", temp, len);
    
    fclose(pFile);
}

 



텍스트 파일에서 문자열 변수로 가져오는 예제

#include <stdio.h>
void main ( )
{
    char temp[20] = "";

    //read mode로 파일 스트림 생성
    FILE* pFile = fopen("test.txt", "r");

    //fputs로 문자열 입력, 입력된 길이를 반환
    int len = fscanf(pFile,"%s", temp);
    fprintf(stdout,"%s, length return : %d\n", temp, len);
    
    fclose(pFile);
}

 

9. sscanf( ), sprintf( )

더보기


gets( ), puts( ), scanf( ), prinf( ), fscanf( ), fprinf( ), sscanf( ), sprintf( )는 동일한 동작을 한다.

sscanf( ), sprintf( )의 차이점은 형식(format) 가변 인자를 통해, 데이터 타입을 지정할 수 있다.

 


문자열 배열 >> 모니터 출력 : print

키보드 입력 >> 문자열 변수 : scan
문자열 배열 >> 텍스트 파일 : print

텍스트 파일 >> 문자열 변수 : scan

 

 


sscanf( )

  • sring scan formatted (string from named buffer)

sprintf( )

  • sring print formatted (string from named buffer)

 

 

 

기타

더보기

stderr( )

에러 메시지 출력을 제때 또는 제대로 못하게 되는 경우를 방지하기 위해, stderr 같은 경우는 버퍼 없이 바로 출력합니다. 따라서 어떤 상황에서도 가장 빠르게 에러 메시지를 출력할 수 있다.

 

EOF

End OF File의 약자로서, "파일의 끝에 도달해서 더 이상 읽을 내용이 없다."를 정의해 놓은 상수다.

fputc(), fgetc()의 경우, 호출 실패 시 EOF를 반환하도록 되어 있다.

EOF는 -1로 정의된 상수로, 반환형이 char형일 경우, unsigned char로 처리하는 컴파일러로 인해 문제가 발생한다.

이를 방지하기 위해 어떠한 상황에서도 -1을 인식할 수 있는 int형을 반환형으로 정의한다.

 

__acrt_iob_func( )

C 언어는 __acrt_iob_func() 함수를 stdin, stdout으로 재정의해서 사용한다.

FILE* __cdecl __acrt_iob_func(unsigned);
 
#define stdin  (__acrt_iob_func(0)) // stdin  = 'standard input'  표준 입력
#define stdout (__acrt_iob_func(1)) // stdout = 'standard output' 표준 출력

FILE *p_input = __acrt_iob_func(0);  // 표준 입력에 대한 포인터 의미
FILE *p_input = stdin;  

FILE *p_output = __acrt_iob_func(1); // 표준 출력에 대한 포인터 의미
FILE *p_output = stdout;  

 

#include <stdio.h>      
      
int main(void)          
{      
    FILE* pStream = stdin;      
    printf("stdin의 크기\t: %lu바이트\n", sizeof(pStream));    // 8바이트  
      
    pStream = stdout;      
    printf("stdout의 크기\t: %lu바이트\n", sizeof(pStream));    // 8바이트        
    return 0;      
}