wordcount程序實現與測試

GitHub地址

https://github.com/jiaxuansun/wordcounthtml

PSP表格

PSP PSP階段 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 10 5
·Estimate 估計這個任務須要多少時間 10 5
Development 開發 510 500
·Analysis 需求分析 (包括學習新技術) 40 30
·Design Spec 生成設計文檔 20 20
·Design Review 設計複審 (和同事審覈設計文檔) 10 10
·Coding Standard 代碼規範 (爲目前的開發制定合適的規範) 10 10
·Design 具體設計 30 30
·Coding 具體編碼 300 240
·Code Review 代碼複審 40 40
·Test 測試(自我測試,修改代碼,提交修改) 60 120
Reporting 報告 70 80
·Test Report 測試報告 30 40
·Size Measurement 計算工做量 10 10
·Postmortem & Process Improvement Plan 過後總結, 並提出過程改進計劃 30 30
合計 590 585

解題思路

對總體程序的功能需求進行劃分以下:python

  • 參數分析功能:判斷命令行的參數,保存所作的選項,並根據選項執行相應的命令,而後輸出的結果git

  • 查找文件功能:查找輸入的文件須要支持如"*.c"等簡單匹配符,在有-s選項的狀況下,須要在當前目錄下遞歸查找文件github

  • 基本計數功能:實現課設基本功能要求的計算文件字符數、行數、單詞數的功能app

  • 代碼計數功能:實現課設擴展功能要求的計算文件代碼行數、空行數、註釋行數的功能函數

根據功能複雜程度選擇Python語言完成做業學習

程序設計實現

根據分析結果將代碼分爲以下幾個模塊:測試

  • 入口代碼:設定所須要支持的參數內容
  • main函數:查找目錄下全部的目標文件,對每個文件調用基本功能函數和擴展功能函數,並將結果返回;若選擇-s選項,則遞歸查找當前目錄下的各個目錄
  • wordcount函數:實現課設要求的基本功能
  • codecount函數:實現課設要求的擴展功能

代碼說明

入口和標準庫的參數解析對象初始化:

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="word count")
    parser.add_argument("-o", "--output", type=str, default="result.txt")
    parser.add_argument("-c", "--bytes", action="store_true")
    parser.add_argument("-w", "--words", action="store_true")
    parser.add_argument("-l", "--lines", action="store_true")
    parser.add_argument("-s", "--recursive", action="store_true")
    parser.add_argument("-a", "--code", action="store_true")
    parser.add_argument("-e", "--stoplist", type=str)
    parser.add_argument("filename", type=str)
    args = parser.parse_args()
    result = main(args, os.getcwd())
    print_result(args, result)

查找目錄並根據不一樣的參數來調用不一樣的功能函數:

def main(args, rootpath):
    result = []
    filename = args.filename.replace("*", "\\w*")
    if args.recursive:
        for name in os.listdir(rootpath):
            path = os.path.join(rootpath, name)
            if os.path.isdir(path):
                result += main(args, path)
            elif re.findall(filename, name):
                fd = open(path)
                wc = wordcount(fd.read())
                if args.stoplist:
                    fd.seek(0)
                    content = fd.read()
                    stoplist = open(args.stoplist)
                    stopchars = stoplist.read().split()
                    count = 0
                    for c in stopchars:
                        count += len(re.findall(c, content))
                    r["words"] -= count
                    stoplist.close()
                if args.code:
                    fd.seek(0)
                    wc.update(codecount(fd))
                wc["filename"] = name
                result.append(wc)
                fd.close()
    else:
        for name in os.listdir(rootpath):
            path = os.path.join(rootpath, name)
            if os.path.isdir(path):
                pass
            elif re.findall(filename, name):
                fd = open(path)
                wc = wordcount(fd.read())
                if args.stoplist:
                    fd.seek(0)
                    content = fd.read()
                    stoplist = open(args.stoplist)
                    stopchars = stoplist.read().split()
                    count = 0
                    for c in stopchars:
                        count += len(re.findall(c, content))
                    r["words"] -= count
                    stoplist.close()
                if args.code:
                    fd.seek(0)
                    wc.update(codecount(fd))
                wc["filename"] = name
                result.append(wc)
                fd.close()

    return result

基本功能實現:

def wordcount(content):
    print(re.split(r"[\s,]+", content))
    result = {
        "words": len(re.split(r"[\s,]+", content))-1,  # 單詞數
        "lines": len(content.split('\n'))-1,  # 行數
        "bytes": len(content)-1  # 字符數
    }

    return result

擴展功能實現

def codecount(fd):
    codelines = 0
    blanklines = 0
    commentlines = 0
    isComment = False
    isString = False
    isCode = False
    for line in fd.readlines():
        line = line.strip().replace('{', '').replace(
            '}', '').replace(';', '')  # 去掉{};以便計算空行
        if not isComment and not line:
            blanklines += 1
            continue
        if isComment:
            commentlines += 1
        elif line.replace('/', '').replace('*', ''):
            codelines += 1
        line = '\n'+line+'\n'
        for i in range(1, len(line)):
            if line[i] == '"' and line[i-1] != '\\':
                isString = not isString
            if not isString:
                if line[i] == '/' and line[i+1] == '/' and not isComment:
                    if not line[:i].split():
                        blanklines += 1
                    commentlines += 1
                    break
                if line[i] == '/' and line[i+1] == '*' and not isComment:
                    isComment = True
                    commentlines += 1
                    i += 1
                if line[i] == '*' and line[i+1] == '/':
                    isComment = False
                    i += 1

    result = {
        "codelines": codelines,
        "blanklines": blanklines,
        "commentlines": commentlines
    }

    return result

測試設計過程

如何設計測試用例

測試時應重點考慮邊界值以及特殊狀況,使測試用例最大程度覆蓋代碼。
思想是使每個判斷語句都執行一遍,實現條件覆蓋,儘可能讓每個判斷語句在是與否的狀況下都能執行一遍,實現語句覆蓋。編碼

哪些地方會致使程序高風險

當輸入文件內容爲空或輸入大於文件內容的邊界時會致使程序高風險命令行

測試代碼設計

  • test1.c
File write,name = new File(outputPath);
            writename.createNe|wFile();
            Buffe,redWriter out = new BufferedWrit,er(new FileWriter(writename));
            out.close();

測試字符數統計

  • test2.c
test()
{
File writename = new File(outputPath);
            writename.createNewFile();
codeLine */
            BufferedWriter out = new BufferedWriter(new FileWriter(writename));
    // note line
        out write(outputBuffer);
/* noteLine
/* noteLine
*/
/* noteLine */
/* noteLine
// noteLine
*/
        out.flush();
        out.close();
}
// noteLine
for(){}/* noteLine */

測試代碼行數、註釋行數、空行數統計

  • test3.c
test()
{
File writename = new File(outputPath);
            writename.createNewFile();
codeLine */
            BufferedWriter out = new BufferedWriter(new FileWriter(writename));
    // note line
        out write(outputBuffer);
/* noteLine
/* noteLine
*/
/* noteLine */
/* noteLine
// noteLine
*/
        out.flush();
        out.close();
} // noteLine
for(){
}/* noteLine */

測試單詞數、行數統計

  • end.txt
for
new
out
  • 測試遞歸查找文件:文件夾test1,其中有一個test3.c文件,選擇-s選項測試便可

-測試命令:
wordcount.exe
wordcount.exe -c test1.c
wordcount.exe -w test3.c
wordcount.exe -l test3.c
wordcount.exe -a test2.c -o testout1.txt
wordcount.exe -s -w test3.c
wordcount.exe -w -e end.txt test2.c
wordcount.exe -a -w -e end.txt test1.c
wordcount.exe -l -w -a -c test2.c -o testout2.txt
wordcount.exe -l -w -a -c -s test3.c -o testout2.txt

參考文獻

  1. http://www.cnblogs.com/xinz/archive/2011/10/22/2220872.html
  2. http://www.ruanyifeng.com/blog/2016/01/commit_message_change_log.html
  3. http://www.cnblogs.com/xinz/archive/2011/11/20/2255830.html
相關文章
相關標籤/搜索