用数组实现从文件搜索帐户和验证密码
?
最近一個(gè)同學(xué)在寫個(gè)銀行管理程序(C語言小項(xiàng)目),然后問我怎么從文件搜索帳戶,給了方法后又不懂文件里面的密碼怎么與輸入的匹配。一般來說,高效的做法是用鏈表實(shí)現(xiàn)。用數(shù)組實(shí)現(xiàn)不是高效的方法,而且浪費(fèi)空間。再者,對(duì)于賬戶類有個(gè)人信息集合的,一般用結(jié)構(gòu)體,代碼寫起來也方便簡(jiǎn)單。
但是他卻用數(shù)組來做,而且沒有用結(jié)構(gòu)體。對(duì)于這種情況下如何搜索帳戶,如何驗(yàn)證密碼呢? 我嘗試了一下,發(fā)現(xiàn)不難解決。
解決這個(gè)問題的方法:用文件數(shù)據(jù)的排序定位來做。
第一步:文件信息讀入
?用fscanf 實(shí)現(xiàn)文件讀出文件信息。
1 char a[20]; 2 3 FILE* fp; 4 fp = fopen("test.txt","rb"); 5 fscanf (fp, "%s", a); 6 fclose(fp);fcanf讀取數(shù)據(jù),以空格為分割點(diǎn)。比如對(duì)于文件內(nèi)容為“abc ABC”(雙引號(hào)之內(nèi))的情況,用如下代碼:
?
fscanf (fp, "%s", a); fscanf (fp, "%s", b);?
?得到字符數(shù)組a 為abc;字符數(shù)組b為 ABC;
若文件內(nèi)容為“abcABC”(雙引號(hào)之內(nèi))的情況,即abc和ABC之間沒有空格隔開,用以上代碼,得到的結(jié)果將是:
字符數(shù)組a 為abcABC;字符數(shù)組b 為亂碼。
fscanf();還有一個(gè)特點(diǎn),就是在一個(gè)程序里面是順序讀入的。
在此舉個(gè)例子:
txt文件(每個(gè)數(shù)據(jù)一行)內(nèi)容:
abc
ABC
ruby
?
然后執(zhí)行下面的代碼:
int main() {char a[20],b[20],c[20];FILE* fp;fp = fopen("test.txt","rb");fscanf(fp, "%s", a);//……此處省略n行代碼fscanf(fp, "%s",b);//……此處省略n行代碼fscanf(fp, "%s",c);fclose(fp); return 0; }?
?得到的結(jié)果是:
字符數(shù)組a為 abc,b為ABC,c為ruby;
?
第二步:搜索賬號(hào)
?
?
賬號(hào)搜索的方法是遍歷文件數(shù)據(jù),找到與輸入匹配的賬號(hào)就停止搜索。
用 while(fscanf(fp,"%s",a) > 0) 實(shí)現(xiàn)遍歷文件數(shù)據(jù)。
作用是把文件內(nèi)容一行一行讀入賦值給字符數(shù)組a,然后再與輸入的賬號(hào)進(jìn)行比較。
同時(shí)使用標(biāo)記 flag 判斷是否找到匹配的賬號(hào),以便后續(xù)處理各種不同情況。
代碼如下:
?
?
char a[20]; char shuRu[20] = {'\0'}; //輸入int flag = 0;cout << "請(qǐng)輸入賬號(hào)名: "; cin >> shuRu;FILE* fp; fp = fopen("test.txt","rb");while(fscanf(fp,"%s",a) > 0) //遍歷文件數(shù)據(jù) {if (strcmp(shuRu,a) == 0){cout << "找到匹配賬號(hào)" << endl;flag = 1;break;} }if (flag == 0){cout << "用戶不存在,請(qǐng)注冊(cè)!" << endl;//下一步 } else//下一步; fclose(fp);?
?代碼中判斷數(shù)據(jù)相同用strcmp(str1,str2); 如果兩個(gè)字符數(shù)組存儲(chǔ)的內(nèi)容相同,則 strcmp(str1,str2)== 0
此時(shí)停止搜索,用break;跳出循環(huán)。
現(xiàn)在舉例一下:
其中第三行為賬號(hào),第五行為密碼。其他的為姓名,地址,年齡等其他信息。
運(yùn)行如下:
?
?第三步:定位文件密碼數(shù)據(jù)
如果是用結(jié)構(gòu)體,當(dāng)檢測(cè)到帳號(hào)的時(shí)候,再用結(jié)構(gòu)體的 “.” 也就是 “點(diǎn)”密碼 來解決。簡(jiǎn)單方便。但是用的不是結(jié)構(gòu)體,所以只能用其他方法。隨筆開頭寫了用“排序定位”來做,如何實(shí)現(xiàn)?
從這個(gè)文件數(shù)據(jù)來看,賬號(hào)與密碼分別是第三行, 第五行,中間隔了個(gè)第四行。下面另一個(gè)帳戶也是同樣的排序。
那么就定位到第五行,然后再進(jìn)行 輸入密碼 與 文件數(shù)據(jù)的比較。
代碼如下:
?
if (strcmp(shuRu,a) == 0) {flag = 1;fscanf(fp,"%s",a);fscanf(fp,"%s",a);break; }?
?這里面當(dāng)檢測(cè)到帳號(hào)的時(shí) flag = 1;表示找到匹配賬號(hào)。
然后用了 兩個(gè)fscanf(fp,"%s",a); 這不是代碼錯(cuò)誤,前面提到了fscanf(); 是順序讀入,并且舉了 a,b,c三個(gè)字符數(shù)組的例子。
這里再說明一下為何用兩個(gè)fscanf();
第一個(gè)fscanf();是把賬號(hào)下面的第一個(gè)數(shù)據(jù)賦值給了 字符數(shù)組a;
第二個(gè)fscanf();是把賬號(hào)下面的第二個(gè)數(shù)據(jù)賦值給了 字符數(shù)組a;
由于密碼數(shù)據(jù)是賬號(hào)數(shù)據(jù)下面的第二個(gè)數(shù)據(jù),所以必須用兩個(gè)fscanf(); 因?yàn)閒scanf();為順序讀入,無法進(jìn)行跳躍。
?
第四步:驗(yàn)證密碼??
定位了密碼數(shù)據(jù),那么就可以進(jìn)行密碼驗(yàn)證了。為了實(shí)現(xiàn)當(dāng)密碼輸入錯(cuò)誤時(shí),能重新輸入,我們必須把驗(yàn)證密碼這個(gè)環(huán)節(jié)寫成一個(gè)函數(shù),然后自身循環(huán)調(diào)用,類似遞歸的用法。
代碼如下:
?
void checkKey(char a[20]) {char mima[20];cout << "輸入密碼:";cin >> mima;if (strcmp(a, mima) == 0)cout << "登錄成功" << endl;else{cout << "密碼輸入錯(cuò)誤!請(qǐng)重新輸入。" << endl;Sleep(2000);checkKey(a);}return; }?
?
?第五步:demo運(yùn)行
初步完成了這個(gè)功能,現(xiàn)在把完整代碼貼出來。
?
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <windows.h> 5 using namespace std; 6 7 //檢測(cè)密碼 8 void checkKey(char a[20]) 9 { 10 char mima[20]; 11 cout << "輸入密碼:"; 12 cin >> mima; 13 if (strcmp(a, mima) == 0) 14 cout << "登錄成功" << endl; 15 else 16 { 17 cout << "密碼輸入錯(cuò)誤!請(qǐng)重新輸入。" << endl; 18 Sleep(2000); 19 checkKey(a); 20 } 21 22 return; 23 } 24 25 int main() 26 { 27 char a[20]; 28 char shuRu[20] = {'\0'}; 29 30 int flag = 0; 31 32 cout << "請(qǐng)輸入賬號(hào)名: "; 33 cin >> shuRu; 34 35 FILE* fp; 36 fp = fopen("test.txt","rb"); 37 38 while(fscanf(fp,"%s",a) > 0) 39 { 40 41 if (strcmp(shuRu,a) == 0) 42 { 43 flag = 1; 44 fscanf(fp,"%s",a); 45 fscanf(fp,"%s",a); 46 break; 47 48 } 49 50 } 51 if (flag == 0) 52 cout << "用戶不存在,請(qǐng)注冊(cè)!" << endl; 53 else 54 checkKey(a); 55 56 fclose(fp); 57 return 0; 58 }?
我們來運(yùn)行一下。
首先文件數(shù)據(jù)如下:(每個(gè)帳戶的第三行為帳號(hào),第五行為密碼)
運(yùn)行結(jié)果:
?
第六步:bug修復(fù)?
看上去好像完成了相應(yīng)預(yù)期功能,但是細(xì)心觀察,不難發(fā)現(xiàn)一個(gè)bug。舉例說明一下:
當(dāng)文件內(nèi)容為:
可以看出,第一個(gè)帳戶的密碼和第二個(gè)帳戶的賬號(hào)相同,都是aabbcc,此時(shí)程序運(yùn)行就有錯(cuò)誤,當(dāng)搜索到了aabbcc,程序就把他當(dāng)成了賬號(hào),于是出錯(cuò)。
修復(fù)bug也很簡(jiǎn)單,用一種特殊字符對(duì)賬號(hào)進(jìn)行處理。比如在賬號(hào)后面追加一個(gè) “@”。
因此,程序要修改兩個(gè)地方
1. 帳戶注冊(cè)后把信息寫入文件時(shí),在賬號(hào)后面追加一個(gè) “@”
2. 登錄時(shí),當(dāng)輸入賬號(hào)完畢后,也給輸入的賬號(hào)后面追加一個(gè)“@”
第一個(gè)地方不是我們討論的范圍,我們來看看與本篇隨筆有關(guān)的要修改的第二個(gè)地方:
相關(guān)函數(shù): strcat(str1,str2);實(shí)現(xiàn)把字符數(shù)組 str2 追加到 str1 后面。
代碼如下:
?
cout << "請(qǐng)輸入賬號(hào)名: "; cin >> shuRu; strcat(shuRu,"@");?
?所以,當(dāng)你登錄時(shí),輸入賬號(hào)完成按回車鍵時(shí),程序會(huì)自動(dòng)給你輸入的賬號(hào)后面追加一個(gè)字符”@“,然后再與文件數(shù)據(jù)進(jìn)行比較。
修改后的完整代碼如下:
?
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <windows.h> 5 using namespace std; 6 7 //檢測(cè)密碼 8 void checkKey(char a[20]) 9 { 10 char mima[20]; 11 cout << "輸入密碼:"; 12 cin >> mima; 13 if (strcmp(a, mima) == 0) 14 cout << "登錄成功" << endl; 15 else 16 { 17 cout << "密碼輸入錯(cuò)誤!請(qǐng)重新輸入。" << endl; 18 Sleep(2000); 19 checkKey(a); 20 } 21 22 return; 23 } 24 25 int main() 26 { 27 char a[20]; 28 char shuRu[20] = {'\0'}; 29 30 int flag = 0; 31 32 cout << "請(qǐng)輸入賬號(hào)名: "; 33 cin >> shuRu; 34 strcat(shuRu,"@"); 35 36 FILE* fp; 37 fp = fopen("test.txt","rb"); 38 39 while(fscanf(fp,"%s",a) > 0) 40 { 41 42 if (strcmp(shuRu,a) == 0) 43 { 44 flag = 1; 45 fscanf(fp,"%s",a); 46 fscanf(fp,"%s",a); 47 break; 48 49 } 50 51 } 52 if (flag == 0) 53 cout << "用戶不存在,請(qǐng)注冊(cè)!" << endl; 54 55 else 56 checkKey(a); 57 58 fclose(fp); 59 return 0; 60 }?
?文件數(shù)據(jù):
運(yùn)行結(jié)果:
密碼匹配成功。
總結(jié):對(duì)于沒有用鏈表 + 結(jié)構(gòu)體的來寫帳戶登記的程序,屬于純文件信息處理。那么就只能差強(qiáng)人意的用一些方法來解決。用的是”排序定位“的方法。
代碼是追求高效,簡(jiǎn)潔的。一開始沒有用好的方法去解決,雖然也能通向羅馬,從程序的維護(hù)和更新的角度來看,是不推薦的。
?
轉(zhuǎn)載于:https://www.cnblogs.com/hlwyfeng/p/3900323.html
總結(jié)
以上是生活随笔為你收集整理的用数组实现从文件搜索帐户和验证密码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对Lucene PhraseQuery的
- 下一篇: Firefly官方教程之Netconne