1. 程式人生 > >大作業:小型購物車系統

大作業:小型購物車系統

中秋佳節,首先在這裡給各位看到文章的大佬說一聲:中秋快樂。中秋節還在CSDN的一定都是最刻苦的,我們都是有夢想的人,我們也一定能實現我們的夢想!!

程式碼多有漏洞,希望各位大佬幫忙指出,一定認真修改。

作業要求:

寫一個購物車系統,其中包括:1. 註冊;2. 登入;3. 購物;4. 支付;5.充值等功能。

# Coding: utf-8
# Author: Catalog Spri
# date: 2018/9/22
# time: 下午2:09

import os, sys     # 匯入os, sys庫,os庫用來操作檔案:刪除或重新命名;sys庫用來直接退出程式。


def register():
    '''
    將註冊功能封裝,方便後面直接呼叫
    :return: 返回值為True
    '''
    spec_char = ['&', '*', '$', '@', '#', '%', '!', '(', ')']   # 定義特殊字元列表,方便密碼合法性監測
    with open('account.txt', mode='a+', encoding='utf-8') as f_acc:  
        f_acc.seek(0)     # a+模式開啟,需要將檔案指標移至檔案頭
        sgn_name = input('Username>>:').strip()
        for line in f_acc:     # 迴圈輸出資料庫中的行
            line = line.split('|')
            if sgn_name == line[0]:    # 判斷使用者輸入使用者名稱和資料庫中使用者名稱是否重複。
                print('Username already exists, please re-try.')
                break
            if sgn_name[0].isdigit() or len(sgn_name) < 6 or len(sgn_name) > 16:
                print('Incorrect input, please re-try.')  # 判斷使用者名稱合法性
                break
        else:    # for迴圈正常結束,沒有被break打破,證明使用者名稱合法,執行else程式碼塊
            sgn_pwd = input('Password>>:').strip()
            for char in spec_char:  # 迴圈取出特殊字元列表中的字元
                if len(sgn_pwd) < 6 or char in sgn_pwd:   # 密碼合法性監測
                    print('Incorrect input, please re-try.')
                    break
            else:    # for迴圈正常結束,沒有被break打破,證明密碼合法,執行else程式碼塊
                print('Registration success')
                info = ('%s|%s|100000\n' % (sgn_name, sgn_pwd)) # 將使用者名稱、密碼、初始金額組成一個字串
                f_acc.write(info)    # 寫入使用者資料庫中
                f_acc.flush()
                return True     # 能走到這一步說明使用者註冊成功。


def log_in():
    '''
    將登入系統封裝,方便後面呼叫
    函式遇到return會直接結束函式
    :return: 返回值為布林值
    '''
    blacklist = {}   # 臨時黑名單計次系統
    while True:
        inp_name = input('Username>>:').strip()
        inp_pwd = input('Password>>:').strip()
        with open('blacklist.txt') as f_lock:    # 開啟黑名單檔案,判斷使用者名稱是否在黑名單中
            for line in f_lock:
                line = line.strip('\n')
                if inp_name == line:
                    print('Account has been locked.')
                    return False      # 如果使用者名稱在黑名單中,則直接結束登入函式,不再向下執行程式碼
        with open('account.txt') as f_msg:   # 判斷使用者名稱密碼與資料庫中使用者名稱密碼是否一致
            for line in f_msg:
                line = line.strip('\n').split('|')
                if inp_name == line[0] and inp_pwd == line[1]:
                    print('Login successful.')
                    return inp_name     # 登入成功則結束函式,不再向下執行程式碼
                if inp_name == line[0]:   # 能執行到這裡則使用者名稱不正確或密碼不正確,判斷使用者名稱是否正確,使用者名稱正確,密碼不正確,則應該新增到臨時黑名單計次資料中
                    if inp_name in blacklist:   # 使用者名稱已存在於臨時黑名單系統,則計次+1
                        blacklist[inp_name] += 1  
                    else:     # 使用者名稱不存在於臨時黑名單系統,則新增進臨時黑名單系統。
                        blacklist[inp_name] = 1
                    break
        with open('blacklist.txt', mode='a', encoding='utf-8') as f_lock:
            if blacklist.get(inp_name) == 3:  # 如果臨時黑名單系統中的次數已經達到三次,則鎖定賬戶,將賬戶名新增到黑名單檔案中。
                f_lock.write('%s\n' % inp_name)
                f_lock.flush()
            print('Username or password is incorrect, please re-try.\n')


def buy(goods_list, shopping_car):
    '''
    將購物功能封裝
    第一個引數為貨物清單,因為每次的貨品清單可能不同,所以不應該將貨物清單在函式中寫死,
可以在函式外寫好,然後以引數的形式傳入函式。
    第二個引數為購物車,不應該在函式中將購物車直接定義為空,因為不知道使用者購物車以前是否為空。
    :return:將購物車返回,方便後面充值時呼叫
    '''
    goods_dic = {}   # 將商品與商品前的序號建立聯絡
    count = 1    # 在商品前面加上序號
    print(' Product list '.center(50, '-'))
    for msg in goods_list:
        print(count, msg.center(15, ' '), goods_list[msg])
        goods_dic[str(count)] = msg
        count += 1
    goods_choice = input('Please enter the name of products \
or the number of produces. >>:').strip()   
    if goods_choice in goods_list or goods_choice in goods_dic:   # 判斷使用者輸入是否正確
        amount = input('How much do you want to buy?  >>:')  # 接收使用者購買數量
        if amount.isdigit():    # 判斷使用者輸入是否為純數字
            amount = int(amount)
        if goods_choice.isdigit():     # 判斷使用者輸入是否為純數字
            goods_name = goods_dic[goods_choice]  
        else:
            goods_name = goods_choice    # 將使用者輸入與商品名稱建立聯絡
        if goods_name in shopping_car:    # 判斷商品是否已經在購物車中,已存在則數量相加
            shopping_car[goods_name] += amount
        else:     # 未存在則新增進購物車
            shopping_car[goods_name] = amount
        return shopping_car   # 將購物車作為返回值
    print('Incorrect input, please re-try.')  # 使用者輸入不正確則執行改行


def pay(shopping_car):   # 以上面的購物車為引數傳入,實現支付功能
    '''
    將支付功能封裝
    :return:
    '''
    total = 0    # 用來存放總金額
    for item in shopping_car:   # 迴圈取出購物車中的所有商品
        single = goods[item] * shopping_car[item]   # 計算一種商品的總金額
        total += single    # 計算全部商品總金額
    with open('account.txt') as f1, open('Temporary Files', mode='w') as f2:  # 修改使用者資料庫中的金額。前天講到,修改檔案的兩種方法。可以作為參考來理解
        for line in f1:       
            line = line.strip('\n').split('|')
            if inp_name == line[0]:   # 判斷使用者名稱與資料庫中的使用者名稱是否一致
                money = int(line[2])  # 使用者名稱一致才能修改其後面的金額
                money -= total     
                if money < 0:
                    print('Insufficient balance')
                    return False     # 如果金額不足,則不能購買,結束函式
                else:
                    money = str(money)
                    line = '|'.join(line).replace(line[2], money)
                    f2.write('%s\n' % line)   # 金額充足,扣款成功,寫入使用者資料庫
                    f2.flush()
                    continue
            line = '|'.join(line)   # 使用者名稱與資料庫中的使用者名稱不一致則直接寫入資料庫
            f2.write('%s\n' % line)
        os.remove('account.txt')   
        os.rename('Temporary Files', 'account.txt')
        print('Payment successful.')


def charge():
    '''
    充值功能封裝
    :return:
    '''
    while True:     # 讓使用者輸入要充值的金額,若輸入錯誤則再次輸入
        charges = input('Please enter the amount >>:')
        if charges.isdigit():
            charges = int(charges)
            break
        else:
            print('Incorrect input.')
    with open('account.txt') as f1, open('Temporary Files', mode='w') as f2:
        for line in f1:     # 使用者充值成功需要更改資料庫中資料
            line = line.strip('\n').split('|')
            if inp_name == line[0]:   # 判斷使用者名稱與資料庫中哪一行相同
                money = int(line[2])   
                money += charges    # 使用者名稱匹配成功則進行充值
                money = str(money)
                print('Now your balance is %s.' % money)
                line = '|'.join(line).replace(line[2], money)
                f2.write('%s\n' % line)   # 將充值後的資料寫入資料庫
                f2.flush()   
                continue        # 跳過本次迴圈
            line = '|'.join(line)
            f2.write('%s\n' % line)   # 使用者名稱與資料庫中的匹配不成功則直接寫入資料部,不作修改
        os.remove('account.txt')
        os.rename('Temporary Files', 'account.txt')
        print('Recharge successful.')


'''
定義商品清單
'''
goods = {
    'iPhone XS Max': 9599,
    'iPhone XS': 8699,
    'iPad': 2565,
    'AirPods': 1276,
    'MacBook Air': 6928,
    'MacBook Pro': 11786,
}

'''
定義一個空字典,方便存放使用者要購買的商品,以商品和購買數量作為鍵值對
'''
shopping_car = {}

while True:
    choice = input('Log in or register?  >>:').strip().lower()   # 使用者輸入登入或註冊
    if choice == 'register':   # 使用者輸入註冊則執行register函式
        if register():      # 若註冊成功,register函式返回值為True,執行下面程式碼,執行不成功則返回外層迴圈。
            reg_choice = input('Press any key to return to the upper layer. \
Press q to exit the program >>:').strip()
            if reg_choice == 'q':
                sys.exit()
            else:
                continue
    elif choice == 'log in':   # 使用者輸入登入則執行log_in函式
        inp_name = log_in()   # log_in函式的返回值即為使用者名稱。需要將其賦予一個變數名方便呼叫
        while tag:
            if inp_name:
                print(' 功能選擇 '.center(50, '-'), end='')
                fun_choice = input('''
    1. 購物
    2. 支付
    3. 充值
    4. 退出
       >>>:''')
                if fun_choice == '1' or fun_choice == '購物':
                    buying = buy(goods, shopping_car)
                elif fun_choice == '2' or fun_choice == '支付':
                    try:    # 不購物直接支付會報錯,try語句可以使程式不報錯。
                        pay(buying)
                    except:   # 捕獲異常。
                        print('No items in the shopping cart.')
                elif fun_choice == '3' or fun_choice == '充值':
                    charge()
                elif fun_choice == '4' or fun_choice == '退出':
                    sys.exit()
                else:
                    print('Incorrect input, please re-try.')
            else:
                sys.exit()
    else:
        print('Incorrect input, please re-try.')
        sys.exit()