C++<五>
//---------------------------------------------------------------------
//写一个复制文件的程序;CP 文件名,复制文件名;
*/
/*
#include<iostream>
using namespace std;
#include<fstream>
int main()
{
ifstream fin("am.cpp");
ofstream fout("b.txt");
for(;;){
if(!fin)break;
fout<<(char)fin.get();
}
fout.close();
fin.close();
}
/*
//;C字符风格:getline();cin.getline(字符数组名,长度),要保证长度够用(比一行的实际长度要长)
//C++: getline(cin,str); c风格和C++风格都含有默认第三个参数
// getline(in,str,'\n'); in.getline(buf,len,'\n');
//可以自己制定第三个参数;第三个参数制定结束字符,默认为'\n';
*/
/*
#include<iostream>
using namespace std;
#include<string>
int main()
{
string str;
char buf[20];
cout<<"input a line:";
getline(cin,str);
cout<<"str="<<str<<endl;
cout<<"input a line (<20):";
cin.getline(buf,20);
cout<<"buf="<<buf<<endl;
if(!cin){
cout<<"read error state "<<endl;
cin.clear();//恢复到正常状态,不是清缓存区;
}//一旦处于错误状态,则不再执行任何输入;
//可以用 while(cin.get()!='\n');来清空缓存区
char n=0;
cout<<"input an integer:";
cin>>n;
cout<<"n="<<n<<endl;
}//cin.ignore(长度,'\n'):清除缓存区,长度一定要够。
/*
void istream::ignore(int len=1,char c=-1)
//两个形参都有默认值
{
for(int i=0;i<len;i++){
if(cin.get()==c) break;
}
}//cin.ignore(),cin.ignore(5);cin.ignore(100,'\n');
//for(int i=0;i<len&&get()!=c;++i){}
*/
/*
#include<iostream>
using namespace std;
#include<fstream>
#include<string>
int main()
{
ifstream fin("a.txt");
string str;
getline(fin,str,':');
cout<<"username:"<<str<<endl;
getline(fin,str,':');
cout<<"password:"<<str<<endl;
getline(fin,str,':');
cout<<"user id:"<<str<<endl;
getline(fin,str,':');
cout<<"group id:"<<str<<endl;
getline(fin,str,':');
cout<<"home:"<<str<<endl;
getline(fin,str);
cout<<"shell:"<<str<<endl;
}
//利用getline可以实现多行的输入;
*/
//-----------------------------------------------------------------
//【peek】 偷看输入流中下一个字符,返回他的ASCII码(整数)
/*
#include<iostream>//不会读走
using namespace std;
#include<string>
int main()
{
cout<<"input No.or name:";
int no;
string name;
char ch=cin.peek();//peek()不会将数据读走;
if(ch>='0'&&ch<='10'){
cin>>no;
cout<<"no="<<no<<endl;
}
else {
getline(cin,name);
cout<<"name="<<name<<endl;
}
}
*/
//【putback】将已经读走的字符送回;
/*
#include<iostream>
using namespace std;
int main()
{
char ch;
int n;
cout<<"input an intefer:";
cin.get(ch);
cin>>n;
cout<<"ch="<<ch<<endl;
cout<<"n="<<n<<endl;
cin.ignore(1000,'\n');
cout<<"input an integer:";
cin.get(ch);
cin.putback(ch);
cin>>n;
cout<<"ch="<<ch<<endl;
cout<<"n="<<n<<endl;
}
*/
//【cin.width(10)】 限定宽度, 只读取前面10个字符
// cin>>ws; 跳过输入缓冲区中的空白字符
//-----------------------------非格式化输出-----------------------
/*
【put(char)】:用来输出一个字符(一定是一个字符)
cout<<cin.get() :输出的是一个整形
cout.put(cin.get()): 输出的一定是一个字符
【fout.write(地址,字节数)】 :把一块内存空间的类容写入到文件中
【fin.read(char* 地址, int字节数)】:把文件中的内容读到一块内存空间中;总是需要类型转换。
*/
/*
#include<iostream>
using namespace std;
#include<fstream>
int main()
{
int n=0;
double d=0.0;
struct s{
char c;
bool b;
char addr[100];
};
s s={'\0',0," "};
class A{
int data;
public:
A(int d=0):data(d){}
void show() const{
cout<<"data="<<data<<endl;
}
};
A a(0);
ifstream fin("var.dat");
fin.read((char*)&n,sizeof(n));
fin.read((char*)&d,sizeof(d));
fin.read((char*)&s,sizeof(s));
fin.read((char*)&a,sizeof(a));
fin.close();
cout<<"n="<<n<<endl;
cout<<"d="<<d<<endl;
cout<<"s.c="<<s.c<<endl;
cout<<"s.b="<<s.b<<endl;
cout<<"s.addr="<<s.addr<<endl;
a.show();
}
*/
//---------------day_13_AM-------------
//回顾:IO,控制台(c) cin,cout,cerr,clog,文件(f):自己来创建
//ifstream fin("文件名")/ ofstream fout("文件名"); 用完之后都要:fout.close()/fin.close();
//控制台与文件输入输出是一样的;cin.get() 返回的是ASCII码; 程序出错额可以用return -1来表示
//main函数中的return值对程序没有影响、 return 0表示程序执行正确
//EOF (end of file)、get(char&)返回IO对象而不是ASCII码;getline(cin,str)
//getline 有第三个参数, 默认为'\0';可以自己设定结束符;会把结束符读走但不放入字符串中
//read(内存地址, 字节数)从文件中将指定字节数读入到指定内存中
//clear() 来恢复到正确状态, ignore()恢复缓存区,peek()偷看,不会将数据读走, putback()
// write(内存地址, 字节数),将内存中的数据写到文件中。必须有类型转换 write((char*)地址,字节数)
//必须有强制类型转换。
// 【cin/fin.gcount() 可以取得读到多少个字节】 read()不会自动加'\0'; (!fin)/fin.eof()来判断是否读到了文件末尾
//若出错,则可以用clear()恢复到正确状态;
//输出格式控制,宽度;width(int n) 指定宽度输出;如果指定宽度不够的时候不会丢失数据,会按实际宽度输出
//指定宽度的默认值为0,所以总是默认按实际宽度输出,, 而且指定宽度是一次性的,只对下一个输出有效;
//fill('填充字符'),默认值为空格;填充字符永久有效。
/*
#include<iostream>
using namespace std;
int main()
{
cout.width(10);
cout<<123<<endl;
cout<<456<<endl;
cout.width(1);// 指定宽度是一次性的,只对下一次输出有效
cout<<123<<endl;
cout.width(10);
cout.fill('*');//填充字符是永久有效的
cout<<123<<endl;
cout.width(10);
cout<<123<<endl;
}
*/
/*
#include<iostream>
using namespace std;
class Wf{
int w;
char f;
public:
Wf(int w,char f):w(w),f(f){}
friend ostream& operator<<(ostream& os,const Wf&o){
os.width(o.w);
os.fill(o.f);
return os;
}
};
int main()
{
Wf o(10,'*');
cout<<Wf(10,'*')/*控制格式<<123<<endl;//输出格式控制符
cout<<Wf(8,' ')<<123<<endl;
}
*/
/*
#include<iostream>
using namespace std;
int main()
{
double d=123.456789;
cout<<"d="<<d<<endl;
cout.precision(8);//指定精度
cout<<"d="<<d<<endl;
}
//【cout.setf();添加控制标志/cout.unsetf()清除标志】
//同时添加多个控制的是时候: 以|连接 cout.setf(ios::left|ios::dec)
//ios::left,ios::rigth,ios::dec.ios::oct,ios::hex,ios::showbase(带前缀输出),ios::showpoint(带小数点)
//ios::scientific(科学计数法),ios::showpos(带符号);ios::uppercase(大写)十六进制或者科学计数法时其中的字母
*/
/*
#include<iostream>
using namespace std;
int main()
{
cout.width(10);
cout.fill('#');
cout.setf(ios::left|ios::showpos);
cout<<123<<endl;
cout.setf(ios::showpoint);
cout<<123.0<<endl;
cout.setf(ios::scientific|ios::uppercase);
cout<<123456.78<<endl;
cout.unsetf(ios::scientific|ios::uppercase);
cout.precision(2);//精度控制,与fixed合用来表示小数部分的精度
cout.setf(ios::fixed);//表示上述的精度表示小数点后的精度
cout<<123.0<<endl;
cout.unsetf(ios::showpos);
cout.unsetf(ios::oct|ios::dec);
cout.setf(ios::hex|ios::showbase);//setf是添加控制设置前需将其他同类型的删除
cout<<123<<endl;
}//输出控制符:flush:清缓冲区;endl:换行,清空缓存区; oct/dec/hex
*/
//setw() 设置宽度;setfill()设置填充字符;setprecision fixed精度设置
// 往文件中输出设置一样;
/*
#include<iostream>
using namespace std;
#include<iomanip>
int main()
{
cout<<setw(10)<<setfill('~')<<left<<123<<endl;
cout<<setprecision(2)<<fixed<<12444.234<<endl;
cout<<hex<<showpos<<uppercase<<123<<endl;
}
*/
//ofstream fout(文件名): 默认会将文件中原有的内容清除掉;
//所以需要添加 :ofstream fout(文件名,方式(默认为ios::fout,若设为追加则为app;ios::binary 二进制原样读写//window下会将'\n'写成'\r'和'\n',读的时候则相反
//ios::ate 在文件末尾读写,ios::in :open for reading 读文件 ios::trunc 清空原有文件
//ios::out :open for writing
/*
#include<iostream>
using namespace std;
#include<string>
#include<fstream>
int main()
{
ofstream fout("a.txt",iostream::app);
string str;
cout<<"please input string:";
getline(cin,str);
fout<<str<<endl;
fout.close();
}//跳跃读写:seekg(位置int)读 seekp(位置 int)写
*/
/*
#include<iostream>
using namespace std;
#include<fstream>
int main()
{
ofstream fout("a.txt",ios::out|ios::binary);
fout<<"hello,sd0705!"<<endl;
fout.seekp(0);
fout.put('H');
fout.seekp(6);
fout<<"S";
fout.close();
ifstream fin("a.txt",ios::in|ios::binary);
fin.seekg(1);
char ch;
fin.get(ch);
cout<<ch<<endl;
fin.close();
}
//【tellp()/tellg()当前位置】;
*/
//fstream fio(文件名,ios::in|ios::out|ios::binary);需注意读写的位置
//-------------------------day_13_PM-------------------------------
//异常: 内部类:在某一个作用域内定义的类;只在某个范围内使用;函数或类中的类
/*
#include<iostream>
using namespace std;
class A{
public:
class B{
};//成员内部类
// int b;
};
class B{};
class D{
public:
class B{};
};// 隐藏名字,避免类名冲突、通过提供统一的内部类名来统一个各类的操作方法
int main()
{
class C{
};//局部内部类
//int c;
C objc;
A obja;
A::B objb;//成员内部类的使用
B obj;
D::B objd;//可区分
}*/
/*异常: 以if(...==-1){处理----},不常见,可预料,并准备;不能避免,只能减小损失
try{
if(有异常情况){throw 数据; //C++中什么都可以抛;}
}try用来监视是否有数据抛出
catch(类型 变量名){//一个catch只能接一种类型数据
}
catch(类型 变量){//处理过程,处理try中抛出来的数据
}
*/
/*
#include<iostream>
using namespace std;
#include<fstream>
int main()
{
try{
ifstream fin("a.txt");
if(!fin)
throw 100;//跳出try去寻找匹配类型的catch();
char buf[1000];
fin.read(buf,1000);
if(!fin)
throw 100.0;
cout.write(buf,1000);
fin.close();
}
catch(double e){//要求严格类型匹配
cout<<"double :"<<e<<endl;
}
catch(long e ){//exception 异常类 其中有成员 what()
cout<<"long:"<<endl;//异常必须被处理否则程序会被异常中止
//在catch执行完毕后会跳到所有的catch之后,其他的catch不再起作用
//后面的语句该怎么执行还怎么执行,异常一旦抛出则不再回来
}
catch(...){//放在最后的catch 不知道throw的数据类型时,可以接收
cout<<"exception!"<<endl;
}
cout<<"what a good day1"<<endl;
}
//异常的传递: 在一个函数中若异常未被捕获, 异常会传递到调用它的地方;
//在main函数中添加捕获 try{} catch(){}
//捕获类型严格匹配的时候class A{}; class B::public A{}; try{ throw B();} catch(A e){ }所以应该先catch子类再catch父类
// 若catch 接受后处理不了该异常则可重新抛出该异常 throw ;
*/
/*数据结构和算法:
链表:头指针,用来指向头结点的指针;每个节点用指针来连接;
typedef int T;
struct Node{//结构中也可以定义构造函数, 结构与类的唯一区别是默认的权限不一样
T data;
Node * next;
};//内部类型,在某个作用域内定义
*/
/*
#include<iostream>
using namespace std;
typedef int T;
void test1()
{
struct Node{
T data;
Node* next;
};
Node n1;
Node* p=new Node;
cout<<"n1.data="<<n1.data<<endl;
cout<<"n1.next="<<n1.next<<endl;
cout<<"p->data="<<p->data<<endl;
cout<<"p->next="<<p->next<<endl;
}
void test2()
{
struct Node{//局部结构不会出现类型名的冲突;
T data;
Node* next;
Node(const T& d=T()):data(d),next(NULL){}
};
Node n1;
Node* p=new Node;
cout<<"n1.data="<<n1.data<<endl;
cout<<"n1.next="<<n1.next<<endl;
cout<<"p->data="<<p->data<<endl;
cout<<"p->next="<<p->next<<endl;
}
int main()
{
test1();
test2();
}
*/
/*
#include<iostream>
using namespace std;
int main()
{
typedef int T;
struct Node{
T data;
Node* next;
Node(const T& d=T()):data(d){
next=NULL; cout<<"V"<<endl;
}
~Node(){cout<<"X"<<endl;}
};
Node * head=NULL;
cout<<"input some integers:";
T item;
do{
cin>>item;
Node* p=new Node(item);
p->next=head;//将各个节点连接起来;
head=p;
}while(cin.get()!='\n');
Node* p=head;
while(p!=NULL){
cout<<p->data<<' ';
p=p->next;
}
cout<<endl;
p=head;
while(p!=NULL){
Node* q=p->next;
delete p;
p=q;//内存的释放;
}
return 0;
}*/
//----------------------指针类:-----------------------------------------
/*
#include<iostream>
using namespace std;
typedef int T;
class List{
struct Node{
T data;
Node* next;
Node(const T&t=T()):data(t)
{ next=NULL;}
};
Node* head;
public:
List():head(NULL){}
void clear(){
while(head!=NULL)
{
Node* q=head->next;
delete head;
head=q;
}
}
~List(){clear();}
void Front_insert(const T &t){
Node* p=new Node(t);
p->next=head;
head=p;
}
void travel(){
Node *p=head;
while(p!=NULL)
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
void insert_back(const T& t){
Node* p=new Node(t);
if(head==NULL)
head=p;
else
getPointer(size()-1)->next=p;
}
T size(){
Node* p=head;
int cnt=0;
while(p!=NULL)
{
cnt++;
p=p->next;
}
return cnt;
}
T getHead(){
if(head==NULL)
throw "no head";
return head->data;
}
T getTail(){
if(head==NULL)
throw "no tail";
Node* p=head;
while(p->next!=NULL)//指针为空则为尾节点
p=p->next;
return p->data;
}
bool empty(){
return head==NULL;
}
T find(const T& t){
Node* p=head;
int pos=0;
while(p!=NULL)
{
if(t==p->data)
return pos;
pos++;
p=p->next;
}
return -1;
}
bool updata(const T&o,const T& n)
{
int pos=find(o);
if(pos==-1)
return false;
Node* p=getPointer(pos);
p->data=n;
return true;
}
private:
Node* getPointer(int pos)
{
Node* p=head;
for(int i=0; i<pos;i++)
p=p->next;
return p;
}
public:
bool erase(const T& t)
{
int pos=find(t);
if(pos==-1)
return false;
if(pos==0)
{
Node* q=head->next;
delete head;
head=q;
}
else{
Node* pre=getPointer(pos-1);
Node* cur=pre->next;
pre->next=cur->next;
delete cur;
}
}
};
int main()
{
List obj;
obj.Front_insert(1);
obj.Front_insert(2);
obj.Front_insert(3);
obj.Front_insert(4);
obj.Front_insert(5);
cout<<"size:"<<obj.size()<<endl;
obj.travel();
cout<<"find 3:"<<obj.find(3)<<endl;
cout<<"find 8:"<<obj.find(8)<<endl;
obj.updata(4,100);
obj.travel();
obj.erase(3);
obj.erase(5);
obj.erase(1);
obj.erase(2);
obj.travel();
obj.insert_back(7);
obj.insert_back(8);
obj.insert_back(9);
obj.insert_back(10);
obj.travel();
}