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