因为之前我也遇到了这个查找文件的某个内容,然后修改文件的某些内容,看了很多篇子都没有看到这块内容。自己发这个博客,为帮助大家解决问题也为了给自己代码留一个副本。
第一次发的博客若有什么不足还请指正,代码全是自己手打测试过的,可以直接拷贝测试运行试试
一,解释一下这几个函数的意思
tellp 用于返回写入位置,tellg 则用于返回读取位置。不管是tellp还是tellg返回的都是记录文件的某个位置,也就是说读取位置和写入位置是一个东西,就是表示某个文件的位置,我也就可以用某个读取文位置去设置某个写入位置的值(如fp.seekp(fp.tellg());)
seekp()和seekg()函数功能
seekp:设置输出文件流的文件流指针位置
seekg:设置输入文件流的文件流指针位置
函数原型:
无偏移
ostream& seekp( streampos pos );
istream& seekg( streampos pos );
有偏移,如果off负的,就往前面偏移,反之
ostream& seekp( streamoff off, ios::seek_dir dir );
istream& seekg( streamoff off, ios::seek_dir dir );
函数参数
pos:新的文件流指针位置值
off:需要偏移的值
dir:搜索的起始位置
dir参数用于对文件流指针的定位操作上,代表搜索的起始位置
在ios中定义的枚举类型:
enum seek_dir {beg, cur, end};
每个枚举常量的含义:
ios::beg:文件流的起始位置
ios::cur:文件流的当前位置
ios::end:文件流的结束位置
二,案例
简单做了一个账户登录平台有以下功能(所有的信息都是保存在account.txt文件下)
注:账号信息的保存格式
caccount[20] \t cpassword[20] \t cquestion[30] \t canswer[30] \n
1、登录
2、注册
3、找回密码(通过回答密保问题)
设置了5个函数
fstream查找修改文件内容的实例在void changeAccount();函数中,其他函数的文件操作用的c语言的文件操作可以结合做参考对比
void fileinit();//文件初始化
int startgo();//功能选择
int login();//登陆
bool chcekAccount();//验证账号密码
void logonAccount();//注册账号信息
void changeAccount();//找回密码
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
using namespace std;
void fileinit();//文件初始化
int startgo();//功能选择
int login();//登陆
bool chcekAccount();//验证账号密码
void logonAccount();//注册账号信息
void changeAccount();//找回密码
int main() {
fileinit();
startgo();
}
int startgo() {
system("cls");
while (true) {
system("cls");
int flag;
char account_number[20], password[20];
printf("\t\t1注册 2登陆 3找回密码");
printf("\n\t\t请选择序号: ");
scanf("%d", &flag);
system("cls");
if (flag == 1) {
logonAccount();
}
else if (flag == 2) {
if (login()) {
break;
}
}
else if (flag == 3) {
changeAccount();
}
}
return 1;
}
int login()
{
int n = 0;
while (TRUE)
{
if (chcekAccount())
{
printf("\t\t欢迎进入系统,请稍候......\n");
Sleep(1000);
return 1;
}
else
{
printf("\t\t密码输入错误,按任意键请重新输入\n\n");
system("pause");
n++;
if (n >= 3)
{
printf("\t\t连续输错3次,程序即将退出......\n");
Sleep(2000);
exit(ERROR);
}
}
}
}
void fileinit() {
fstream fp("account.txt", std::ios::_Nocreate);
//若文件不存在
if (!fp.is_open()) {
string t = "登陆名\t密码\t密保问题\t\t密保答案\n";
ofstream tfp("account.txt");
tfp << t;
tfp.close();
}
}
bool chcekAccount()
{
char account_number[20], password[20];
system("cls");
printf("\t\t账号:");
scanf("\n%s", &account_number);
printf("\t\t密码:");
scanf("\n%s", &password);
bool flag = false;
char caccount[20], cpassword[20], cquestion[30], canswer[30];
FILE* fp = fopen("account.txt", "r");
if (fp == NULL)
{
fp = fopen("account.txt", "w");
}
while (fscanf(fp, "%s\t%s\t%s\t%s\n", caccount, cpassword, cquestion, canswer) != EOF && flag == false)
{
if ((strcmp(account_number, caccount) == 0) && (strcmp(password, cpassword) == 0)) {
flag = true;
}
}
fclose(fp);
return flag;
}
void logonAccount()
{
printf("\t\t正在进行注册账号......\n");
char account_number[20], password[20], question[30], answer[30];
bool flag = 0;
FILE* fp = fopen("account.txt", "a+");
printf("\t\t账号:");
getchar();
scanf("\n%s", &account_number);
printf("\t\t密码:");
scanf("\n%s", &password);
printf("\t\t密保问题:");
scanf("\n%s", &question);
printf("\t\t答案:");
scanf("\n%s", &answer);
fprintf(fp, "%s\t%s\t%s\t%s\n", account_number, password, question, answer);
fclose(fp);
printf("\t\t注册成功!!\n\t\t即将返回登陆界面");
Sleep(1000);
}
void changeAccount() {
printf("\t\t正在进行找回密码......\n");
fstream fp("account.txt", ios::in | ios::out | ios::binary);
char account_number[20], password[20], answer[30];
printf("\t\t账号:");
scanf("%s", &account_number);
if (!fp.is_open())
{
printf("open file fail");
system("pause");
}
bool flag = false;//是否已经修改
char c;
char caccount[20], cpassword[20], cquestion[30], canswer[30];//存储登录名 密码 密保问题 密保答案
while (!fp.eof() && flag == 0) {
fp >> caccount;
fp.get();//读\t
//存储格式caccount[20] \t cpassword[20] \t cquestion[30] \t canswer[30] \n
if (strcmp(caccount, account_number) == 0) {
streamoff len = fp.tellg();//记录密码在文件的位置
fp >> cpassword;
c = fp.get(); //读\t
fp >> cquestion;
c = fp.get(); //读\t
fp >> canswer;
c = fp.get(); //读\n
int t = 0;
while (true) {
t++;
printf("\n\t\t密保问题:%s?", cquestion);
printf("\n\t\t请输入你的密保答案:");
scanf("%s", &answer);
if (strcmp(answer, canswer) == 0)
{
printf("\n\t\t验证成功......");
while (true) {
printf("\n\t\t输入新的密码:");
scanf("%s", &password);
char t[30];
printf("\n\t\t请再次输入新的密码:");
scanf("%s", &t);
if (strcmp(t, password) == 0) {
break;
}
else {
printf("\n\t\t两次输入密码不一致请重新输入");
}
}
fp.seekp(len);
fp << password;
//如果修改后内容变短会出现问题,所以用用空格补上,当然如果更长,就不会有影响,可以试着把这条for语言注释后,看看效果
for (int i = strlen(password); i < (int)strlen(cpassword); i++) {
fp.write(" ", 1);
}
flag = 1;
break;
}
else printf("\n\t\t密保没有通过,请重新输入......");
if (t >= 3) {
printf("\n\t\t连续输错3次,程序即将退出......\n");
Sleep(2000);
exit(ERROR);
}
}
}
if (fp.eof()) {
printf("\t\t改用户没有注册修改失败!!\n\t\t即将返回登陆界面");
}
if (flag == 0) {
fp >> cpassword; c = fp.get(); fp >> cquestion; c = fp.get(); fp >> canswer; c = fp.get();
}
}
if (flag == 1)printf("\t\t修改成功!!\n\t\t即将返回登陆界面");
Sleep(1000);
fp.close();
}