用數組實現從檔案搜尋帳戶和驗證密碼

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   os   io   strong   

最近一個同學在寫個銀行管理系統,然後問我怎麼從檔案搜尋帳戶,給了方法後又不懂檔案裡面的密碼怎麼與輸入的匹配。一般來說,高效的做法是用鏈表實現。用數組實現不是高效的方法,而且浪費空間。再者,對於賬戶類有個人資訊集合的,一般用結構體,代碼寫起來也方便簡單。

但是他卻用數組來做,而且沒有用結構體。對於這種情況下如何搜尋帳戶,如何驗證密碼呢? 我嘗試了一下,發現不難解決。

解決這個問題的方法:用檔案資料的排序定位來做。

第一步:檔案資訊讀入                                            

 用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運行                                                

初步完成了這個功能,現在把完整代碼貼出來。

#include <iostream>#include <cstdlib>#include <cstring>#include <windows.h>using namespace std;//檢測密碼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;}int main(){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){flag = 1;fscanf(fp,"%s",a);fscanf(fp,"%s",a);break;}}if (flag == 0)cout << "使用者不存在,請註冊!" << endl;elsecheckKey(a);fclose(fp);return 0;}

我們來運行一下。

首先檔案資料如下:(每個帳戶的第三行為帳號,第五行為密碼)

運行結果:

第六步:bug修複                                                   

看上去好像完成了相應預期功能,但是細心觀察,不難發現一個bug。舉例說明一下:

當檔案內容為:

可以看出,第一個帳戶的密碼和第二個帳戶的帳號相同,都是aabbcc,此時程式運行就有錯誤,當搜尋到了aabbcc,程式就把他當成了帳號,於是出錯。

修複bug也很簡單,用一種特殊字元對帳號進行處理。比如在帳號後面追加一個 “@”。

因此,程式要修改兩個地方

1. 帳戶註冊後把資訊寫入檔案時,在帳號後面追加一個 “@”

2. 登入時,當輸入帳號完畢後,也給輸入的帳號後面追加一個“@”

第一個地方不是我們討論的範圍,我們來看看與本篇隨筆有關的要修改的第二個地方:

相關函數: strcat(str1,str2);實現把字元數組 str2 追加到 str1 後面。

代碼如下:

cout << "請輸入帳號名: ";cin >> shuRu;strcat(shuRu,"@");

 所以,當你登入時,輸入帳號完成按斷行符號鍵時,程式會自動給你輸入的帳號後面追加一個字元”@“,然後再與檔案資料進行比較。

修改後的完整代碼如下:

#include <iostream>#include <cstdlib>#include <cstring>#include <windows.h>using namespace std;//檢測密碼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;}int main(){char a[20];char shuRu[20] = {‘\0‘};int flag = 0;cout << "請輸入帳號名: ";cin >> shuRu;strcat(shuRu,"@");FILE* fp;fp = fopen("test.txt","rb");while(fscanf(fp,"%s",a) > 0){if (strcmp(shuRu,a) == 0){flag = 1;fscanf(fp,"%s",a);fscanf(fp,"%s",a);break;}}if (flag == 0)cout << "使用者不存在,請註冊!" << endl;elsecheckKey(a);fclose(fp);return 0;}

 檔案資料:

運行結果:

密碼匹配成功。

總結:對於沒有用鏈表 + 結構體的來寫帳戶登記的程式,屬於純檔案資訊處理。那麼就只能差強人意的用一些方法來解決。用的是”排序定位“的方法。

代碼是追求高效,簡潔的。一開始沒有用好的方法去解決,雖然也能通向羅馬,從程式的維護和更新的角度來看,是不推薦的。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.