首页 > 其他 > 详细

WorkCount

时间:2018-09-26 21:20:26      阅读:348      评论:0      收藏:0      [点我收藏+]

此项目码云链接

软件测试方法和技术第二次作业

1 作业内容

根据WordCount的需求描述,先编程实现,再编写单元测试,最后撰写博客。至少完成需求中的基本功能。

2 WordCount需求说明

WordCount的需求可以概括为:对程序设计语言源文件统计字符数、单词数、行数,统计结果以指定格式输出到默认文件中,以及其他扩展功能,并能够快速地处理多个文件。

2.1 基础功能

wc.exe -c file.c //返回文件 file.c 的字符数
wc.exe -w file.c //返回文件 file.c 的单词总数
wc.exe -l file.c //返回文件 file.c 的总行数
wc.exe -o outputFile.txt //将结果输出到指定文件outputFile.txt
注意:
空格,水平制表符,换行符,均算字符。
由空格或逗号分割开的都视为单词,且不做单词的有效性校验,例如:thi#,that视为用逗号隔开的2个单词。
-c, -w, -l参数可以共用同一个输入文件,形如:wc.exe –w –c file.c 。
-o 必须与文件名同时使用,且输出文件必须紧跟在-o参数后面,不允许单独使用-o参数。

2.2 扩展功能

wc.exe -s //递归处理目录下符合条件的文件
wc.exe -a file.c //返回更复杂的数据(代码行 / 空行 / 注释行)
wc.exe -e stopList.txt // 停用词表,统计文件单词总数时,不统计该表中的单词
[file_name]: 文件或目录名,可以处理一般通配符。
其中,
代码行:本行包括多于一个字符的代码。
空 行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。
注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:
}//注释
在这种情况下,这一行属于注释行。
-e 必须与停用词文件名同时使用,且停用词文件必须紧跟在-e参数后面,不允许单独使用-e参数。
stopList.txt中停用词可以多于1个,单词之间以空格分割,不区分大小写,形如:
while if switch
则while,if,switch作为3个停用词,在单词统计的时候不予考虑。停用词表仅对单词统计产生影响,不影响字符和行数的统计。

2.3 高级功能

wc.exe -x //该参数单独使用,如果命令行有该参数,则程序会显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、单词数、行数等全部统计信息。

3 解题过程

解题思路

本作业总体而言比较简单,因此采用面向过程方法就可轻松完成

首先是准备的一些变量,后面要用到

    static string fileName;  //操作的文件名
    static string ResultFile = "result.txt";//储存结果的文件,没有-o参数时默认为result.txt
    //用于计数
    static int aChar = 0;
    static int aWord = 0;
    static int aLine = 0;
    static int aCode = 0;
    static int aNote = 0;
    static int aEmpty = 0;

    //用于检测是否有对应参数
    static int fChar = 0;
    static int fWord = 0;
    static int fOutput = 0;
    static int fLine = 0;
    static int fMore = 0;
    static int fRecursion = 0;

我把每个功能都写到一个方法中

首先肯定要对参数输入进行检测

    static bool Check(string[] args)
    {
        int i;
        fileName = args[args.Length - 1];   //如果没有-o参数,则操作文件为最后一个参数
        //对参数进行检查           
        for (i = 0; i < args.Length; i++)
        {
            //检查是否输入了多个参数
            if (args[i] == "-c")
            { fChar++; }
            else if (args[i] == "-w")
            { fWord++; }
            else if (args[i] == "-o")
            { fOutput++; }
            else if (args[i] == "-l")
            { fLine++; }
            else if(args[i] == "-a")
            { fMore++; }
            else if(args[i] == "-s")
            { fRecursion++; }

            if (args[i] == "-o")
            {
                if (args.Length <= 2)
                {
                    Console.WriteLine("错误的命令,若使用-o参数请先在前面使用-c或-w或-i或-l指令");
                    return false;
                }
                fileName = args[i - 1];     //-o参数前一个参数必定为操作文件
                ResultFile = args[i + 1];   //-o参数后一个参数必定为储存文件
            }
        }
        if (fChar > 1 || fWord > 1 || fOutput > 1)
        {   //如果大于一表示输入了至少两个重复参数
            Console.WriteLine("输入的参数不能重复,请修改后再输入");
            return false;
        }

        if (!Regex.IsMatch(fileName, "\\w*\\.(txt|c|docx)"))
        {   //检查操作的文件格式
            Console.WriteLine("Wrong filename,please try again!\nparam:-o,filename:{0}", fileName);
            Console.WriteLine("Allowed FileName:*.(txt|c|docx");
            return false;
        }
        else if (!Regex.IsMatch(ResultFile, "\\w*\\.(txt|c|docx)"))
        {   //检查储存文件格式
            Console.WriteLine("Wrong filename,please try again!\nparam:-o,filename:{0}", ResultFile);
            Console.WriteLine("Allowed FileName:*.(txt|c|docx");
            return false;
        }

        //所有的格式没问题后检查文件是否存在
        if(!File.Exists(fileName))
        {
            if (!Regex.IsMatch(fileName, "\\*\\.(txt|c|docx)"))
            {
                Console.WriteLine("文件不存在!请重新输入");
                return false;
            }
        }
        return true; //一切OK
    }

其次是基础功能

    /// <summary>
    /// 字符计数
    /// </summary>

    static void CharCount()
    {
        StreamReader content = new StreamReader(fileName);
        char[] output = content.ReadToEnd().ToCharArray();  //将字符串流保存到char数组中
        content.Close();
        File.AppendAllText(ResultFile, fileName + ",字符数:" + output.Length.ToString() + "\n");    //保存到result.txt中              
        aChar = output.Length;
    }

基础功能大同小异,思路就是从文件中读取数据流,进行对应处理后计数,然后保存数字。单词和行数同理就不提了

然后是扩展功能,对应算法如下

    /// <summary>
    /// 代码行、空行、注释行计数
    /// </summary>

    static void MoreCount()
    {
        string[] More = File.ReadAllText(fileName).Split(‘\n‘);
        int i = 0;
        char[] chr;
        for(i = 0;i < More.Length;i++)
        {
            chr = More[i].Replace(" ", "").Replace("\t","").ToCharArray();   //去掉空格和制表符
            if(chr.Length > 1)
            {   //字符数大于一,可能是代码行,可能是注释行
                if(chr[0] == ‘}‘ || chr[0] == ‘{‘ && chr[1] == ‘/‘ && chr[2] == ‘/‘)
                {   //去掉空格后如果包括{或}加上//则为注释行
                    aNote++;
                }
                else
                {   //否则是代码行
                    aCode++;
                }
                   
            }
            else
            {   //去掉空行后字符数小于一,则是空行
                aEmpty++;
            }
        }
        string print = string.Format("代码行/空行/注释行:{0}/{1}/{2}\n", aCode, aEmpty, aNote);
        File.AppendAllText(ResultFile, print);
    }

然后是循环处理满足条件的文件

    /// <summary>
    /// 用于递归处理目录下符合条件的文件
    /// </summary>
    static void Recursion()
    {
        List<FileInfo> file = GetAllFilesInDirectory(".\\");  //GetAllFilesInDirectory是自定义方法,返回输入目录及其子目录的所有文件
        string[] suffix = fileName.Split(‘.‘);  //文件后缀
        string pattern = fileName.Replace("*.", "\\w*\\.").Replace(suffix[1], "") + "(" + suffix[1] + ")$";  //利用正则表达式挑选符合条件的文件
        foreach(var f in file)
        {  //循环每个文件
                if (Regex.IsMatch(f.Name, pattern))
            {        //符合条件则全部方法都调用一遍
                fileName = f.Name;
                //根据参数决定该调用哪些方法
                if (fChar > 0)
                    CharCount();    //字符计数
                if (fWord > 0)
                    WordsCount();   //单词计数
                if (fLine > 0)
                    LinesCount();   //行数计数
                if (fMore > 0)
                    MoreCount();    //代码行、空行、注释行计数

                Print();    //将结果输出到屏幕
            }
        }
    }

由于-c -w -l都有在屏幕显示的功能,故我写在一个方法中

    static void Print()
    {
        if (fChar > 0)
            Console.WriteLine(fileName + ",字符数:" + aChar.ToString());
        if(fWord > 0)
            Console.WriteLine(fileName + ",单词数:" + aWord.ToString());
        if(fLine > 0)
            Console.WriteLine(fileName + ",行数:" + aLine.ToString());
        if (fMore > 0)
        {
            string print = string.Format("代码行/空行/注释行:{0}/{1}/{2}", aCode, aEmpty, aNote);
            Console.WriteLine(print);
        }
    }

然后开始时主界面调用方法就行

    static void Main(string[] args)
    {
        //检查参数,此外-o参数在此方法已解决
        if(!Check(args))   
        {
            return;
        }

        //根据参数决定该调用哪些方法
        if (fRecursion > 0)
        {
            Recursion();    //循环
            return;
        }
        if (fChar > 0)
            CharCount();    //字符计数
        if (fWord > 0)
            WordsCount();   //单词计数
        if (fLine > 0)
            LinesCount();   //行数计数
        if (fMore > 0)
            MoreCount();    //代码行、空行、注释行计数

        Print();    //将结果输出到屏幕
    }

测试用例

文件:

目录文件:

运行结果

WorkCount

原文:https://www.cnblogs.com/damocleses/p/9709560.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!