以前的C库不好,不把C库封装成新的类
stdio中定义的FILE为指向文件的指针,假定需要安全地打开文件并且不依赖用户
调用close()来关闭它
//: C04:FileClass.h
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// stdio files wrapped.
#ifndef FILECLASS_H
#define FILECLASS_H
#include <cstdio>
#include <stdexcept>
class FileClass {
std::FILE* f;
public:
struct FileClassError : std::runtime_error {
FileClassError(const char* msg)
: std::runtime_error(msg) {}
};
FileClass(const char* fname, const char* mode = "r");
~FileClass();
std::FILE* fp();
};
#endif // FILECLASS_H ///:~
在C语言中进行文件I/O时,是使用无保护的指向FILE struct的指针来完成有关
操作,但这个类封装了文件结构指针,并且用构造函数和析构函数来确保指针
被正确地初始化和清理
为了在文件I/O函数中使用这个指针的值,可以用存取访问函数 access function
fp()取得它
//: C04:FileClass.cpp {O}
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// FileClass Implementation.
#include "FileClass.h"
#include <cstdlib>
#include <cstdio>
using namespace std;
FileClass::FileClass(const char* fname, const char* mode) {
if((f = fopen(fname, mode)) == 0)
throw FileClassError("Error opening file");
}
FileClass::~FileClass() { fclose(f); }
FILE* FileClass::fp() { return f; } ///:~
构造函数调用fopen(),而且要确保返回结果不为零,结果为零说明打开文件失败
如果文件不能正常打开,则抛出异常
析构函数用来关闭文件,而存取访问函数fp()返回指针f
使用FileClass
//: C04:FileClassTest.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
//{L} FileClass
#include <cstdlib>
#include <iostream>
#include "FileClass.h"
using namespace std;
int main() {
try {
FileClass f("FileClassTest.cpp");
const int BSIZE = 100;
char buf[BSIZE];
while(fgets(buf, BSIZE, f.fp()))
fputs(buf, stdout);
} catch(FileClass::FileClassError& e) {
cout << e.what() << endl;
return EXIT_FAILURE;
}
getchar();
return EXIT_SUCCESS;
} // File automatically closed by destructor
///:~
输出
//: C04:FileClassTest.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
//{L} FileClass
#include <cstdlib>
#include <iostream>
#include "FileClass.h"
using namespace std;
int main() {
try {
FileClass f("FileClassTest.cpp");
const int BSIZE = 100;
char buf[BSIZE];
while(fgets(buf, BSIZE, f.fp()))
fputs(buf, stdout);
} catch(FileClass::FileClassError& e) {
cout << e.what() << endl;
return EXIT_FAILURE;
}
getchar();
return EXIT_SUCCESS;
} // File automatically closed by destructor
///:~
创建一个FileClass对象并在普通的 C文件I/O函数中通过调用fp()使用它
虽然FILE指针是私有的,但它并不是特别安全,因为成员函数fp()可以检索它
如果需要得到完全的安全,就必须防止客户直接存取FILE指针
所有的I/O函数都必须作为成员函数封装在类中,使得借助于C语言能做到的每
一件事,在C++类中均可做到:
//: C04:Fullwrap.h
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Completely hidden file IO.
#ifndef FULLWRAP_H
#define FULLWRAP_H
#include <cstddef>
#include <cstdio>
#undef getc
#undef putc
#undef ungetc
using std::size_t;
using std::fpos_t;
class File {
std::FILE* f;
std::FILE* F(); // Produces checked pointer to f
public:
File(); // Create object but don't open file
File(const char* path, const char* mode = "r");
~File();
int open(const char* path, const char* mode = "r");
int reopen(const char* path, const char* mode);
int getc();
int ungetc(int c);
int putc(int c);
int puts(const char* s);
char* gets(char* s, int n);
int printf(const char* format, ...);
size_t read(void* ptr, size_t size, size_t n);
size_t write(const void* ptr, size_t size, size_t n);
int eof();
int close();
int flush();
int seek(long offset, int whence);
int getpos(fpos_t* pos);
int setpos(const fpos_t* pos);
long tell();
void rewind();
void setbuf(char* buf);
int setvbuf(char* buf, int type, size_t sz);
int error();
void clearErr();
};
#endif // FULLWRAP_H ///:~
无输出 只是一个头文件
这个类几乎包含了<cstdio>中所有的文件I/O函数
类File的构造函数有一个默认的构造函数
默认构造函数将私有FILE指针f设为0
能设想为标准 控制台 I/O和内核格式化 in-core formatting 读/写一个内存块,
而不是文件或控制台 构造相似的类
在这里遇到的绊脚石是用于可变参数列表函数 variable argument list function
的运行时解释程序