570 likes | 810 Views
입출력 시스템. C++ 입출력의 기초 포맷 입출력 width(), precision(), fill() 의 사용 입출력 조작자의 사용 삽입자의 사용 추출자의 사용. C++ 입출력의 기초 (1). 스트림 - 정보를 생산하거나 소비하는 논리적 장치 - C++ 입출력 시스템에 의하여 물리적 장치와 연결됨 - 연결된 물리적 장치들이 다르더라도 , 모두 같은 방 식으로 동작 w 화면 출력 , 파일 출력 , 프린터 출력의 방법이 동일 자동적으로 실행되는 스트림
E N D
입출력 시스템 C++ 입출력의 기초 포맷 입출력 width(), precision(), fill()의 사용 입출력 조작자의 사용 삽입자의 사용 추출자의 사용
C++ 입출력의 기초(1) • 스트림 -정보를 생산하거나 소비하는 논리적 장치 -C++입출력 시스템에 의하여 물리적 장치와 연결됨 -연결된 물리적 장치들이 다르더라도, 모두 같은 방 식으로 동작 w화면 출력, 파일 출력, 프린터 출력의 방법이 동일 • 자동적으로 실행되는 스트림 -cin : 표준 입력(키보드) -cout : 표준 출력(화면) -cerr : 표준 에러(화면) -clog : cerr의 버퍼 버전(화면)
C++ 입출력의 기초(2) • C++의 입출력 클래스(in iostream.h) -low level : streambuf class w기본적이고 낮은 단계의 입출력 연산을 지원 -high level : ios class • wformatting, 에러검사, 스트림 입출력에 관련된 상태 정 보 제공 w istream, ostream, iostream의 기본 클래스
스트림 상속 계층 ios 클래스 streambuf 클래스 일반적인 스트림 특성 구현 클래스 스트림 버퍼 객체를 가지고 있음 버퍼 메모리를 다룬다 istream 클래스 입력기능 담당 ostream 클래스 출력기능 담당 다중상속 iostream 클래스 입력과 출력기능 담당 cout 객체 cin객체 ifstream 파일로부터 버퍼에 입력 ofstream 버퍼로부터 파일에 출력
C++ 파일 입출력 • 3개의 기반 클래스 • 입력을 위한 istream 클래스 • 출력을 위한 ostream 클래스 • 입출력을 위한 iostream 클래스 • C++에서는 파일을 스트림으로 간주 • 파일 입출력을 위한 fstream 클래스 • iostream 클래스를 포함한다. • 프로그램을 시작할 때 자동으로 만들어지는 클래스 변수 • cout 객체는 ostream 클래스에서 정의한 <<연산자를 이용 • cin 객체는 istream 클래스에서 정의한 >>연산자를 이용
포맷 입출력(1) • C의 printf함수와 같이 포맷화된 출력이 가능 • 출력 포맷에 관련된 태그들이 ios클래스에 정의되어 있음
포맷 입출력(2) • 플래그 설정에 관련된 ios클래스의 멤버 함수 -long setf(long flags) w이전의 포맷 플래그들의 값을 반환하고 flags에 지정된 플래그를 설정 -long unsetf(long flags) w flags에 지정된 플래그들을 해제 (다른 플래그들은 영향을 받지 않는다.) -long flags() • w현재 포맷 플래그의 상태를 long int에 저장하여 반환 • -long flags(long f) • w f에 있는 비트들이 스트림의 포맷 플래그를 저장하는 변수 • 에 복사됨, 이전의 모든 플래그 설정 다시 함, 이전의 상태 • 반환
예제 프로그램(1) #include<iostream.h> main() { cout << 123.23 << “hello” << 100 << ‘\n’; cout << 10 << ‘’<< -10 << ‘\n’; cout << 100.0 << “\n\n”; cout.setf(ios :: hex | ios :: scientific); cout << 123.23 << “hello” << 100 << ‘\n’; cout.setf(ios :: showpos); cout << 10 << ‘’ << -10 << ‘\n’; cout.setf(ios :: showpoint | ios :: fixed); cout << 100.0; return 0; } Result :
예제 프로그램(2) #include<iostream.h> main() { cout.setf(ios :: uppercase | ios :: showbase | ios :: hex); cout << 88 << ‘\n’; cout.unsetf(ios :: uppercase); cout << 88 << ‘\n’; return 0; } Result :
예제 프로그램(3)-1 #include<iostream.h> void showflags(); main() { showflags(); cout.setf(ios :: oct | ios :: showbase | ios :: fixed); showflags(); return 0; } void showflags() { long f,i; int j; char flgs[15][12] = { “skipws”, “left”, “right”, “internal”, “dec”, “oct”, “hex”, “showbase”, “showpoint”, “uppercase”, “showpos”, “scientific”, “fixed”, “unitbuf”, “stdio” }; 뒤에 계속
예제 프로그램(3)-2 f = cout.flags(); for(i = 1, j = 0; i<=0x4000; i = i<<1, j++) if(i&f) cout << flgs[j] << “is on\n”; else cout << flgs[j] << “ is off\n”; cout << “\n”; } Result :
예제 프로그램(4)-1 #include<iostream.h> void showflags(); main() { showflags(); long f = 0x04A4; cout.flags(f); showflags(); return 0; } void showflags() { long f,i; int j; char flgs[15][12] = { “skipws”, “left”, “right”, “internal”, “dec”, “oct”, “hex”, “showbase”, “showpoint”, “uppercase”, “showpos”, “scientific”, “fixed”, “unitbuf”, “stdio” }; 뒤에 계속
예제 프로그램(4)-2 f = cout.flags(); for(i = 1, j = 0; i<=0x4000; i = i<<1, j++) if(i&f) cout << flgs[j] << “is on\n”; else cout << flgs[j] << “ is off\n”; cout << “\n”; } Result :
width(), precision(), fill()의 사용 • int width(int w) -최소 필드 너비를 지정 -w는 필드 너비이고 함수의 결과는 이전의 필드 너비가 반환된다. - 출력될 값이 출력 필드 너비를 초과하는 경우 필요한 만큼이 더해 지고, 그렇지 않은 경우 디폴트로 공백문자가 채워짐. w fill()함수를 통해서 공백문자 이외의 문자로 채울 수 있음. • int precision(int p) -유효 자리수를 설정 -p값으로 설정하고, 함수의 결과로서 이전의 값이 반환 • char fill(char ch) -ch가 채워지는 문자가 되고, 함수의 결과로서 이전의 문자가 반환
예제 프로그램 #include <iostream.h> main() { cout.width(10); cout<< “Hello" << “\n”; cout.fill('%'); cout.width(10);cout<< “Hello" << ‘\n’; cout.setf(ios::left); cout.width(10); cout << “Hello" << ‘\n’; cout.width(10); cout.precision(10); cout<< 123.234567 << ‘\n’; cout.width(10); cout.precision(6); cout<< 123.234567 << ‘\n’; return 0; } Result :
입출력 조작자의 사용(1) • 입출력 조작자 -C++입출력 시스템을 사용하여 정보를 포맷하는 다른 방법 - ios형식 플래그와 함수를 사용하는 것보다 쉬울 때가 있음. • 입출력 조작자의 사용 예 -조작자가 인수를 취하지 않을 때 괄호가 사용되지 않는다는 것 에 주의
입출력 조작자의 사용(2) • C++입출력 조작자
입출력 조작자의 사용(3) • 입출력 조작자의 사용 -입출력 문장과 함께 있는 스트림에만 미침 -ios멤버함수보다 사용하기 쉽고 간결한 코드로 작성 가능 • 예제 프로그램 #include<iostream.h> #include<iomanip.h> main() { cout << hex << 100 << endl; cout << oct << 10 << endl; cout << setfill(‘X’) << setw(10); cout << 100 << “hi” << endl; return 0; } Result :
입출력 조작자의 사용(4) Result : #include<iostream.h> #include<iomanip.h> #include<math.h> main() { double x; cout << setprecision(3); cout << “ x sqrt(x) x^2\n\n”; for(x = 2.0; x <=20.0; x++) { cout << setw(7) << x << “”; cout << setw(7) << sqrt(x) << “”; cout << setw(7) << x * x << ‘\n’; } return 0; }
삽입자의 생성(1) • C++에서는 출력연산을 삽입(insertion)이라 부르고, <<을 삽입연산자(Insertion operator)라고 한다. -삽입함수(insertion function) or 삽입자(inserter)의 생성 w << 연산자를 중복할 때를 말함 w 출력 연산자가 스트림에 정보를 삽입(insertion)하기 때문 • C++출력 연산자 << 의 중복 -사용자가 정의한 클래스에 대해서 출력 연산자를 중복할 수 있음.
삽입자의 생성(2) • 삽입자 함수의 일반적인 형식 -클래스의 멤버 함수가 아니라 friend함수로 정의 -연산자의 좌측 피연산자가 스트림이고, 우측 피연산자가 출력할 객체이기 때문
예제 프로그램(1) main() { coord a(1,1), b(10,23); cout << a << b; return 0; } #include<iostream.h> class coord{ int x, y; public : coord() { x = 0, y = 0; } coord(int i, int j) { x = i; y = j; } friend ostream &operator << (ostream &stream, coord ob); }; ostream &operator << (ostream &stream, coord ob) { stream << ob.x << “,” << ob.y << ‘\n’; return stream; } Result :
예제 프로그램(2) main() { coord a(1,1), b(10,23); cout << a << b; return 0; } #include<iostream.h> class coord{ public : int x, y; coord() { x = 0, y = 0; } coord(int i, int j) { x = i; y = j; } }; ostream &operator << (ostream &stream, coord ob) { stream << ob.x << “,” << ob.y << ‘\n’; return stream; } Result :
추출자의 생성 • 추출 연산자(extraction operator) >> 의 생성 -정보를 입력하는 동작이 데이터를 추출하는 행위와 유사 • 추출자 함수의 일반적인 형식 istream &operator>>(istream &stream, class-name &ob) { //body of inserter return stream ; } istream &stream : 입력 스트림 class-name &ob : 입력을 받아들이는 객체에 대한 참조 반환값 : istream 형 스트림의 참조
예제 프로그램(1)-1 #include<iostream.h> class coord{ int x, y; public : coord() { x = 0, y = 0; } coord(int i, int j) { x = i; y = j; } friend ostream &operator << (ostream &stream, coord ob); friend istream &operator >> (istream &stream, coord &ob); }; ostream & operator << (ostream &stream, coord ob) { stream << ob.x << “,” << ob.y << ‘\n’; return stream; }
예제 프로그램(1)-2 istream &operator >> (istream &stream, coord &ob) { cout << “Enter coordinates: ”; stream >> ob.x >> ob.y; return stream; } main() { coord a(1,1), b(10,23); cout << a << b; cin >> a; cout << a; return 0; }
예제 프로그램(2)-1 #include<iotstream.h> #include<string.h> class inventory { char item[40]; int onhand; double cost; public : inventory(char *i, int o, double c) { strcpy(item, i); onhand = o; cost = c; } friend ostream &operator << (ostream &stream, inventory ob); friend istream &operator >> (istream &stream, inventory &ob); };
예제 프로그램(2)-2 main() { inventory ob(“hammer”, 4 ,12.55); cout << ob; cin >> ob; cout << ob; return 0; } ostream &operator<<(ostream &stream, inventory ob) { stream << ob.item << “ : ” << ob.onhand; stream << “ on hand at $” << ob.cost << ‘\n’; return stream; } istream &operator>> (istream &stream, inventory &ob) { cout << “Enter item name : ”; stream >> ob.item; cout << “Enter number on hand : ”; stream >> ob.onhand; cout << “Enter cost: ”; stream >> ob.cost; return stream; }
조작자의 생성(1) • 사용자 요구에 맞는 조작자의 생성 -여러 개의 개별적인 입출력연산을 하나의 조작자로 통합시킬 때 w일련의 입출력 연산이 한 프로그램 내에서 자주 사용하는 경우 -사용자 자신의 조작자는 비표준 장치에서 입출력 연산을 수행할 필요가 있을 때 • 조작자의 유형 -입력 스트림 w인수를 갖는 조작자 w인수를 갖지 않는 조작자 -출력 스트림 w인수를 갖는 조작자 w인수를 갖지 않는 조작자
조작자의 생성(2) • 매개변수를 갖지 않는 조작자 함수의 형식
예제 프로그램(1) #include<iostream.h> ostream &setup(ostream &stream) { stream.width(10); stream.precision(4); stream.fill(‘*’); return stream; } main() { cout << setup <<123.123456; return 0; } Result :
예제 프로그램(2) #include<iostream.h> #include<iomanip.h> ostream &atn(ostream &stream) { stream << “Attention: ”; return stream; } ostream ¬e(ostream &stream) { stream << “Please Note: ”; return stream; } main() { cout << atn << “High voltage circuit\n”; cout << note << “Turn off all light\n”; return 0; } Result :
파일 입출력의 기초(1) • 파일 입출력에 관련된 클래스들 -ifstream, ofstream, fstream w istream과 ostream에서 파생됨 w istream과 ostream은 ios class에서 파생 • 파일 입출력 -스트림에 연결됨으로써 파일이 열린다. w입력, 출력, 입/출력 w ifstream in; //입력 w ofstream out; //출력 w fstream io; //입출력
파일 입출력의 기초(2) • 파일과 스트림의 연결 -open 함수의 사용
파일 입출력의 기초(3) • 파일의 access 값
파일 입출력의 기초(4) • open 함수의 사용 예 • 파일 닫기 - close()함수의 사용 • eof()함수의 사용
예제 프로그램(1) #include<iostream.h> #include<fstream.h> main() { ofstream fout("test"); if(!fout){ cout <<"cannot open output file.\n"; return 1; } fout << "Hello!\n"; fout << 100<< ‘ ’ << hex << 100 << endl; fout.close(); ifstream fin("test"); if(!fin){ cout << "Cannot open input file.\n"; return 1; } char str[80]; int i; fin >> str >> i; cout << str << ‘ ’ << i << endl; fin.close(); return 0; } Result :
예제 프로그램(2) if(!fin){ cout <<"cannot open input file.\n"; return 1; } char ch; fin.unsetf(ios::skipws): //공백문자무시안됨 while(!fin.eof()){ fin >> ch; if(ch==‘ ’) ch=‘ | ’; fout << ch; } return 0; } #include<iostream.h> #include<fstream.h> main(int argc, char *argv[]) { if(argc !=3){ cout<<"Usage : CONVERT <input><output>\n"; return 1; } ifstream fin(argv[1]); ofstream fout(argv[2]); if(!fout){ cout<<"cannot open output file.\n"; return 1; }
포맷되지 않은 2진 입출력 • 2진 파일 입출력 함수 -가장 낮은 단계의 2진 입출력 함수 w istream &get(char &ch) 관련된 스트림으로부터 한 문자를 읽어들임 w ostream &put(char ch); 스트림에 ch를 기록 -2진 데이터의 블록 읽기 / 쓰기 w istream &read(unsigned char *buf, int num) num 만큼의 바이트를 읽어 buf가 가리키는 버퍼에 저장 num 만큼의 문자를 읽기 전에 파일의 끝에 도달하면 멈춤 w ostream &write(const unsigned char *buf, int num) buf가 가리키는 버퍼로부터 num만큼의 바이트를 연결된 스트림에 저장 w int gcount() 함수 2진 입력에 의해 읽혀진 문자의 수를 반환
예제 프로그램(1) #include<iostream.h> #include<fstream.h> main(int argc, char*argv[]) { char ch; if(argc !=2){ cout << "Usage : PR<filename>\n"; return 1; } ifstream in(argv[1]); if(!in) { cout<<"cannot open file\n"; return 1; } while(!in.eof()){ in.get(ch); cout << ch; } return 0; }
예제 프로그램(2) #include<iostream.h> #include<fstream.h> #include<string.h> main() { ofstream out("test"); if(!out){ cout<<"cannot open output file.\n"; return 1; } double num = 100.45; char str[]="This is a test"; out.write((char *)&num, sizeof(double)); out.write(str, strlen(str)); out.close(); return 0; }
예제 프로그램(3) #include<iostream.h> #include<fstream.h> main() { ofstream out("test"); if(!out){ cout<<"cannot open output file.\n"; return 1; } double nums[4]={ 1.1, 2.2, 3.3, 4.4 }; out.write((char *)nums, sizeof(nums)); out.close(); ifstream in("test"); if(!in){ cout << "cannot open input file.\n"; return 1; } in.read((char *)&nums, sizeof(nums)); int i; for(i=0; i<4; i++) cout << nums[i] <<‘ ’; cout << '\n'; cout << in.gcount()<<"characters read\n"; in.close(); return 0; } Result :
2진 입출력 함수(1) • istream &get(char *buf, int num, char delim='\n') -num만큼의 문자를 읽어 들이거나 delim가 지정하는 식별문자를 만날때까지 읽어들임. • int get() -스트림으로부터 다음 문자를 반환 • istream &getline(char *buf, int num, char delim='\n') -num만큼의 문자를 읽어 들이거나 delim 에 지정된 식별 문자를 만 날 때 까지 입력으로부터 문자를 읽어 들여 buf가 가리키는 배열에 저장.
2진 입출력 함수(2) • int peek() -스트림에 있는 다음 문자를 반환하거나, 파일의 끝에 도달하면 EOF를 반환 • istream &putback(char c) -스트림으로 부터 읽어들인 마지막 문자를 다시 그 스트림에 반환 • ostream &flush() -버퍼가 가득차기 전에 정보를 디스크에 기록
2진 입출력 함수(3) #include<iostream.h> #include<fstream.h> main() { char str[80]; cout << "Enter your name:"; cin.getline(str, 79); cout << str << '\n'; return 0; } Result :
2진 입출력 함수(4) #include<iostream.h> #include<fstream.h> #include<ctype.h> #include<stdlib.h> main(){ char ch; ofstream out("test"); if(!out){ cout<<"cannot open output file.\n"; return 1; } char str[80], *p; out << 123 << “this is a test” << 23; out << “Hello there!” << 99 << “sdf” << endl; out.close(); ifstream in("test"); if(!in){ cout << "cannot open inpt file.\n"; return 1; } 뒤에 계속
2진 입출력 함수(5) Result : do { p=str; ch=in.peek(); if(isdigit(ch)){ while(isdigit(*p = in.get())) p++; in.putback(*p); *p = '\0'; cout << “Integer:” << atoi(str); } else if(isalpha(ch)){ while(isalpha(*p = in.get())) p++; in.putback(*p); *p = '\0'; cout << “string:” <<str; } else in.get(); cout << '\n'; } while( !in.eof()); in.close(); return 0; }
임의 접근(1) • 파일의 입출력 포인터의 위치 변경 -istream &seekg(streamoff offset, seek_dir orign) -ostream &seekp(streamoff offset, seek_dir orign) w streamoff : offset이 가질 수 있는 최대 유효값을 포함 w seek_dir의 값 - 파일에 관련된 두가지 포인터 w입력 포인터(get pointer) w출력 포인터(put pointer)
임의 접근(2) • 파일의 두 포인터에 대한 현재 위치 알아내기 - streampos tellg() - streampos tellp()
예제 프로그램 Result : #include<iostream.h> #include<fstream.h> #include<stdlib.h> main(int argc, char *argv[]) { char ch; if(argc !=3){ cout <<"Usage : LOCATE<filename><loc>\n"; return 1; } ifstream in(argv[1]); if(!in){ cout << "cannot open input file.\n"; return 1; } in.seekg (atoi(argv[2]), ios :: beg); while(!in.eof()) { in.get(ch); cout << ch; } in.close(); return 0; }