员工管理程序问题集

问题点1
遍历list,使用del删除空时,连续4个空,只能删除两个,因为删除时原list索引变化。
使用range(len-1,-1,-1)从后面往前删,保证了未删除的元素索引不变化。

问题点2:
解决select name , age from staff_table where age > 22
Name,age之前空格问题
Sql三个关键词,位置对应0,2,4,但是以空格为分割符,name和age之问有空格,就不能判断2的位置是from的位置,所以需要把from到select之间的元素合成一个。
方法二:
search 三个关键字,字符串切片,这种方法简单。:),不高大上。其实我想做一个同时解析出update和select语句的牛X代码,,,,,,

问题3:
格式化后的字段和条件字符串位置不一样,
['select', 'age,name', 'from', 'staff_table', 'where', '22>age']
原字符串拼接语句:field = field + sql_list[i]
修改成:field = sql_list[i] +field

问题4:
Sql语句查询条件解析,需要判断各个运算符号。
使用eval()可以直接返回运算结果,使用 try判断不是条件或者条件格式错误,提示错误,返回False。

问题5:
当出现错误时,在不同功能里,需要重复打印相同错误
把所有错误统一处理,写在一个函数,当处理错误非学多的时候,代码块特别长。后来,每个错误都做成单独函数,返回错误值,使用装饰器捕捉错误,打印提示。代码块小,管理方便。
但是,使用此方式会报变量未定义错误,所以需要初始化变量值。

问题6:
解析sql语句的select和update时,使用每句的关键字进行判断,要把select和update都做一遍。
做成函数,关键字动态以后,同一段代码可以解析两条不同关键字语句。

问题点7:
Eval()和exec()作为两个运行字符串的神奇的函数,给我留下了超级大坑。所以必须重点写一下。
背景:制作update和select语句时,总想把语句做的智能化一些,代码也尽可能的短,所以想到了eval()和exec().
过程:在处理select的查询条件时,eval()确实十分有用,给对应变量赋值就可以判断。
但是处理update的赋值时,使用exec()遇到了莫名妙的问题,在s=’dept=”IT”’, 执行exec(s)时,dept始终是初始值,没有变化。查资料发现原来是限于全局变量,如果在函数内用处理起来十分麻烦,但是可能在类里面能够正常,没学到类,以后补充。

问题10
程序终于做完了,测试时候功能也实现了,但是,fuck了,文件存的数据有空行,打印出来的信息也是没有规律的空行!!!!
越改格式出现的问题越多,后来回了一个写入文件函数,所有写入数据库的都需要格式化一下,然后数据格式就好了。

def strip_and_enter(string):
    ds_enter = string.strip()+'\n'
    return ds_enter

问题9
装饰器,终极版。
其实就是外面再套一层函数。套的多了自然就迷糊了,迷糊了就是高大上~~

附上很烂的程序原代码

#!-*- coding:utf-8 -*-
# __author__ = 'david'

"""
员工信息管理系统

1.使用select语句查找
2.条件格式支持symbol_list里面的所有符号
3.select支持自定义显示字段。
4.update也可以使用条件格式,支持symbol_list里面的所有符号
5.每个功能使用一次后返回主菜单,所以有些显示信息可能被冲掉
6.登陆信息时不能中途退出
7.子菜单第一个输入界面可以使用q返回
8.删除功能,可以自定义字段

--------
待改进:
1.search模块功能繁琐
2.删除功能,模糊查找
3.条件格式不支持not and or
4.装饰器,可以捕捉更多错误
5.文件目录没有设计

"""

# def sql_delete_blank(sql)                                 删除sql语句多余空格
# def format_sql()                                          按关键字组合成列表 格式:
#               format_sql(key_0, key_2, key_4, sql_list=sql_delete_blank(input_sql))

# def try_eval(string)                                      检测eval合法性
# def try_int(num):                                         检测数字类型的合法性
# def str_check(string, length_min=4, length_max=20)        检测字符字段的值合法性
# def num_check(string, length_min=4, length_max=20)        检测数字字段的值合法性
# def sql_delete_blank(sql)                                 用空格分割成列表,并删除列表里的所有空格
# def format_sql(key_0, key_2, key_4, sql_list):            以sql语句格式化sql_delete_blank处理过的列表
# def check_field(field_str, em_info_filed=original_filed)  select字段显示控制,可以支持自定义字段
# def show_info(field, line_list)                           查询显示函数,可以和更新、删除做在一起,后续优化
# def copy_file(source_file, target_file)                   复制文件
# def search()                                             根据条件查询函数,本来做个通用的,发现太大,花费了许许多多时间
# def search(sql, func_choice, source_file=main_file, target_file=temp_file)

# def check_exist(index, value, source_file=main_file)      检测文件里是不是存在数据,比上面功能单一,可以合并成一个
# def append_user()                                         追加用户函数,返回追加的信息
#               def append_user(filed_list, check_num_filed, check_str_filed, append_file_name=main_file)
# def del_user(del_index, del_value, source_file, target_file) 删除用户函数,显示删除的用户信息
# def show_error(func)                                      装鉓器,获取错误,打印提示
# sql_list = []
# sql_list_temp = []
# index = 0
# em_info_filed
import os
# #############初始化值################ #
main_file = 'em_info.txt'
temp_file = 'em_info_temp.txt'
original_filed = ['staff_id', 'name', 'age', 'phone', 'dept', 'enroll_date']
original_filed_dict = {'staff_id': None, 'name': None, 'age': None,
                       'phone': None, 'dept': None, 'enroll_date': None}
# 限制字段值的一些条件
num_filed = {'staff_id': (1, 99999999999, 88),  'age': (10, 99, 23), 'phone': (11111111111, 99999999999, 13899998888)}
str_filed = {'name': (1, 30, 'Edmond'), 'dept': (1, 99, 'IT'), 'enroll_date': (6, 20, '2018-08-08')}

menu_list = ['非常牛X的员工信息操作面板', '1.模糊查询', '2.模糊修改', '3.新建员工', '4.删除员工', '5.退出程序']
select_sql = """select name,age from staff_table where age > 22"""
update_sql = """UPDATE  staff_table  SET dept ="Market" where dept = "IT" """
symbol_list = [' in ', '>=', '<=', '=', '>', '<']
main_key = 'phone'
em_info = """1,Alex Li,22,13651054608,IT,2013-04-01
2,Da Peng,65,13265234552,SH,2013-04-01
3,Event,24,18652434308,IT,2013-04-01
4,Pan Da,44,15523422223,HR,2013-04-01
"""
# 创建原始文件:
if os.path.exists('main_file'):
    pass
else:
    with open(main_file, 'w', encoding='utf-8') as file:
        file.write(em_info)

def menu(m_list):
    for i in m_list:
        print(i)

def strip_and_enter(string):
    ds_enter = string.strip()+'\n'
    return ds_enter

def show_error(func):                                       # 装饰器,捕捉try_eval,try_int错误信息。
    def print_prompt(*args, **kwargs):
        prompt = func(*args, **kwargs)
        if prompt == 'EvalError':
            print('输入条件格式错误,请正确输入!')
            return False
        if prompt == 'IntError':
            print('输入数字格式错误,请正确输入!')
            return False
        else:
            return True
    return print_prompt

@show_error
def try_eval(string,staff_id=0, name='', age=0, phone='', dept='', enroll_date='', *args, **kwargs):

    print(dept)
    try:
        eval(string)
    except:
        return 'EvalError'

@show_error
def try_int(num):
    try:
        int(num)
    except:
        return 'IntError'

def str_check(string, length_min=4, length_max=20):
    string = string.replace('"', '')
    if length_min < len(string) < length_max:
        str_list = string.strip().split(' ')
        for i in range(len(str_list)):
            if str_list[i].isalnum():
                pass
            else:
                print('含有非法字符!')
                return False
        else:
            return True
    else:
        print('长度不符合要求,需要在%d和%d之间'.strip() % (length_min, length_max))
        return False

def num_check(number, num_min=11111111111, num_max=99999999999):
    if number.isdigit():
        if num_min < int(number) < num_max:
            return True
        else:
            print(strip_and_enter('值不符合要求,需要在%d和%d之间,'.strip() % (num_min, num_max)))
            return False
    else:
        print('只能是数字!')
        return False

def sql_delete_blank(sql):
    sql_list = sql.strip().split(" ")
    index = len(sql_list)-1
    for i in range(index, -1, -1):
        temp = sql_list[i].lower()
        if temp == '':                                      # 去除语句中多余的空格
            del sql_list[i]
    return sql_list

def format_sql(key_0, key_2, key_4, sql_list):
    field = ''
    condition = ''
    condition_str = ''
    index = k0 = k2 = k4 = len(sql_list)-1
    for i in range(index, -1, -1):
        temp = sql_list[i]
        if temp.lower() == key_4:                # 用于截取条件语句的阀值w=1截取结束
            k4 = 1
        elif temp.lower() == key_2:
            k2 = 1
        elif temp.lower() == key_0:
            k0 = 1

        if k4 != 1:                                     # 用于组合位置5
            if temp.lower() == 'like':
                temp = ' in '                           # 把like换成in 放便使用eval
            elif temp.lower() == '=':                           # 把=好换成==,用于eval
                temp = '=='
            condition_str = temp + condition_str
            del sql_list[i]

        elif k4 == 1 and k2 != 1 and temp.lower() != key_4:                 # 用于组合位置3
            condition = temp + condition
            del sql_list[i]

        elif k2 == 1 and k0 != 1 and temp.lower() != key_2:    # 用户于组合位置1
            field = temp.lower() + field
            del sql_list[i]
    if ' in ' in condition_str:
        re_split = condition_str.strip().split(' ')
        condition_str = re_split[-1] + ' ' + re_split[1] + ' ' + re_split[0]
    sql_list.insert(1, field)
    sql_list.insert(-1, condition)
    sql_list.append(condition_str)
    if sql_list[0].lower() != key_0 or sql_list[2].lower() != key_2 or sql_list[4].lower() != key_4 :
        sql_list = [0, 0, 0, 0, 0, 0]
    return sql_list

def check_field(field_str, em_info_filed=original_filed):
    # 判断字段是否存在,存在,反回所有字段列表,不存在返回空,提示错误!
    if field_str == '*':                        # *是全字段,不需要进一步解析
        return em_info_filed
    field_show = []
    field_list = field_str.split(',')
    for fi in field_list:
        if fi in em_info_filed:
            field_show.append(fi)
        else:
            field_show.clear()
            return field_show                   # 如果输入字段没在原始字段里,返回空列表=False
    return field_show                           # 如果全在原始字段里,返回list

def show_info(field, line_list):
        field_input = check_field(field)
        if field_input:
            f3 = line_list
            field_dict = dict(zip(original_filed, f3))
            for show in field_input:
                print(field_dict[show].ljust(20, ' '), end='')

def copy_file(source_file, target_file):
    with open(target_file, 'w', encoding='utf-8') as target_file_write,\
            open(source_file, 'r', encoding='utf-8') as file_read:
        file_read_line = file_read.readline()
        while file_read_line:
            target_file_write.write(file_read_line)
            file_read_line = file_read.readline()

def search(sql, func_choice, source_file=main_file, target_file=temp_file):
    count = 0
    field_str = ''
    update_value = ''
    condition = sql[-1].lower()

    if func_choice == 1:
        field_str = sql[1]
    if func_choice == 2:
        update_value = sql[3]

    with open(source_file, 'r') as file_search,\
            open(target_file, 'w') as file_temp:
        fs = file_search.readline()
        while fs:
            temp_list = fs.strip().split(',')
            staff_id = int(temp_list[0])
            name = temp_list[1].lower()
            age = int(temp_list[2])
            phone = temp_list[3]
            dept = temp_list[4].lower()
            enroll_date = temp_list[5]
            if eval(condition):
                if func_choice == 1:
                    show_info(field_str, temp_list)
                    count += 1
                if func_choice == 2:
                    tem = update_value.split('=')
                    tem[0] = tem[0].strip().lower()
                    tem[1] = tem[1].strip(' ').strip('"')
                    if tem[0] == 'name':
                        temp_list[1] = tem[1]
                    if tem[0] == 'age':
                        temp_list[2] = tem[1]
                    if tem[0] == 'phone':
                        temp_list[3] = tem[1]
                    if tem[0] == 'dept':
                        temp_list[4] = tem[1]
                    if tem[0] == 'enroll_date':
                        temp_list[5] = tem[1]
                    fs = '%s,%s,%s,%s,%s,%s' % (str(temp_list[0]), str(temp_list[1]), str(temp_list[2]),
                                                 str(temp_list[3]), str(temp_list[4]), str(temp_list[5]))
                    print(strip_and_enter(fs), end='')
                    count += 1
                if func_choice == 3:
                    pass

            file_temp.write(strip_and_enter(fs))
            fs = file_search.readline()
        return count

def check_exist(index, value, source_file=main_file):
    id_field = ''
    temp_list = []
    with open(source_file, 'r', encoding='utf-8') as check_main_key:
        f = check_main_key.readline()
        while f:
            temp_list = f.strip().split(',')
            if temp_list[index] == value:
                print(temp_list)
                id_field = ''
                return id_field
            else:
                id_field = temp_list[0]
            f = check_main_key.readline()

    return id_field

def append_user(filed_list, check_num_filed, check_str_filed, append_file_name=main_file):
    f = ''
    check = ''
    value = ''
    value_type = ''
    fs = ''
    value_example = ''
    temp_list = []
    for f in filed_list:
        if f in check_num_filed:
            value_type = '数字'
            value_example = str(check_num_filed[f][2])
        else:
            value_type = '字符'
            value_example = str(check_str_filed[f][2])

        while True:
            if filed_list.index(f) == 0:
                temp_list.append('0')
                break
            value = input("请输入[%s],%s类型,示例[%s]:" % (f, value_type, value_example)).strip()
            if f in check_num_filed:
                check = num_check(value, check_num_filed[f][0], check_num_filed[f][1])
            else:
                check = str_check(value.replace('-', ' '), check_str_filed[f][0], check_str_filed[f][1])

            if f.strip() == main_key:
                if check_exist(filed_list.index(main_key), value):
                    temp_list[0] = int(check_exist(filed_list.index(main_key), value))+1
                else:
                    print('[%s]必须唯一,请重新输入' % f)
                    continue

            if check:
                temp_list.append(value.strip('"').strip("'"))
                break
            else:
                print("请重新输入")
                continue
    else:
        fs = '%s,%s,%s,%s,%s,%s' % (str(temp_list[0]), str(temp_list[1]), str(temp_list[2]),
                                         str(temp_list[3]), str(temp_list[4]), str(temp_list[5]))
        with open(append_file_name, 'a', encoding='utf-8') as append:
            append.write(strip_and_enter(fs))
        return fs

def del_user(del_index, del_value, source_file, target_file):
    s_list = []
    count = 0
    with open(source_file, 'r', encoding='utf-8') as s_file,\
                open(target_file, 'w', encoding='utf-8') as t_file:
        s_line = s_file.readline()
        while s_line:
            s_list = s_line.strip().split(',')

            if s_list[del_index].strip().lower() == del_value.lower():
                print("{0:10}{1:10}{2:10}{3:10}{4:10}{5:10}".format(*s_list))
                count += 1
                s_line = s_file.readline()
                continue
            t_file.write(strip_and_enter(s_line))
            s_line = s_file.readline()
        else:
            return count

while True:
    menu(menu_list)
    choice = input('请选择对应数字:').strip()
    if choice == '1':                                       # 查询
        while True:
            c1 = input("您已选择[%s],请输入查询语句:\n[例如:%s]" % (menu_list[int(choice)], select_sql)).strip()

            if c1.lower() == 'q':                           # q返回列表
                print('您已返回列表。')
                break

            a1 = sql_delete_blank(c1)                           # 删除中间多余的空格
            a = format_sql('select', 'from', 'where', a1)   # 判断select语句格式

            if try_eval(a[-1]):                               # 条件语句合法性检查
                a2 = search(a, 1)                             # a2查询数量
                if a2:
                    print("本次共查询到[%d]条记录。" % a2)
                else:
                    print("对不起,没有查到符合条件的记录。")
                break
            else:
                pass

    elif choice == '2':                                     # 更新
        while True:
            c2 = input("您已选择[%s],请输入修改语句:\n[例如:%s]" % (menu_list[int(choice)], update_sql)).strip()

            if c2.lower() == 'q':                           # q返回列表
                print('您已返回列表。')
                break

            c2 = c2.replace(' WHERE ', ' where ').replace('UPDATE ', 'update ').replace(' SET ', ' set ')
            # 关键字不影响值,所以替换小写方便使用
            c2_a = c2.strip().split(' where ')                 # c2_a[1]是条件
            c2_b = c2_a[0].strip().split(' set ')              # c2_b[1]是赋值
            if len(c2_a) == 2 and len(c2_b) == 2:
                s = []
                s2_0 = sql_delete_blank(c2_b[0])                # set前面的语句列表,删除所有空格
                s2_1 = sql_delete_blank(c2_a[1])                # where 后面的语句列表,删除所有空格
                s.extend(s2_0)
                s.extend(['set'])
                s.extend([c2_b[1].strip()])                     # 姓名有空格,所以赋值语句不能使用sql_delete_blan删除空格
                s.extend(['where'])
                s.extend(s2_1)                                  # 以上主要是空格处理,完成后按原来格式组合
                s = format_sql('update', 'set', 'where', s)
                if s and try_eval(s[-1]):                        # 条件表达式格式通过
                    s3_list=s[3].strip().split('=')              # 开始判断赋值语句
                    s3_list[0] = s3_list[0].strip()
                    s3_list[1] = s3_list[1].strip()
                    if s3_list[0].lower() in num_filed:          # 判断字段合法,并且是数字字段
                        # 判断数字值的有效性
                        if num_check(s3_list[1], num_filed[s3_list[0]][0], num_filed[s3_list[0]][1]):
                            pass
                        else:
                            continue
                    elif s3_list[0].lower() in str_filed:         # 判断字段合法,并且是数字字段
                        # 判断字符值的有效性
                        if str_check(s3_list[1], str_filed[s3_list[0]][0], str_filed[s3_list[0]][1]):
                            pass
                        else:
                            continue
                    else:
                        print('更新字段错误,请重试!')
                        continue

                    get_flag = search(s, 2)                        # get_flag返回值,判断是否找到记录
                    if get_flag:
                        print("本次共更新了[%d]条记录。" % get_flag)
                        copy_file(temp_file, main_file)
                        os.remove(temp_file)
                        break
                    else:
                        print("对不起,没有符合条件的记录,返回主菜单....")
                        break

    elif choice == '3':                                           # 追加
        while True:
            cq = input('[q]返回,任意键添加用户...')
            if cq.lower() == 'q':                           # q返回列表
                print('您已返回列表。')
                break
            c3 = append_user(original_filed, num_filed, str_filed)     # 直接调用追加函数,c3返回的是用户信息。
            if c3:
                print('添加成功!您的信息是:\n', c3)
                break
            else:
                print('未知错误:已被你玩坏!')

    elif choice == '4':       # 删除,可以自定义用来检索的字段,所以比较长,较长,长,长。。。
        while True:
            delete_str = 'staff_id'.strip()                       # 如果变成input可以实现自定义条件字段
                            # delete_str = input('试一次会咋样,字段名'),strip()    如果解除input可以实现自定义

            if delete_str.lower() == 'q':                           # q返回列表
                print('您已返回列表。')
                break

            if check_field(delete_str):                            # 判断字段有效性
                break
            else:
                print('找不到[%s]字段,可选择字段有:\n' % delete_str, original_filed)

        if delete_str.lower() == 'q':                           # q返回列表
            continue

        while True:                                                     # 读取字段属性,并检测输入值有效性
            value_4 = input('已经选择[%s]字段,请输入值:' % delete_str).strip()
            if delete_str in num_filed:
                if num_check(value_4, num_filed[delete_str][0], num_filed[delete_str][1]):
                    break
            elif delete_str in str_filed:
                if str_check(value_4, str_filed[delete_str][0], str_filed[delete_str][0]):
                    break
            else:
                print('值[%s]不符合要求!请重新输入....' % value_4)

        index_4 = original_filed.index(delete_str)               # 获取些字段的位置
        if not check_exist(index_4, value_4):                        # 查找值在文件中存在,开始调用
            del_count4 = del_user(index_4, value_4, main_file, temp_file)     # 删除用户,新表存放在temp_file
            copy_file(temp_file, main_file)                                   # 数据复制回主文件
            os.remove(temp_file)
            print("一共删除了[%s]条记录。" % del_count4)

    elif choice.lower() == 'q' or choice== '5':                                   # 退出
        print('谢谢使用,再见!')
        break
    else:
        print('输入无效,请重试')

# 因为select form where是关键字,所以判断这三个位置是不是0,2,4
# if sql_list[0].lower() == 'select' and sql_list[2].lower() == 'form' and sql_list[4].lower() == 'where':

转载于:https://blog.51cto.com/yishi/2047223

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值