賬號(hào)登錄系統(tǒng)在很多系統(tǒng)設(shè)計(jì)時(shí)都時(shí)必不可少的,今天這個(gè)登錄系統(tǒng)功能較全,可以注冊,登錄,找回密碼,修改密碼,以及在輸入密碼時(shí)會(huì)有*將密碼掩蓋,還有完善地登錄選擇界面,廢話不多,上代碼!
目錄
1.頭文件&結(jié)構(gòu)體&大概函數(shù)實(shí)現(xiàn)
2.主函數(shù)&登錄界面
3.注冊系統(tǒng)
4.登錄系統(tǒng)
5.找回密碼(更改密碼)
6.密碼輸入獲取&密碼掩蓋
7.完整代碼!!!!!
!!!!首先需要在和.c文件同個(gè)目錄下新建一個(gè)文件儲(chǔ)存數(shù)據(jù),命名users.dat ?如圖!!
img
!!!!!!!!!!!!!!!!!!!!
也可以命名別的,后綴dat是我自己隨便取的,喜歡就行!但是記得在代碼中將文件名改過來!
1.頭文件&結(jié)構(gòu)體&大概函數(shù)實(shí)現(xiàn)
?
//引頭文件 #include?#include? #include? #include? //用于反應(yīng)意外情況的,下面會(huì)講到 #include? //定義宏常量 #define?MAX_ID?11//ID的最大長度 #define?MAX_PWD?20//密碼的最大長度 #define?MAX_NAME?15//名字的最大長度 #define?MAX_SEX?5//性別的最大長度 #define?MAX_PHONE?12//電話的最大長度 //創(chuàng)建用戶的結(jié)構(gòu)體 typedef?struct?Users { ?char?id[MAX_ID];//id?即登錄的賬號(hào) ?char?pwd[MAX_PWD];//密碼 ?char?name[MAX_NAME];//姓名 ?char?sex[MAX_SEX];//性別 ?char?phone[MAX_PHONE];//電話 }Users; //聲明函數(shù) //打印菜單 void?menu(); //用戶注冊 void?Register(); //登錄 void?Login(); //找回密碼 void?Reback(); ? //定位光標(biāo) void?gotoxy(); //獲取x的位置 int?posx(); //獲取y的位置 int?posy(); //密碼輸入(含掩蓋功能) void?Getpwd(char*?pwd);
?
這里定義了很多宏常量,可以看情況修改合適的數(shù)值,比較快捷方便,不用到代碼里一個(gè)個(gè)改
2.主函數(shù)&登錄界面
?
void?menu() { ?printf("************************************ "); ?printf("************************************ "); ?printf("*****1.Register?????????2.Login***** "); ?printf("*****3.Reback???????????0.exit?***** "); ?printf("************************************ "); ?printf("************************************ "); } int?main() { ?char?input; ?do ?{ ??menu(); ??setbuf(stdin,?NULL);//清空輸入緩沖區(qū),避免下面getchar讀到上一次輸入緩沖區(qū)剩下的東西 ??input?=?getchar(); ??switch?(input) ??{ ??case?'1': ???Register(); ???break; ??case?'2': ???Login(); ???break; ??case?'3': ???Reback(); ???break; ??case?'0': ???printf("退出成功! "); ???break; ??default: ???printf("選擇錯(cuò)誤,請重新選擇! "); ???break; ??} ?}?while?(input!='0');//如果輸入了0,就exit退出咯 }
?
這里用到字符去當(dāng)作switch的判斷依據(jù),是因?yàn)槿绻谜稳プ雠袛嘁罁?jù)的話,若向input中輸入的東西不是整形而是字符或者字符串,switch在循環(huán)中就會(huì)陷入死循環(huán),具體情況大家去試試就知道,這里不多講解,用單個(gè)字符判斷到現(xiàn)在是沒試出什么bug。
3.注冊系統(tǒng)
?
void?Register() { ?Users?a,?b;//創(chuàng)建用戶結(jié)構(gòu)體臨時(shí)變量,a是用來接收用戶輸入的,b是用來從文件中讀取的,來和a作比較 ?char?tmp[20]="";//用著下面判斷的 ?? ?printf("歡迎來到注冊界面! "); ?FILE*?pf?=?fopen("users.dat",?"rb");//"rb"是以二進(jìn)制只讀方式打開文件的意思 ?fread(&b,?sizeof(Users),?1,?pf);//將數(shù)據(jù)讀入b中 ?if?(!pf)//如果打開失敗 ?{ ??printf("%s",?strerror(errno));//errno可以理解是報(bào)的錯(cuò)誤對應(yīng)的編號(hào),strerror可以把這個(gè)編號(hào)翻譯出來,輸出在屏幕上 ??return; ?} ?Sleep(800); ?? ?printf("請輸入您的賬號(hào)>>"); ?scanf("%s",?a.id); ?while?(1) ?{ ??if?(strcmp(a.id,?b.id))//兩個(gè)用戶名不相等 ??{ ???if?(!feof(pf))//沒讀到文件末尾 ???{ ????fread(&b,?sizeof(Users),?1,?pf);//繼續(xù)讀取文件中的用戶到b中 ???} ???else//讀到文件末尾了,確認(rèn)沒有重復(fù)的id ???{ ????break; ???} ??} ??else//有兩個(gè)用戶名相等 ??{ ???printf("此用戶名已存在在,請重新輸入! "); ???Sleep(1000); ???fclose(pf);//關(guān)閉文件 ???pf?=?NULL;//pf置空,避免野指針 ???return; ??} ?} ?printf("請輸入您的姓名>>"); ?scanf("%s",?a.name); ?printf("請輸入您的性別>>"); ?scanf("%s",?a.sex); ?printf("請輸入您的電話號(hào)碼>>"); ?scanf("%s",?a.phone); ?printf("請輸入您的密碼>>"); ?Getpwd(a.pwd);//輸入密碼的函數(shù),有掩蓋功能,下面會(huì)介紹 ?printf(" 請?jiān)俅未_認(rèn)您的密碼>>"); ?Getpwd(tmp); ?do ?{ ??if?(!strcmp(a.pwd,?tmp))//兩次密碼相等 ??{ ???pf?=?fopen("users.dat",?"ab"); ???fwrite(&a,?sizeof(Users),?1,?pf); ???printf(" 賬號(hào)注冊成功,請登錄! "); ???Sleep(500); ???fclose(pf); ???pf?=?NULL; ???return; ??} ??else ??{ ???printf(" 兩次密碼不匹配!請重新輸入>>"); ???Getpwd(a.pwd); ???printf(" 請?jiān)俅未_認(rèn)>>"); ???Getpwd(tmp); ??} ?}?while?(1); }
?
文件都是以二進(jìn)制打開以二進(jìn)制寫入的,沒別的原因,就是覺得帥!
關(guān)注公眾號(hào):C語言中文社區(qū),免費(fèi)領(lǐng)取300G編程資料
4.登錄系統(tǒng)
?
void?Login() { ?Users?a,?b;//同理,a是用來給用戶輸入的,b是用來是水的(從文件中讀取到b中,用b和a匹配比較) ?FILE*?pf?=?fopen("users.dat",?"rb");//以只讀的方式打開文件 ?if?(!pf)//如果讀取失敗 ?{ ??printf("%s ",?strerror(errno));//上面有講過~ ??return; ?} ?printf("歡迎來到登錄界面! "); ?Sleep(1000); ?? ?fread(&b,?sizeof(Users),?1,?pf);//先從文件中讀取一個(gè)用戶試試水 ?? ?printf("請輸入賬號(hào)>>"); ?scanf("%s",?a.id); ?? ?while?(1) ?{ ??if?(!strcmp(a.id,?b.id))//在文件中找到了與用戶輸入相同的id ??{ ???break; ??} ??else ??{ ???if?(!feof(pf))//沒讀到文件末尾,繼續(xù)讀取文件中的id到b中 ???{ ????fread(&b,?sizeof(Users),?1,?pf);//繼續(xù)從文件中讀取用戶信息進(jìn)b,直到在文件中找到一個(gè)和a的信息相同的 ???} ???else//讀到文件末尾了,沒有找到與用戶輸入相同的賬號(hào) ???{ ????printf("此賬號(hào)不存在!請重新輸入! "); ????Sleep(500); ????fclose(pf); ????pf?=?NULL; ????return; ???} ??} ?} ?do ?{ ??printf("請輸入密碼>>"); ??Getpwd(a.pwd);//獲取密碼,在下面會(huì)講 ??if?(!strcmp(a.pwd,?b.pwd))//輸入的密碼與文件中的相同 ??{ ???printf(" 登錄成功!歡迎使用! "); ???Sleep(500); ???fclose(pf);//用完當(dāng)然要把文件關(guān)啦 ???pf?=?NULL;//置空,避免野指針 ???return; ??} ??else ??{ ???printf(" 密碼輸入錯(cuò)誤,請重新輸入 "); ??} ?}?while?(strcmp(a.pwd,?b.pwd)); }
?
大概思路就是用戶先輸入賬號(hào)(id),接著b從文件中讀取用戶,直到找到與用戶輸入id相同的,然后就是輸入密碼判斷密碼對不對咯。? 里面用到了一個(gè)庫函數(shù)strcmp,判斷字符串是不是一樣的,如果一樣則返回0,不一樣則返回一個(gè)非0值。
5.找回密碼(更改密碼)
?
void?Reback() { ?char?tmp[20]?=?"";//密碼匹配用的 ?Users?a,?b; ?FILE*?pf?=?fopen("users.dat",?"rb+");//"rb+"是為了讀和寫以二進(jìn)制打開文件的意思 ?? ?if?(!pf)//老樣子,先判斷能不能順利打開 ?{ ??printf("%s",?strerror(errno)); ??return; ?} ?? ?fread(&b,?sizeof(Users),?1,?pf);//照樣,讀一個(gè)試試水 ?? ?printf("請輸入您的賬號(hào)>>"); ?Sleep(800); ?? ?scanf("%s",?a.id); ?? ?while?(1)//在文件中找到與用戶輸入相同的id ?{ ??if?(!strcmp(a.id,?b.id))//如果讀取到了相同的id(在文件中找到了和用戶輸入一樣的) ??{ ???break; ??} ??else ??{ ???if?(!feof(pf))//沒讀到文件尾,繼續(xù)讀 ???{ ????fread(&b,?sizeof(Users),?1,?pf); ???} ???else ???{ ????printf("您輸入的賬號(hào)不存在!請重新輸入! "); ????Sleep(500); ????fclose(pf); ????pf?=?NULL; ????break; ???} ??} ?} ?? ?//下面是信息匹配驗(yàn)證 ?do//匹配姓名 ?{ ??printf("請輸入您的姓名>>"); ??scanf("%s",?a.name); ??if?(!strcmp(a.name,?b.name)) ??{ ???break; ??} ??else ??{ ???printf("輸入錯(cuò)誤,請重新輸入! "); ??} ?}?while?(strcmp(a.name,?b.name)); ?? ?do//匹配性別 ?{ ??printf("請輸入您的性別>>"); ??scanf("%s",?a.sex); ??if?(!strcmp(a.sex,?b.sex)) ??{ ???break; ??} ??else ??{ ???printf("輸入錯(cuò)誤,請重新輸入! "); ??} ?}?while?(strcmp(a.sex,?b.sex)); ?do//匹配電話號(hào)碼 ?{ ??printf("請輸入您的電話號(hào)碼>>"); ??scanf("%s",?a.phone); ??if?(!strcmp(a.phone,?b.phone)) ??{ ???break; ??} ??else ??{ ???printf("輸入錯(cuò)誤,請重新輸入! "); ??} ?}?while?(strcmp(a.phone,?b.phone)); ?? ?//更改密碼 ?printf("驗(yàn)證成功!請修改您的密碼! "); ?printf("請輸入您的密碼>>"); ?Getpwd(a.id); ?printf("請?jiān)俅未_認(rèn)您的密碼>>"); ?Getpwd(tmp); ?if?(!pf) ?{ ??printf("%s",?strerror(errno)); ??return; ?} ?//將原來的密碼覆蓋掉 ?do ?{ ??if?(!strcmp(a.pwd,?tmp))//兩次密碼相等 ??{ ???fseek(pf,-((int)(sizeof(Users)-MAX_ID)),?SEEK_CUR);//將文件流調(diào)回到要修改的密碼的位置 ???fprintf(pf,?"%s",?a.pwd);//覆蓋原來的密碼 ???printf("密碼修改成功,請登錄! "); ???Sleep(500); ???fclose(pf); ???pf?=?NULL; ???return; ??} ??else ??{ ???printf("兩次密碼不匹配!請重新輸入>>"); ???scanf("%s",?a.pwd); ???printf("請?jiān)俅未_認(rèn)>>"); ???scanf("%s",?tmp); ??} ?}?while?(1); }
?
大概思路是輸入賬號(hào)->匹配信息->修改密碼,修改密碼時(shí)要將文件流調(diào)回要修改的密碼的前面,這里用到了fseek,-((int)(sizeof(Users)-MAX_ID))是要調(diào)回的范圍。
6.密碼輸入獲取&密碼掩蓋
?
void?gotoxy(int?x,?int?y) { ?//更新光標(biāo)位置 ?COORD?pos; ?HANDLE?hOutput?=?GetStdHandle(STD_OUTPUT_HANDLE);//GetStdHandle是一個(gè)Windows API函數(shù)。 ?pos.X?=?x; ?pos.Y?=?y; ?SetConsoleCursorPosition(hOutput,?pos); } int?posx() { ?CONSOLE_SCREEN_BUFFER_INFO?ptr; ?GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),?&ptr); ?return?(ptr.dwCursorPosition.X); } int?posy() { ?CONSOLE_SCREEN_BUFFER_INFO?ptr; ?GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),?&ptr); ?return?(ptr.dwCursorPosition.Y); } void?Getpwd(char*?pwd) { ?int?i?=?0; ?int?x,?y; ?while?(1) ?{ ??pwd[i]?=?getch();//獲取單個(gè)密碼(字符) ??if?(pwd[i]?==?VK_BACK?&&?i?>=?0)//如果輸入的是回退鍵,VK_BACK是鍵盤的鍵值,ASCII碼值為8 ??{ ???if?(i?>?0)//i>0說明有輸入東西了,則回退前一格 ???{ ????i--; ????x?=?posx()?-?1;//定位x并回退一格 ????y?=?posy();//定位y ????gotoxy(x,?y);//定位光標(biāo) ????printf("?");//將*用空格掩蓋 ????x?=?posx()?-?1;//再次回退,下次輸入時(shí)光標(biāo)才會(huì)顯示在正確的位置 ????y?=?posy();//定位y ????gotoxy(x,?y); ????continue;//然后跳過此次循環(huán) ???} ???else?if?(i?==?0)//i==0說明沒輸入東西,直接跳過此次循環(huán)即可 ???{ ????continue; ???} ??} ??if?(i?>=?0?&&?pwd[i]?!=?VK_RETURN?&&?pwd[i]?!=?VK_BACK)//輸入東西了 ??{ ???x?=?posx(); ???y?=?posy(); ???gotoxy(x,?y); ???printf("*"); ??} ??if?(i?==?0?&&?pwd[i]?==?VK_RETURN)//如果沒輸入東西直接按回車,直接跳過此次循環(huán),避免程序把回車當(dāng)密碼了 ??{ ???continue; ??} ??if?(pwd[i]?==?VK_RETURN||i==MAX_PWD-2)//輸入回車了或者到上限了 ??{ ???i++; ???pwd[i]?=?'';//結(jié)尾放'' ???break; ??} ??i++; ?} }
?
那幾個(gè)長長的都是windows控制臺(tái)的API函數(shù),這里不多講解
7.完整代碼!!!!!
?
//引頭文件 #include?#include? #include? #include? #include? //定義宏常量 #define?MAX_ID?11 #define?MAX_PWD?20 #define?MAX_NAME?15 #define?MAX_SEX?5 #define?MAX_PHONE?12 //創(chuàng)建用戶的結(jié)構(gòu)體 typedef?struct?Users { ?char?id[MAX_ID]; ?char?pwd[MAX_PWD]; ?char?name[MAX_NAME]; ?char?sex[MAX_SEX]; ?char?phone[MAX_PHONE]; }Users; ? //聲明函數(shù) //打印菜單 void?menu(); //用戶注冊 void?Register(); //登錄 void?Login(); //找回密碼 void?Reback(); //定位光標(biāo) void?gotoxy(); //獲取x的位置 int?posx(); //獲取y的位置 int?posy(); //密碼輸入(含掩蓋功能) void?Getpwd(char*?pwd); int?main()//主函數(shù) 關(guān)注公眾號(hào):C語言中文社區(qū),免費(fèi)領(lǐng)取300G編程資料 { ?char?input; ?do ?{ ??menu(); ??setbuf(stdin,?NULL); ??input?=?getchar(); ??switch?(input) ??{ ??case?'1': ???Register(); ???break; ??case?'2': ???Login(); ???break; ??case?'3': ???Reback(); ???break; ??case?'0': ???printf("退出成功! "); ???break; ??default: ???printf("選擇錯(cuò)誤,請重新選擇! "); ???break; ??} ?}?while?(input!='0'); } //打印菜單 void?menu() { ?printf("************************************ "); ?printf("************************************ "); ?printf("*****1.Register?????????2.Login***** "); ?printf("*****3.Reback???????????0.exit?***** "); ?printf("************************************ "); ?printf("************************************ "); } //注冊系統(tǒng) void?Register() { ?Users?a,?b;//創(chuàng)建用戶結(jié)構(gòu)體臨時(shí)變量,a是用來接收用戶輸入的,b是用來從文件中讀取的,來和a作比較 ?char?tmp[20]="";//用著下面判斷的 ?? ?printf("歡迎來到注冊界面! "); ?FILE*?pf?=?fopen("users.dat",?"rb");//"rb"是以二進(jìn)制只讀方式打開文件的意思 ?fread(&b,?sizeof(Users),?1,?pf);//將數(shù)據(jù)讀入b中 ?if?(!pf)//如果打開失敗 ?{ ??printf("%s",?strerror(errno));//errno可以理解是報(bào)的錯(cuò)誤對應(yīng)的編號(hào),strerror可以把這個(gè)編號(hào)翻譯出來,輸出在屏幕上 ??return; ?} ?Sleep(800); ?? ?printf("請輸入您的賬號(hào)>>"); ?scanf("%s",?a.id); ?while?(1) ?{ ??if?(strcmp(a.id,?b.id))//兩個(gè)用戶名不相等 ??{ ???if?(!feof(pf))//沒讀到文件末尾 ???{ ????fread(&b,?sizeof(Users),?1,?pf);//繼續(xù)讀取文件中的用戶到b中 ???} ???else//讀到文件末尾了,確認(rèn)沒有重復(fù)的id ???{ ????break; ???} ??} ??else//有兩個(gè)用戶名相等 ??{ ???printf("此用戶名已存在在,請重新輸入! "); ???Sleep(1000); ???fclose(pf);//關(guān)閉文件 ???pf?=?NULL;//pf置空,避免野指針 ???return; ??} ?} ?printf("請輸入您的姓名>>"); ?scanf("%s",?a.name); ?printf("請輸入您的性別>>"); ?scanf("%s",?a.sex); ?printf("請輸入您的電話號(hào)碼>>"); ?scanf("%s",?a.phone); ?printf("請輸入您的密碼>>"); ?Getpwd(a.pwd);//輸入密碼的函數(shù),有掩蓋功能,下面會(huì)介紹 ?printf(" 請?jiān)俅未_認(rèn)您的密碼>>"); ?Getpwd(tmp); ?do ?{ ??if?(!strcmp(a.pwd,?tmp))//兩次密碼相等 ??{ ???pf?=?fopen("users.dat",?"ab"); ???fwrite(&a,?sizeof(Users),?1,?pf); ???printf(" 賬號(hào)注冊成功,請登錄! "); ???Sleep(500); ???fclose(pf); ???pf?=?NULL; ???return; ??} ??else ??{ ???printf(" 兩次密碼不匹配!請重新輸入>>"); ???Getpwd(a.pwd); ???printf(" 請?jiān)俅未_認(rèn)>>"); ???Getpwd(tmp); ??} ?}?while?(1); } //登錄系統(tǒng) void?Login() { ?Users?a,?b;//同理,a是用來給用戶輸入的,b是用來是水的(從文件中讀取到b中,用b和a匹配比較) ?FILE*?pf?=?fopen("users.dat",?"rb");//以只讀的方式打開文件 ?if?(!pf)//如果讀取失敗 ?{ ??printf("%s ",?strerror(errno));//上面有講過~ ??return; ?} ?printf("歡迎來到登錄界面! "); ?Sleep(1000); ?? ?fread(&b,?sizeof(Users),?1,?pf);//先從文件中讀取一個(gè)用戶試試水 ?? ?printf("請輸入賬號(hào)>>"); ?scanf("%s",?a.id); ?? ?while?(1) ?{ ??if?(!strcmp(a.id,?b.id))//在文件中找到了與用戶輸入相同的id ??{ ???break; ??} ??else ??{ ???if?(!feof(pf))//沒讀到文件末尾,繼續(xù)讀取文件中的id到b中 ???{ ????fread(&b,?sizeof(Users),?1,?pf);//繼續(xù)從文件中讀取用戶信息進(jìn)b,直到在文件中找到一個(gè)和a的信息相同的 ???} ???else//讀到文件末尾了,沒有找到與用戶輸入相同的賬號(hào) ???{ ????printf("此賬號(hào)不存在!請重新輸入! "); ????Sleep(500); ????fclose(pf); ????pf?=?NULL; ????return; ???} ??} ?} ?do ?{ ??printf("請輸入密碼>>"); ??Getpwd(a.pwd);//獲取密碼,在下面會(huì)講 ??if?(!strcmp(a.pwd,?b.pwd))//輸入的密碼與文件中的相同 ??{ ???printf(" 登錄成功!歡迎使用! "); ???Sleep(500); ???fclose(pf);//用完當(dāng)然要把文件關(guān)啦 ???pf?=?NULL;//置空,避免野指針 ???return; ??} ??else ??{ ???printf(" 密碼輸入錯(cuò)誤,請重新輸入 "); ??} ?}?while?(strcmp(a.pwd,?b.pwd)); } //找回密碼 void?Reback() { ?char?tmp[20]?=?"";//密碼匹配用的 ?Users?a,?b; ?FILE*?pf?=?fopen("users.dat",?"rb+");//"rb+"是為了讀和寫以二進(jìn)制打開文件的意思 ?? ?if?(!pf)//老樣子,先判斷能不能順利打開 ?{ ??printf("%s",?strerror(errno)); ??return; ?} ?? ?fread(&b,?sizeof(Users),?1,?pf);//照樣,讀一個(gè)試試水 ?? ?printf("請輸入您的賬號(hào)>>"); ?Sleep(800); ?? ?scanf("%s",?a.id); ?? ?while?(1)//在文件中找到與用戶輸入相同的id ?{ ??if?(!strcmp(a.id,?b.id))//如果讀取到了相同的id(在文件中找到了和用戶輸入一樣的) ??{ ???break; ??} ??else ??{ ???if?(!feof(pf))//沒讀到文件尾,繼續(xù)讀 ???{ ????fread(&b,?sizeof(Users),?1,?pf); ???} ???else ???{ ????printf("您輸入的賬號(hào)不存在!請重新輸入! "); ????Sleep(500); ????fclose(pf); ????pf?=?NULL; ????break; ???} ??} ?} ?? ?//下面是信息匹配驗(yàn)證 ?do//匹配姓名 ?{ ??printf("請輸入您的姓名>>"); ??scanf("%s",?a.name); ??if?(!strcmp(a.name,?b.name)) ??{ ???break; ??} ??else ??{ ???printf("輸入錯(cuò)誤,請重新輸入! "); ??} ?}?while?(strcmp(a.name,?b.name)); ?? ?do//匹配性別 ?{ ??printf("請輸入您的性別>>"); ??scanf("%s",?a.sex); ??if?(!strcmp(a.sex,?b.sex)) ??{ ???break; ??} ??else ??{ ???printf("輸入錯(cuò)誤,請重新輸入! "); ??} ?}?while?(strcmp(a.sex,?b.sex)); ?do//匹配電話號(hào)碼 ?{ ??printf("請輸入您的電話號(hào)碼>>"); ??scanf("%s",?a.phone); ??if?(!strcmp(a.phone,?b.phone)) ??{ ???break; ??} ??else ??{ ???printf("輸入錯(cuò)誤,請重新輸入! "); ??} ?}?while?(strcmp(a.phone,?b.phone)); ?? ?//更改密碼 ?printf("驗(yàn)證成功!請修改您的密碼! "); ?printf("請輸入您的密碼>>"); ?Getpwd(a.id); ?printf("請?jiān)俅未_認(rèn)您的密碼>>"); ?Getpwd(tmp); ?if?(!pf) ?{ ??printf("%s",?strerror(errno)); ??return; ?} ?//將原來的密碼覆蓋掉 ?do ?{ ??if?(!strcmp(a.pwd,?tmp))//兩次密碼相等 ??{ ???fseek(pf,-((int)(sizeof(Users)-MAX_ID)),?SEEK_CUR);//將文件流調(diào)回到要修改的密碼的位置 ???fprintf(pf,?"%s",?a.pwd);//覆蓋原來的密碼 ???printf("密碼修改成功,請登錄! "); ???Sleep(500); ???fclose(pf); ???pf?=?NULL; ???return; ??} ??else ??{ ???printf("兩次密碼不匹配!請重新輸入>>"); ???scanf("%s",?a.pwd); ???printf("請?jiān)俅未_認(rèn)>>"); ???scanf("%s",?tmp); ??} ?}?while?(1); } //定位光標(biāo) void?gotoxy(int?x,?int?y) { ?//更新光標(biāo)位置 ?COORD?pos; ?HANDLE?hOutput?=?GetStdHandle(STD_OUTPUT_HANDLE);//GetStdHandle是一個(gè)Windows API函數(shù)。 ?pos.X?=?x; ?pos.Y?=?y; ?SetConsoleCursorPosition(hOutput,?pos); } //獲取光標(biāo)x坐標(biāo) int?posx() { ?CONSOLE_SCREEN_BUFFER_INFO?ptr; ?GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),?&ptr); ?return?(ptr.dwCursorPosition.X); } //獲取光標(biāo)y坐標(biāo) int?posy() { ?CONSOLE_SCREEN_BUFFER_INFO?ptr; ?GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),?&ptr); ?return?(ptr.dwCursorPosition.Y); } //輸入密碼 void?Getpwd(char*?pwd) { ?int?i?=?0; ?int?x,?y; ?while?(1) ?{ ??pwd[i]?=?getch();//獲取單個(gè)密碼(字符) ??if?(pwd[i]?==?VK_BACK?&&?i?>=?0)//如果輸入的是回退鍵,VK_BACK是鍵盤的鍵值,ASCII碼值為8 ??{ ???if?(i?>?0)//i>0說明有輸入東西了,則回退前一格 ???{ ????i--; ????x?=?posx()?-?1;//定位x并回退一格 ????y?=?posy();//定位y ????gotoxy(x,?y);//定位光標(biāo) ????printf("?");//將*用空格掩蓋 ????x?=?posx()?-?1;//再次回退,下次輸入時(shí)光標(biāo)才會(huì)顯示在正確的位置 ????y?=?posy();//定位y ????gotoxy(x,?y); ????continue;//然后跳過此次循環(huán) ???} ???else?if?(i?==?0)//i==0說明沒輸入東西,直接跳過此次循環(huán)即可 ???{ ????continue; ???} ??} ??if?(i?>=?0?&&?pwd[i]?!=?VK_RETURN?&&?pwd[i]?!=?VK_BACK)//輸入東西了 ??{ ???x?=?posx(); ???y?=?posy(); ???gotoxy(x,?y); ???printf("*"); ??} ??if?(i?==?0?&&?pwd[i]?==?VK_RETURN)//如果沒輸入東西直接按回車,直接跳過此次循環(huán),避免程序把回車當(dāng)密碼了 ??{ ???continue; ??} ??if?(pwd[i]?==?VK_RETURN||i==MAX_PWD-2)//輸入回車了或者到上限了 ??{ ???i++; ???pwd[i]?=?'';//結(jié)尾放'' ???break; ??} ??i++; ?} }
?
審核編輯:湯梓紅
評(píng)論
查看更多