判断是否建立
知识点:
正常情况下不可用字符串直接填入里面,但是可以&pos[0]
ifstream可以不建立文件,用iscreate.is_open()来实现有没有打开
bool iscreate(const string pos){//pos表示文件位置
ifstream iscreate(&pos[0]);
if(iscreate.is_open()){
iscreate.close();
return 1;//1代表建立了
}
else{
iscreate.close();
return 0;//0代表没建立
}
}
建立文件
知识点:
ofstream可建立文件(stream优点之一),可前提是在目录下未建立文件才能建立文件
这时就要用到上面的模板了
bool newfile(const string pos){
if(iscreate(pos))return 0;//0表示建立文件失败
ofstream newfile(&pos[0]);//同理
newfile.close();
return 1;//1表示建立成功
}
登录系统
结合上面
可能有点长
知识点:
ofstream::app可以在文件最后面接着写而不是重写,是stream的优点之一
_getch()可以在你输入时直接获取,但是不会出现在控制台上
us.eof()可以判断是否输入完成,是stream的优点之一
其他的写注释
void login(){
struct user{
string id,pw;
}uin;
printf("1.登录 2.注册并登录\n");
char dz=_getch();
cout<<dz<<endl;//因为不会出现在控制台上,所以还要输出
if(dz=='2'){
while(1){
cout<<"请输入用户名:\n";
cin>>uin.id;
cout<<"请输入密码:\n";
for(int i=0;;i++){
char namechar=_getch();
if(namechar==' '||namechar=='\n'||namechar=='\r')break;
//win的回车会输入\r\n,所以还要判断\r
printf("*");
//利用_getch()特性让你输入的东西全部变成星号
uin.pw.resize(uin.pw.size()+1);
//不重新设置长度会出现不知道哪来的东西
uin.pw[i]=namechar;
}//这里是密码加密,如果不想加密可以,直接cin>>uin.id;
string real;
cout<<"请确认密码:\n";
for(int i=0;;i++){
char namechar=_getch();
if(namechar==' '||namechar=='\n'||namechar=='\r')break;
printf("*");
uin.pw.resize(uin.pw.size()+1);
uin.pw[i]=namechar;
}//这里是密码加密,如果不想加密可以,直接cin>>real;
if(real!=uin.pw){
printf("密码与确认密码不相同,请重新注册!\n");
Sleep(1000);
}
else break;
}
ofstream us("GRU.sgff",ofstream::app);
//这个双引号里面想咋改咋改,没限制
us<<uin.id<<' '<<uin.pw<<endl;
cout<<"注册成功!已登录\n";
cout<<"欢迎光临,"<<uin.id<<"用户\n";
us.close();
}//registered system
else{//搞个计数器还可以登录几次之后不让登录了,当然退出了又可以了
bool zdjs=1;
while(zdjs){
ifstream us("GRU.sgff");//这里的双引号要和上面的双引号一致
if(!us.is_open()){//这里不用模板是因为可以顺带一判
cout<<"您还未注册,登录失败\n";
us.close();
login();
return;
//返回去让你注册,除非你一直选登录容易爆内存
}
cout<<"输入昵称:\n";
cin>>uin.id;
cout<<"输入密码:\n";
for(int i=0;;i++){
char namechar=_getch();
if(namechar==' '||namechar=='\n'||namechar=='\r')break;
printf("*");
uin.pw.resize(uin.pw.size()+1);
uin.pw[i]=namechar;
}//同上上,不想说了
printf("\n");
user users;
for(int u=1;;u++){
us>>users.id;
us>>users.pw;
if(uin.id==users.id&&uin.pw==users.pw){
cout<<"登录成功!\n";
cout<<"欢迎光临,"<<uin.id<<"用户 "<<uin.pw<<endl;
zdjs=0;
us.close();
break;
}
if(us.eof()){
//如果到头了还没有匹配的说明有问题
printf("登录失败,账号名或密码错误\n");
us.close();
break;
}
}
}
}//login system
}
相关函数
其实我们可以发现cin和cout其实就是指向控制台的stream,所以他们有的函数我们自定义也有
比如说
cin.get()
如果不填参数,会返回输入字符的ASCII码值(Python input?)
如果填一个参数,就是输入那个参数
填两个参数,可输入一行,但不对换行处理,只能读取C风格字符串
cin.getline()
和cin.get()读行时的区别是会对换行进行处理
cout.flags() cout.width() cout.fill()
控制宽度
flags用于不够时让原变量往哪儿移动(ios::left ios::right)
width用于设置宽度
fill用于不够时填什么东西
设置后只对下一次输出那一次有效!
cout.setf cout.precision
设置位数
setf(fixed) precision(位数)
其实也可以直接cout<<fixed<<setprecision(位数)
区别在于:上者要到执行cout.unsetf(fixed)时才不会有效果,但是下者之后对后面的有效果
cout,put()括号里直接输出字符,其他事儿他啥也不管啥也不问
后记
话说为什么某Z说stream不好用啊awa我至今没琢磨明白
注释:某Z MNZ