데이터의 입력과 출력은 프로그램의 흐름을 뜻하는 것이다.
프로그램을 중심으로 프로그램 안으로 데이터가 흘러들어오는 것이 입력이고
프로그램 밖으로 데이터가 흘러 나가는 것이 출력이다.
대표적인 입력장치로 키보드가 있으며, 파일도 입력의 대상이 될 수 있다.
대표적인 출력장치로 모니터가 있으며, 파일 역시 출력의 대상이 될 수 있다.
모니터와 키보드는 연결되어있는 개체가 아닌, 서로 떨어져 있는 개체이다. 따라서 프로그램 상에서 모니터와 키보드를 대상으로 입출력하기 위해서는 이들을 연결시켜주는 다리가 필요하다. 그리고 이러한 다리의 역할을 하는 매개체를 가리켜 '스트림(Stream)'이라 한다.
스트림은 출력 스트림과 입력스트림으로 나눠져 있다.
콘솔(키보드 와 모니터) 입출력과 파일 입출력 사이에는 차이점이 있다.
파일과의 연결을 위한 스트림의 생성은 우리가 직접 요구해야 하지만, 콘솔과의 연결을 위한 스트림의 생성은 요구할 필요가 없다.
즉 콘솔 입출력을 위한 '입력 스트림'과 '출력 스트림'은 프로그램이 실행되면 자동으로 생성되고, 프로그램이 조욜되면 자동으로 소멸되는 스트림이다.
즉, 이 둘은 기본적으로 제공되는 '표준 스트림(Standard Stream)'이다.
stdin 표준 입력 스트림 키보드 대상으로 출력
stdout 표준 출력 스트림 모니터 대상으로 출력
stderr 표준 에러 스트림 모니터 대상으로 출력
문자 출력 함수
#include <stdio.h>
int putchar (int c);
int fputc(int c, FILE *stream);
->함수 호출 성공시 쓰여진 문자정보가 출력되고, 실패시 EOF를 반환한다.
puchar함수는 인자로 전달된 문자정보를 stdout으로 표현되는 표준 출력 스트림으로 전송하는 함수이다 .따라서 인자로 전달된 문자를 모니터로 출력하는 함수이다 .
fputc 함수도 putchar와 동일한데, 다만 fputc함수는 문자를 전송할 스트림을 지정할 수 있다.
즉 파일을 대상으로도 데이터를 전송할 수 있다는 것이다.
문자 입력 함수
#include <stdio.h>
int getchar(void);
int fgetc(FILE *stream);
->파일의 끝에 도달하거나, 함수 호출 실패시 EOF반환
getchar함수는 stdin으로 표현되는 표준 입력 스트림으로부터 하나의 문자를 입력 받아서 반환하는 함수이다. 따라서 키보드로부터 하나의 문자를 입력 받는 함수라 할 수 있다.
fgetc함수도 getchar와 동일한데 , 다만 입력 받을 스트림을 지정할 수 있다.
#include <stdio.h>
int main()
{
int ch1, ch2;
ch1 =getchar(); //문자입력
ch2 =fgetc(stdin); //엔터 키 입력
putchar(ch1); //문자출력
fputc(ch2, stdout); //엔터 키 출력
return 0;
}
=================================실행결과===========================
p
p
위의 예제상에는 분명 두 개의 문자를 입출력하고있다. 그런데 실행 결과만 놓고 보면 , 하나의 문자만 입력과 출력이 된것으로 보인다. 실제로는 엔터키도 입력과 출력이 되었다 . 눈에 보이지 않을 뿐이다 .
'엔터 키'도 아스키 코드 값이 10인 '\n'으로 표현되는 문자이다.
EOF는 End of File의 약자로서, 파일의 끝을 표현하기 위해서 정의해 놓은 상수이다. 따라서 파일을 대상으로 fgetc함수가 호출되면, 그리고 그 결과로 EOF가 반환되면, 이는 '파일의 끝에 도달해서 읽을 내용이 없다'라는 뜻이다.
키보드를 대상으로 하는 fgetc함수와 getchar함수가 EOF를 반환하는 시기는
1. 함수 호출의 실패
2. Windows에서 CTRL +Z키, Linux에서 CTRL + D키가 입력되는 경우이다.
키보드의 입력에서는 '파일의 끝'이 존재하지 않기 때문에 EOF반환 시기를 별도로 약속한 것이다.
int getchar(void);
int fgetc(FILE *stream);
반환되는 것은 1바이트 크기의 문자인데 반환형이 int이다.
두 함수가 반환하는 값중 하나인 EOF는 -1로 정의된 상수이다.
printf와 scanf 함수를 이용해도 문자열의 입출력이 가능하다. scanf함수는 공백이 포함되는 문자열을 입력 받는데 제한이 있다.
문자열 출력
#include <stdio.h>
int puts(const char * s);
int fputs(const char *s, FILE *stream);
->출력 성공시 음수가 아닌 값을 , 실패시 EOF를 반환한다.
puts는 출력의 대상이 stdout으로 결정되어 있지만 fputs함수는 출력의 대상을 결정 할 수 있다 .
그리고 둘 다 첫번째 인자로 전달되는 주소 값의 문자열을 출력하지만, 출력의 형태에 있어 차이점이 있다.
puts함수가 호출되면 문자열 출력후 자동으로 개행이 이뤄지지만, fputs함수가 호출되면 문자열 출력 후 자동으로 개행이 이뤄지지 않는다 .
문자열 입력 함수
#include <stdio.h>
char * gets(char *s); //현재 비쥬얼 스튜디오에서 이 함수는 삭제되었다.
char *fgets(char *s , int n, FILE *stream);
->파일의 끝에 도달하거나, 함수 호출 실패시 NULL포인터를 반환
int main(){
char str[7];
fgets(str, sizeof(str), stdin); //stdin으로부터 문자열을 입력 받아서 str에 저장
}
위의 fgets함수 호출이 의미하는 바는 다음과 같다.
stdin으로부터 입력을 받아서 sizeof(str)의 길이만큼 배열 str에 저장
sizeof(str)의 반환 값보다 하나 작은 길이의 문자열만 읽어서 str에 저장하게 된다.
왜냐하면 널문자의 저장을 위해 공간을 남겨두는 것이다 .
문자열을 입력 받으면 자동으로 문자열의 끝에 널 문자가 추가가 된다.
따라서 하나 작은 길이의 문자열이 젖아되는 것이다.
fgets함수는 \n을 만날 때 까지 문자열을 읽어 들이는데, \n을 제외시키거나 버리지 않고 문자열의 일부로 받아들인다.
즉 엔터 키의 정보까지도 문자열의 일부로 저장되는 것이다 .
fgets함수를 호출해 만약 Good을 입력했다고 가정하자.
메모리공간에 저장된 상태를 보면
G | o | o | d | \n | 0 |
이렇게 저장되어 있다. 즉 fgets함수는 엔터키(줄바꿈)도 읽어들여서 배열에 저장하게된다.
printf와 scanf, fputc와 fgetc 모두 표준 입출력 함수이다.
표준 입출력 함수를 통해서 데이터를 입출력 하는 경우, 해당 데이터들은 운영체제가 제공하는 '메모리 버퍼'를 중간에 통과하게 된다.
메모리 버퍼란 데이터를 임시로 모아두는 메모리 공간이다.
키보드를 통해 데이터를 입력한다 하면, 입력 버퍼에 저장된 다음에 프로그램에서 읽혀진다. 즉 fgets함수가 읽어 들이는 문자열은 입력버퍼에 저장된 문자열이다. 키보드로부터 입력된 데이터가 입력스트림을 거쳐서 입력 버퍼로 들어가는 시점은 엔터키가 눌리는 시점이다.
그래서 키보드로 문자열을 입력해도 엔터 키가 눌리기 전에는 fgets함수가 문자열을 읽어 들이지 못하는 것이다. 엔터 키가 눌리기 전에는 입력버퍼가 비워져 있기 때문이다.
버퍼링을 하는 이뉴는 데이터 전송의 효율성과 관련이 있다.
데이터를 버퍼에 둬서 데이터를 한데 묶어서 이동하는 것이 보다 효율적이고 빠르기 때문이다.
출력버퍼 비우는 함수
출력버퍼가 비워진다는 것은 출력버퍼에 저장된 데이터가 버퍼를 떠나서 목적지로 이동됨을 뜻한다.
하지만 시스템에 따라 , 버퍼의 성격에 따라 버퍼가 비워지는 시점이 동일하지 않기 때문에 출력버퍼 함수를 알아둬야 한다.
#include <stdio.h>
int fflush(FILE *stream);
->함수 호출 성공시 0, 실패시 EOF반환
fflush(stdout); //표준 출력 버퍼를 비움
어떠한 시스템의 표준 출력버퍼라도 버퍼에 저장된 내용이 비워지면서 데이터가 목적지로 이동한다.
위 함수는 파일을 대상으로도 호출이 가능하다. 인자로 파일의 스트림정보가 전달되면, 해당 버퍼에 저장되어 있던 데이터들이 버퍼를 떠나서 파일에 기록이 된다.
입력버퍼 비우기
입력버퍼에 지워짐은 데이터의 소멸을 의미한다.
fflush는 출력버퍼를 대상으로 하는 호출하는 함수이다.
일반적으로 입력버퍼를 비울때 사용하는 함수는
getchar()함수이다.
getchar함수는 \n을 만날때까지 읽어들이는 함수이다. 물론 이 함수가 읽어들인 문자를 저장하거나 하지는 않는다.
특히 엔터키의 입력을 지울때 많이 사용된다 .
배열의 길이를 7로 선언하고 6자리를 입력했다고 가정하자.
문자열이기 때문에 마지막에는 널문자가 자동으로 붙는다 . 하지만 6자리를 입력하고 엔터키를 누르면 8자리가 되서 오류가 생긴다. 이때문에 입력버퍼를 비우기 위해 getchar()함수를 \n이 읽혀질때까지 호출되게 하면 입력버퍼에 남아있던 엔터 키는 소멸하게 된다.
또한 위 함수를 사용하면 필요한 만큼까지만 읽어들이고 나머지는 지워버리기 때문에 잘못입력해도 그 길이만 맞춰서 출력이 된다.
'휴지통 > C 언어' 카테고리의 다른 글
구조체 (0) | 2021.02.04 |
---|---|
문자열 입력 함수 (0) | 2021.02.02 |
함수 포인터, void 포인터 (0) | 2021.01.31 |
다차원 배열과 포인터, 다중 포인터 (0) | 2021.01.30 |
1차원 배열, 포인터 (0) | 2021.01.23 |