C++進階訓練——停車收費系統設計


一、簡介      

經過一段時間的c++基礎學習,是時候做一個較為全面的、運用c++功能的較復雜的項目練練手了。  

運用軟件:Visual Studio   (VS)。

題目:c++停車收費系統設計(某本編程書進階習題)        

要求: 管理員登陸; 有停車、取車、查詢實時停車情況三個功能; 按照停車后時間分段計時收費。        

分析: 管理員登陸需要密碼的不可視輸入,即輸入密碼輸出“*”,輸入錯誤用戶名或者錯誤密碼要報錯並且返回初始界面; 三個功能要基於寫入txt文件來實行,其中停車寫入信息,取車讀取信息並初始化信息,查詢輸出文件信息; 通過寫入文件的停車時間和取車時時間來計算停車分鍾,然后分段計時收費; 主界面需要實時顯示系統時間,並且在一段時間沒有操作后返回初始界面,標題要自定義為c++停車系統; 注意輸出格式; 文件信息應包括車位序號、車牌號、入庫時間(按指定位數輸出,如201808041128方便保存),停車時優先存在車位序號小的車位。        

流程圖如下圖所示。

 


 二、系統設計思路

 1 void mainspace();//主界面,功能界面
 2 
 3 void stop();//停車子函數
 4 
 5 void move();//取車子函數
 6 
 7 void check();//檢查當前庫存情況子函數
 8 
 9 int money(int n);//計時收費子函數
10 
11 void code();//密碼登陸子函數
12 
13 string hide(int size);//輸入密碼輸出*子函數     

 

 

根據流程圖大致需要以上幾個子函數,其中登陸界面包含code()和hide()兩個函數,主界面為mainspace(),三個操作功能一一對應一個子函數,其中取車多包含money()計時收費功能。      

根據分析,這些函數應分別實現以下功能:

code():密碼登陸界面,用戶名與密碼預先設置好,若輸入錯誤則報錯並返回登陸界面,成功則進入主界面

hide():輸入一個字符時在操作台上不顯示本來字符,並輸出一個“*”

mainspace():輸出三個功能選擇,跳轉頁面

stop():將停車的三個信息(車位序號,車牌號,停車時間)寫入txt文件,車位序號小數字優先,其中停車時間由讀取當前系統時間進行處理

move():將選擇的車位序號的那一行信息刪除

check():將txt文件內容全部輸出

money():讀取選擇的車位序號的那一行信息,並處理計算得出停車時間並計時收費

三、函數功能實現

  1 #include <iostream>
  2 #include <ctime>
  3 #include <string>
  4 #include <stdio.h>
  5 #include <conio.h>
  6 #include <cstdlib>
  7 #include <windows.h>
  8 #include <iomanip>
  9 #include <fstream>
 10 using namespace std;
 11 void mainspace();//主界面,功能界面
 12 void stop();//停車子函數
 13 void move();//取車子函數
 14 void check();//檢查當前庫存情況子函數
 15 int money(int n);//計時收費子函數
 16 void code();//密碼登陸子函數
 17 string hide(int size);//輸入密碼輸出*子函數
 18 int park[10] = { 1,1 };//停車位序號,此時txt里預設了兩組數據
 19 struct pay //返回自定義值
 20 {
 21     int timemin;
 22     int money;
 23 }pay1;
 24 int main()
 25 {
 26     SetConsoleTitle("Stop Cars");//標題
 27     while (1) {
 28         time_t now = time(0);
 29         tm *ltm = localtime(&now);
 30         cout << 1900 + ltm->tm_year << "." << 1 + ltm->tm_mon << "." << ltm ->tm_mday << endl;
 31         cout << ltm->tm_hour << ":" << ltm->tm_min << endl;//輸出時間
 32         code();
 33         mainspace();
 34         Sleep(60000);//一段時間不操作返回初始界面
 35         system("cls");
 36     }
 37 }
 38 void mainspace()
 39 {
 40     cout << "功能" << endl;
 41     cout << "1.停車" << endl;
 42     cout << "2.取車" << endl;
 43     cout << "3.查詢" << endl;
 44     int x;
 45     cin >> x;
 46     switch (x)
 47     {
 48     case 1:stop(); break;
 49     case 2:move(); break;
 50     case 3:check(); break;
 51     }
 52 }
 53 void code()
 54 {
 55     string name = "linuas";
 56     string pw = "111111";
 57     string name1;
 58     string code;
 59     while (1)
 60     {
 61         cout << "請輸入用戶名:" << endl;
 62         cin >> name1;
 63         if (strcmp(name1.c_str(), name.c_str()) == 0)
 64         {
 65             system("cls");
 66             cout << "請輸入密碼:" << endl;
 67             code = hide(7);
 68             if (strcmp(pw.c_str(), code.c_str()) == 0)
 69             {
 70                 system("cls");
 71                 cout << "登陸成功!" << endl;
 72                 Sleep(2000);
 73                 break;
 74             }
 75             else cout << endl << "密碼錯誤!" << endl;
 76             Sleep(2000);
 77             system("cls");
 78             continue;
 79         }
 80         else cout << endl << "用戶名不存在!" << endl;
 81         Sleep(2000);
 82         system("cls");
 83         continue;
 84     }
 85 }
 86 string hide(int size)
 87 {
 88     char c;
 89     int count = 0;
 90     char *password = new char[size]; // 動態申請空間
 91     string str;
 92     while ((c = _getch()) != '\r') {
 93 
 94         if (c == 8) { // 退格
 95             if (count == 0) {
 96                 continue;
 97             }
 98             putchar('\b'); // 回退一格
 99             putchar(' '); // 輸出一個空格將原來的*隱藏
100             putchar('\b'); // 再回退一格等待輸入
101             count--;
102         }
103         if (count == size - 1) { // 最大長度為size-1
104             continue;
105         }
106         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <=            '9')) {  // 密碼只可包含數字和字母
107             putchar('*');  // 接收到一個字符后, 打印一個*
108             password[count] = c;
109             count++;
110         }
111     }
112     password[count] = '\0';
113     str = password;
114     return str;
115 }
116 void stop()
117 {
118     int n = 0;
119     int i = 0;
120     string str;
121     time_t now = time(0);
122     tm *ltm = localtime(&now);//獲取當前系統時間准備寫入
123     cout << "請輸入車牌號:" << endl;
124     cin >> str;
125     for (i = 0; i < 10; i++)//車位序號存在與否判定
126     {
127         if (park[i] != 1)
128         {
129             n = i;
130             break;
131         }
132         else continue;
133     }
134     park[n] = 1;
135     ofstream outfile("C:\\Users\\Linuas\\Desktop\\demo.txt", ios::app);//寫入文件式打開
136     outfile << endl << n << " " << str << " " << (1900 + ltm->tm_year) * 10000 + (1 + ltm->tm_mon) * 100 +ltm->tm_mday << " " << (ltm->tm_hour) * 100 + ltm->tm_min;
137     outfile.close();//寫入成功后關閉文件,切記!
138     cout << "停車成功" << endl;
139     Sleep(2000);
140     mainspace();
141 }
142 void check()
143 {
144     ifstream myfile("C:\\Users\\Linuas\\Desktop\\demo.txt");
145     string temp;
146     cout << "車位 " << "車牌號 " << "停車時間" << endl;
147     while (getline(myfile, temp))
148     {
149         cout << temp << endl;
150     }
151     myfile.close();
152     mainspace();
153 }
154 void move()
155 {
156     ifstream file("C:\\Users\\Linuas\\Desktop\\demo.txt");
157     string line;
158     int m, n, count = 0;
159     ofstream outfile("test2.txt", ios::out | ios::trunc);
160     cout << "您停車的車位是:" << endl;
161     cin >> m;
162     n=money(m)+1;
163     n = m + 1;
164     while (!file.eof()) {
165         getline(file, line);
166         if (count != n - 1)//保留行
167             outfile << line << endl;
168         count++;
169     }
170     outfile.close();
171     file.close();
172     ofstream outfile1("C:\\Users\\Linuas\\Desktop\\demo.txt", ios::out | ios::trunc);
173     fstream file1("test2.txt");
174     while (!file1.eof()) {
175         getline(file1, line);
176         outfile1 << line << endl;
177     }
178     outfile1.close();
179     file1.close();
180     system("del test2.txt");//刪除中間文件
181     Sleep(2000);
182     mainspace();
183 }
184 int money(int n)
185 {
186     fstream infile;
187     infile.open("C:\\Users\\Linuas\\Desktop\\demo.txt", ios::in);
188     string line;
189     int count = 0;
190     int a, b, c, d;
191     int b1, b2, c1, c2;
192     if (n == 0) { infile >> a >> line >> b >> c; }
193     else
194     {
195         while (!infile.eof()) {
196             getline(infile, line);//自動回車了一次
197             if (count == n - 1)
198             {
199                 infile >> a >> line >> b >> c;
200             }
201             count++;
202         }
203     }
204     infile.close();
205     d = b % 10000;
206     b1 = d % 100;
207     b2 = (d - b1) / 100;
208     c1 = c % 100;
209     c2 = (c - c1) / 100;
210     time_t now = time(0);
211     tm *ltm = localtime(&now);
212     pay1.timemin = (1 + ltm->tm_mon - b2) * 31 * 24 * 60 + (ltm->tm_mday - b1) * 24 * 60 + (ltm->tm_hour -        c2) * 60 + ltm->tm_min - c1;
213     if (pay1.timemin <= 15)
214     {
215         pay1.money = 10;
216     }
217     else if (pay1.timemin <= 60)
218     {
219         pay1.money = 10 + pay1.timemin - 15;
220     }
221     else pay1.money = 60;
222     cout << "停車時間為" << pay1.timemin << "分鍾" << endl;
223     cout << "計時收費為" << pay1.money << "" << endl;
224     Sleep(2000);
225     return n;
226 }

其中,

str1=str2 即字符串相等時,strcmp(str1.c_str(),str2.c_str())=0。 因為 strcmp 的參數應為 char ,因此 string 定義的參數要加 .c_str(),如上所示。  c++定義字符時,用 string 比用 char 數組要簡便的多得多。

讀寫文件的三個格式:ifstream 只讀,ofstream 只寫,fstream 打開; 讀取和寫入指令:infile 讀取,outfile 寫入;其中 ios::app 表示從文件的末尾開始寫入。
在車位序號的循環中,推薦使用 for 循環而不是 while 減少崩潰幾率。
這里注意a=0時,if(a) 假,if(!a) 真, if(a=0) 假,if(a==0) 真,if(a!=0) 假的關系。
切記,打開文件執行完操作后務必關閉文件,否則會出現不可名狀的錯誤!
move()這個函數的關鍵就是刪除 txt 文件中的指定行,而c++是沒有這樣的指令的。因此我們選擇曲線實現這個功能:先復制除了將要刪除那一行的數據到一個臨時文件,再清空原文件,之后將臨時文件的數據復制到原文件並刪除臨時文件即可實現這個功能。
money()這個函數要實現讀取特定行的 int 型內容並計算的功能,用 getline 的特性來獲取定位行的功能; 然后就是存在文件的時間與當前系統時間進行計算,如201808061123分解成2018年8月6日11時23分。

四、程序運行圖示

登陸界面。

密碼不可視輸入。

主界面。

 停車指令。

查詢現在停車場的情況。

此時txt文件情況。

 

 

取車計算時間與收費。

取車完后刪除那一行信息。

五、總結與分享

總的來說,這個項目還算有些內容,是即將開始的下一個項目的很好的台階。希望大家一起學習,在代碼學習的道路上越走越遠,頭發越掉越少!

下個項目,某為校招筆試題。

作者:會武術的白貓
https://www.bilibili.com/read/cv899072
出處: bilibili

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM