C++编程学习笔记 复习/拾遗 4
类和对象应用
基于项目的多文件管理
- 将类的设计与类的使用分离
类定义与main函数(类测试) 不在一个文件中。
- 将类的声明和类的成员函数实现分离
类定义与成员函数定义
不在一个文件中
优点:
便于分工合作
便于软件的维护。
例5.1:设计一个圆类,并计算圆的面积
//类的定义(Circle.h文件)
class Circle
{
public:
Circle(double a=0);
double Area();
protected:
double r;
};
//类的成员函数实现( Circle.cpp文件)
#include "Circle.h"
Circle::Circle(double a)
{
r=a;
}
double Circle::Area()
{
return 3.14*r*r;
}
// 主函数(main.cpp文件)
#include <iostream>
#include "Circle.h"
using namespace std;
int main()
{
Circle c(5);
cout<<c.Area()<<endl;
return 0;
}
步骤
1、创建一个控制台类型的项目L5.1,带一个main.cpp文件,其内容是main函数
2、在L5.1工程中为circle类创建2个文件(circle.h和circle.cpp文件)
1)在项目管理面板的项目名L5.1上右键单击,选择新建文件,添加新文件,如图所示。
注意手动操作,新建的文件与项目文件要保存在同一个目录下。
2)文件->新建->新建一个类,或者查看类面板上右键单击,选择新建类,如图所示:
系统自动加了框架代码。
- 输入类名circle
- 输入构造函数参数
- 勾选创建构造函数
- 默认文件名circle.cpp及circle.h
- 单击新建类的对话框中的创建按钮,即为circle类创建了2个文件
最后按照例5.1代码所在文件情况,依次添加到相应位置:
实例
#include <iostream>
#include <string>
using namespace std;
class student
{
public:
void output();
void set(const string &p,int i,double x,double y)//[4]
{ name=p; num=i; m_c=x; m_math=y;}
double jstotal()//[5]
{ return m_c+m_math; }
student(const string &p="wang",int i=1,double x=0,double y=0)//[7]
{ name=p; num=i; m_c=x; m_math=y;}
private:
string name;//姓名
int num ; //学号
double m_c;//语文成绩
double m_math;//数学成绩
};
void student::output()
{
cout<<"姓名:"<<name<<","<<"学号:"<< num<<","
<<"语文:"<< m_c<<","<<"数学:"<< m_math <<endl;//[4]
}
int main()
{
//string x("wang");//等价于string x="wang";
//student s;//[1]定义对象
//s.set(x,1,85.5);//[2]设置学生数据
//s.output();//[3]输出学生数据
//s.set(x,1,92.1);//[4]修改学生成绩数据
//cout<<"总成绩:"<<s.jstotal()<<endl;//[6]
student t;//[8]定义对象t
t.output();//[8]输出学生数据
cout<<"总成绩:"<<t.jstotal()<<endl;//[8]
student z("liuxiang",2,100,95);//定义对象z
z.output();
cout<<"总成绩:"<<z.jstotal()<<endl;
return 0;
}
student.h:类定义
#include <string>
using namespace std;
class student
{
public:
void output();
void set(const string &p,int i,double x,double y);
double jstotal();
student(const string &p="wang",int i=1,double x=0,double y=0);
protected:
string name;//姓名
int num ; //学号
double m_c;//语文成绩
double m_math;//数学成绩
};
student.cpp:成员函数定义
#include "student.h"
#include <iostream>
#include <string>
using namespace std;
void student::output()
{
cout<<"姓名:"<<name<<","<<"学号:"<< num<<","
<<"语文:"<< m_c<<","<<"数学:"<< m_math <<endl;//[4]
}
void student::set(const string &p,int i,double x,double y)//[4]
{ name=p; num=i; m_c=x; m_math=y;}
double student::jstotal()//[5]
{ return m_c+m_math; }
student::student(const string &p,int i,double x,double y)//[7]
{ name=p; num=i; m_c=x; m_math=y;}
项目:main.cpp:类测试
#include <iostream>
#include <string>
#include "student.h"
using namespace std;
int main() {
//string x("wang");//等价于string x="wang";
//student s;//[1]定义对象
//s.set(x,1,85.5);//[2]设置学生数据
//s.output();//[3]输出学生数据
//s.set(x,1,92.1);//[4]修改学生成绩数据
//cout<<"总成绩:"<<s.jstotal()<<endl;//[6]
student t;//[8]定义对象t
t.output();//[8]输出学生数据
cout<<"总成绩:"<<t.jstotal()<<endl;//[8]
student z("liuxiang",2,100,95);//定义对象z
z.output();
cout<<"总成绩:"<<z.jstotal()<<endl;
return 0;
}
系统这些头文件中的内容包含是因为系统这些头文件中的内容包含ifndef或者#pragma once,该宏就是为了避免同一个头文件被include多次时,不会出现重定义的错误。
输入/输出流类的继承层次结构
iostream类库提供了数百种I/O功能,其接口部分分别包含在几个头文件中:
无格式I/O和格式化I/O:头文件iostream
格式化I/O :包含头文件iomanip
文件处理操作 :包含头文件fstream
注意:iostream属于多继承
文件操作
- 文件和流
C++把每一个文件都看成一个有序的字节流,对文件的操作可采用与输入输出流相关的方法。
头文件fstream包含了流类ifstream(从文件输入)、ofstream(向文件输出)和fstream(从文件输入/输出)的定义。
- 文件的处理由三个步骤组成:打开文件,读写,关闭文件。
- 打开文件,两种方法:
1)先建立文件流对象,再调用成员函数open()将它与某一个文件关联 ifstream infile; // 输入文件流对象
infile.open(“a.txt”); infile.open(“a.dat”,ios::binary); //打开读二进制文件
2)在建立文件流对象的同时通过构造函数来打开文件。如:
ifstream infile (“a.txt”);
ifstream outfile(“a.dat”,ios::binary);//打开读二进制文件 测试文件是否被正确打开的方法如下: if ( ! infile) { … // 处理文件打开失败情况的代码 }
-
关闭文件:成员函数close()
infile.close( );//等价于if(!infile.is_open())或if(!infile.fail())
- 打开文件,两种方法:
1)先建立文件流对象,再调用成员函数open()将它与某一个文件关联
ofstream outfile; // 输出文件流对象
outfile.open("a.txt ");
outfile.open(“a.txt”,ios::binary); //打开写二进制文件
2)在建立文件流对象的同时通过构造函数来打开文件。如:
ofstream outfile (“a.txt”);
ofstream outfile(“a.dat”,ios::binary);//打开写二进制文件
测试文件是否被正确打开的方法如下:
if ( ! outfile)
{ …// 处理文件打开失败情况的代码
} - 关闭文件:成员函数close()
outfile.close( );//等价于if(!outfile.is_open())或if(!outfile.fail())
- 打开文件,两种方法:
1)先建立文件流对象,再调用成员函数open()将它与某一个文件关联
fstream iofile; // 输入输出文件流对象
iofile.open(文件名,文件打开方式);//不能省略
2)在建立文件流对象的同时通过构造函数来打开文件。文件打开方式不能省略。如下:
fstream iofile(文件名, ios::in);//读文本文件
fstream iofile(文件名, ios::out);//写文本文件
fstream iofile(文件名, ios::in|ios::binary);//读二进制文件
fstream iofile(文件名, ios::out|ios::binary);//写二进制文件
测试文件是否被正确打开的方法如下:
if ( ! iofile)
{ … // 处理文件打开失败情况的代码
} - 关闭文件:成员函数close()
iofile.close( );//等价于if(!iofile.is_open())或if(!iofile.fail())
文本文件的读写
使用插入与提取运算符对文本文件进行读写
例5.3:写文本文件示例
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream outfile("d:\\grade.txt");
//等价于:fstream outfile("d:\\grade.txt",ios::out);
//写文本文件
if(!outfile)
{
cout << "文件打开失败!"<<endl;
return 1;
}
outfile << "程序设计" << " " << 95 << endl;
outfile << "大学英语" << " " << 90.5 << endl;
outfile << "高等数学" << " " << 93 << endl;
outfile << "普通物理" << " " << 87.5 << endl;
outfile.close();
return 0;
}
例5.4:读文本文件示例
#include <iostream>
#include <fstream>
using namespace std;
int main()
{ ifstream infile("d:\\grade.txt");
//等价于:fstream infile(“d:\\grade.txt”,ios::in);
//读文本文件
if(!infile)
{
cout << "文件打开失败!"<<endl;
return 1;
}
char course[20];
float score;
infile >> course >> score;
cout << course << " " << score << endl;
infile >> course >> score;
cout << course << " " << score << endl;
infile >> course >> score;
cout << course << " " << score << endl;
infile >> course >> score;
cout << course << " " << score << endl;
infile.close();
return 0;
}
例5.5 使用成员函数get()完成读文本文件操作
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char ch;
int count=0; // 计数器
ifstream infile("d:\\grade.txt");
//等价于:fstream infile("d:\\grade.txt",ios::in);
//读文本文件
if(!infile)
{
cout << "文件打开失败"<<endl;
return 1;
}
while(!infile.eof( ))
{
infile.get(ch); // 从文件流中读入下一个字符
cout<<ch; // 屏幕输出从文件中读入的字符
if(ch>='0' && ch<='9') count++; // 若是数字字符,计数器加1
}
cout<<endl<<"文件中共有数字字符:"<<count<<"个。"<<endl;
infile.close();
return 0;
}
例5.6: 打开一个由若干个整数组成的文本文件“number.txt”,找出其中所有的质数并存入另一个文本文件“prime.txt”中。
#include <iostream>
#include <fstream>
using namespace std;
int isprime(int a) // 素数判别函数
{ for(int i=2; i<=a/2; i++)
if(a%i == 0) return 0;
return 1;
}
int main()
{ ifstream infile("number.txt");
ofstream outfile("prime.txt");
if(!infile || !outfile)
{ cout << "文件打开失败!"<<endl;
return 1;
}
int num;
while(!infile.eof() )
{ infile>>num;
if(isprime(num)) outfile<<num<<" ";
}
infile.close();
outfile.close();
return 0;
}
二进制文件
二进制文件以位(bit)为单位,整个文件是由0和1组成的无格式的原始数据序列。在二进制方式下的输入输出过程中,系统不对数据进行任何转换。
文本文件以字节(byte)为单位,整个文件实际保存的是一串ASCII字符。可用文字处理器进行编辑。在文本方式下的输入输出过程中,系统进行字符转换。
二进制文件读写
二进制文件的读写比文本文件复杂,不能用插入或提取符。
①put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比较简单,如file1.put(‘c’);就是向流写一个字符’c’。
②get()函数从流读入字符或者字符串,比较灵活,有3种常用的重载形式。
③读写数据块 要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:
read(unsigned char *buf,int num);
write(const unsigned char *buf,int num);
read()从文件中读取 num 个字符到 buf 指向的缓存中
write() 从buf 指向的缓存写 num 个字符到文件中
// 例5.7:二进制文件拷贝的程序
#include <iostream>
#include <fstream>
using namespace std;
int main()
{ char s[50], d[50];
cout<<"请输入准备复制的文件名(含后缀名):";
cin>>s;
cout<<"请输入新生成的文件名(含后缀名):";
cin>>d;
ifstream infile(s, ios::binary);
ofstream outfile(d, ios::binary);
if(!infile || !outfile)
{ cout << "文件打开失败!"<<endl;
return 1;
}
int num;
while(!infile.eof() )
{ infile.read ((char*)&num,sizeof(num));// 成员函数read( )用于从输入流中读取一个整数
outfile.write((char*)&num,sizeof(num));// 成员函数write( )将读入的整数num写到输出流中
}
infile.close();
outfile.close();
return 0;
}