一、项目简介

       源码地址:https://gitee.com/Juice-Dreamer/WordCount.git

       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

           wc.exe -s            //递归处理目录下符合条件的文件

           wc.exe -a file.c     //返回更复杂的数据(代码行 / 空行 / 注释行)

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

         2.开发环境:vs2017+c#实现

         3.思路分析: 从基本功能可以看出这个程序是对文件进行操作,统计一些重要的数据,以及对结果进行处理。扩展功能是对一些高级数据统计,以及快速处理等功能。c#中主要用到的类有FileStream、StreamWriter、StreamReader三个来对文件进行操作,利用这三个类很容易对文件进程操作。我自己在设计时由于没有注重代码可维护性,因此代码很乱,将会在后续慢慢更正。

二、项目实现

       1.设计整个项目设计了一个大类WC,其中的字段和方法如下所示:
                               

  private List<string> inputPara = null;  //输入参数
  private int charCount=0;//需要统计的字符数
  private int wordCount = 0;//需要统计的单词数
  private int lineCount = 0;//需要统计的总行数
  private string inputFile="";//需要处理的文件
  private int codeCount = 0;//代码行数
  private int emptyCount = 0;//空行
  private int noteCount = 0;//注释行          

public void analyzeInput(List<string>lstInput)//解析输入,对用户输入的结果进行解析
public void FunBaseCount()//统计基本功能结果
public int WordCount()//统计单词数,因单词数要求很多,拿出来专门作为一个函数进行处理
public void FunSeniorCount()//统计高级数据:空行、代码行、注释行
public void ResultToFile(string file)//将结果输入到指定文件中 输出到默认文件中result.txt
public void DisplayAllResult(string file)//统计所有信息到file中

 

        2.实现:       

             Main函数为程序的入口,进行与用户交互。

 [STAThread]
        static void Main(string[] args)
        {
            //程序入口处
            try
            {
                Console.WriteLine("请输入您对程序的操作,若需多项操作,请用空格隔开!,操作末尾默认是需要操作的文件");
                string inputMessage = "";
                while (inputMessage != "exit")
                {
                    Console.Write("wc.exe ");
                    inputMessage = Console.ReadLine();
                    inputMessage = inputMessage.Trim(' ');//去掉前后空格
                    inputMessage = inputMessage.Trim('\t');
                    if (inputMessage != "-x")
                    {
                        string[] input = inputMessage.Split(' ');
                        List<string> inputPara = new List<string>();
                        for (int i = 0; i < input.Length; i++)
                        {
                            if (input[i] != "")
                            {
                                inputPara.Add(input[i]);
                            }

                        }
                        inputPara = inputPara.Distinct().ToList();//去重复命令
                        WC wc = new WC();
                        wc.analyzeInput(inputPara);
                         
                    }
                    else 
                    {
                         
                        List<string> inputPara = new List<string>();
                        inputPara.Add("-x");
                        inputPara.Add("");
                        
                        WC wc = new WC();
                        wc.analyzeInput(inputPara);
                        
                    }


                }
            }
            catch (Exception e)
            {
                Console.WriteLine("程序遇到错误:"+e.Message);
            }
        }

            analyzeInput()主要是对用户输入进行分析来做出判断。

 

 public void analyzeInput(List<string>lstInput)//解析输入,对用户输入的结果进行解析
        {
            this.inputPara = lstInput;//获取参数
            inputFile = inputPara[inputPara.Count - 1]; //获取文件
            for (int i = 0; i < inputPara.Count - 1;i++ )
            {
                if (inputPara[i] == "-x")//图形化处理
                {
                    try
                    {
                        
                        OpenFileDialog ofd = new OpenFileDialog();
                        ofd.InitialDirectory = Application.StartupPath;
                        ofd.Filter = ".c files(*.c)|*.c";
                        ofd.FilterIndex = 2;
                        ofd.RestoreDirectory = true;
                        if (ofd.ShowDialog() == DialogResult.OK)
                        {
                            this.inputFile = ofd.FileName;
                            FunBaseCount();
                            FunSeniorCount();
                            DisplayAllResult("result.txt");
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }
                else if (inputPara[i] == "-c" || inputPara[i] == "-l" || inputPara[i] == "-w")//统计基本功能
                {
                    FunBaseCount();
                    if (!inputPara.Contains("-o"))
                    {
                        ResultToFile("result.txt");
                    }
                    if (inputPara[i + 1] == "-o")//输出结果到指定文件夹中
                    {
                        ResultToFile(inputPara[i + 2]);
                    }
                }
                else if (inputPara[i] == "-a")//统计高级功能并输入到指定文件夹中
                {

                    FunSeniorCount();
                    if (!inputPara.Contains("-o"))
                    {
                        ResultToFile("result.txt");
                    }
                }
                else if (inputPara[i] == "-s")//遍历当前目录文件夹以及子文件,满足.c文件都可以统计
                {
                    try
                    {
                       
                        //  获取符合条件的文件名
                        string[] files = Directory.GetFiles(@"..\Debug", "*.c",SearchOption.AllDirectories);
                       
                        foreach (string file in files)
                        {
                            
                           // Console.WriteLine(Application.StartupPath + file.Substring(8));
                            this.inputFile = Application.StartupPath + file.Substring(8);
                            FunBaseCount();
                            FunSeniorCount();
                            DisplayAllResult("result.txt");
 
                        }
                        break;
                    }
                    catch (IOException ex)
                    {
                         Console.WriteLine(ex.Message);
   
                    }

                }
  else
                {
                    Console.Write(inputPara[i] + "不是正确的命令,请重新输入!");
                }
} }

            FunBaseCount()统计基本结果。

         

 public void FunBaseCount()//统计基本功能结果
        {
           // Console.Write(inputFile);
            FileStream fs = new FileStream(inputFile, FileMode.Open,FileAccess.Read);//读取文件
            StreamReader sr = new StreamReader(fs);
            int iChar;
              
            int charCount = 0;
            int lineCount = 0;
             
            while ((iChar = sr.Read()) !=-1)
            {
                if (iChar != '\n')
                {
                    charCount++;//字符数
                   // Console.WriteLine((char)iChar);
                }
                
                if (iChar == '\n')
                {
                    lineCount++;//行数
                     
                }        
            }
            this.charCount = charCount;
            this.lineCount = lineCount+1;
            this.wordCount = WordCount();
            fs.Close();
            sr.Close();
        }

 

 public int WordCount()//统计单词数
        {
            FileStream fs = new FileStream(inputFile, FileMode.Open, FileAccess.Read);
            StreamReader sr = new StreamReader(fs);
            string readLine = "";
            int count = 0;
            while ((readLine = sr.ReadLine()) != null)//逐行读取
            {
                if (readLine.Trim(' ').Contains(' ')||readLine.Trim(' ').Contains(','))//对含有多个空格等进行分割
                {
                    string[] words = readLine.Trim(' ').Split(",' '".ToCharArray());

                    foreach (string i in words)
                    {
                        if (i.Length != 0) count++;
                    }
                       // Console.WriteLine(i+" len:"+i.Length);
                }
                else 
                {
                  //  Console.WriteLine("No:" + readLine);
                   count++;
                }
                
            }
            sr.Close();
            fs.Close();
            return count;
        }

            FunseniorCount()统计高级计数结果。

 

 public void FunSeniorCount()//统计高级数据:空行、代码行、注释行
        {
            FileStream fs = new FileStream(inputFile, FileMode.Open, FileAccess.Read);
            StreamReader sr = new StreamReader(fs);
            string readLine;
            while ((readLine = sr.ReadLine()) != null)//逐行读取
            {
                if (readLine.Trim(' ').Length == 0 || readLine.Trim(' ') == "{" || readLine.Trim(' ') == "}")//空行
                {
                    this.emptyCount++;
                }
                else  if (readLine.Trim(' ').Length > 1)//代码行
                {
                    this.codeCount++;
                }
                else   if ((readLine.Contains("{") || readLine.Contains("}")) && (readLine.Contains("//")))//注释行
                {
                    this.noteCount++;
                }

            }
            fs.Close();
            sr.Close();
           
        }

            ResultToFile()是把统计信息写入指定文件

 

public void ResultToFile(string file)//将结果输入到指定文件中 输出到默认文件中result.txt
        {
            try
            {
                FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write);
                StreamWriter sw = new StreamWriter(fs);
                string resultStr = "";
                foreach (string s in inputPara)//根据参数输入来决定文件中写什么内容
                {
                    if (s == "-c") resultStr = resultStr + inputFile + ",字符数:" + charCount.ToString() + "\r\n";
                    else if (s == "-l") resultStr = resultStr + inputFile + ",行数:" + lineCount.ToString() + "\r\n";
                    else if (s == "-w") resultStr = resultStr + inputFile + ",单词数:" + wordCount.ToString() + "\r\n";
                    else if (s == "-a")
                    {
                        resultStr = resultStr+inputFile + ",代码行:" + codeCount.ToString() + "\r\n";
                        resultStr = resultStr +inputFile+ ",空行:" + emptyCount.ToString() + "\r\n";
                        resultStr = resultStr+inputFile + ",注释行:" + noteCount.ToString() + "\r\n";
                    }
                }
                sw.Write(resultStr);
                sw.Close();
                fs.Close();
            }
            catch (IOException e)
            {
                Console.WriteLine("结果写入遇到错误:" + e.Message);
            }
        }

            DisplayAllResult()显示所有统计信息到指定文件中

    

public void DisplayAllResult(string file)//统计所有信息到file中
        {
            try
            {
                FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write);
                StreamWriter sw = new StreamWriter(fs);
                string resultStr = "";
                resultStr = resultStr + inputFile + ",字符数:" + charCount.ToString() + "\r\n";
                resultStr = resultStr + inputFile + ",行数:" + lineCount.ToString() + "\r\n";
                resultStr = resultStr + inputFile + ",单词数:" + wordCount.ToString() + "\r\n";
                resultStr = resultStr + inputFile + ",代码行/空行/注释行:" + codeCount.ToString()+"/"+ emptyCount.ToString()+"/"+ noteCount.ToString() + "\r\n";
                sw.Write(resultStr);
                sw.Close();
                fs.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine("发生错误:"+e.Message);
            }
        }

         3.测试:

             3.1采用白盒测试,对输入进行测试如下图:

             test.c内容:

        

             测试-c:

   

             测试-l:

    

             测试-w:

    

             测试-c -l:

        

             测试-c -w:

        

             测试-c -w -l:

       

             错误输入:

       

             测试-s:

             

 

             测试-x:

       

      

             测试-o:

 

             3.2单元测试:

                  创建单元测试

               

using WordCount;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;

namespace TestProject2
{
    
    
    /// <summary>
    ///这是 WCTest 的测试类,旨在
    ///包含所有 WCTest 单元测试
    ///</summary>
    [TestClass()]
    public class WCTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///获取或设置测试上下文,上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试特性
        // 
        //编写测试时,还可使用以下特性:
        //
        //使用 ClassInitialize 在运行类中的第一个测试前先运行代码
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //使用 ClassCleanup 在运行完类中的所有测试后再运行代码
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //使用 TestInitialize 在运行每个测试前先运行代码
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //使用 TestCleanup 在运行完每个测试后运行代码
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///WordCount 的测试
        ///</summary>
        [TestMethod()]
        public void WordCountTest()
        {
            WC target = new WC(); // TODO: 初始化为适当的值
            int expected = 10; // TODO: 初始化为适当的值
            int actual;
            actual = target.WordCount();
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("验证此测试方法的正确性。");
        }

        /// <summary>
        ///WC 构造函数 的测试
        ///</summary>
        [TestMethod()]
        public void WCConstructorTest()
        {
            WC target = new WC();
            Assert.Inconclusive("TODO: 实现用来验证目标的代码");
        }

        /// <summary>
        ///DisplayAllResult 的测试
        ///</summary>
        [TestMethod()]
        public void DisplayAllResultTest()
        {
            WC target = new WC(); // TODO: 初始化为适当的值
            string file = string.Empty; // TODO: 初始化为适当的值
            target.DisplayAllResult(file);
            Assert.Inconclusive("无法验证不返回值的方法。");
        }

        /// <summary>
        ///FunBaseCount 的测试
        ///</summary>
        [TestMethod()]
        public void FunBaseCountTest()
        {
            WC target = new WC(); // TODO: 初始化为适当的值
            target.FunBaseCount();
            Assert.Inconclusive("无法验证不返回值的方法。");
        }

        /// <summary>
        ///FunSeniorCount 的测试
        ///</summary>
        [TestMethod()]
        public void FunSeniorCountTest()
        {
            WC target = new WC(); // TODO: 初始化为适当的值
            target.FunSeniorCount();
            Assert.Inconclusive("无法验证不返回值的方法。");
        }

        /// <summary>
        ///ResultToFile 的测试
        ///</summary>
        [TestMethod()]
        public void ResultToFileTest()
        {
            WC target = new WC(); // TODO: 初始化为适当的值
            string file = string.Empty; // TODO: 初始化为适当的值
            target.ResultToFile(file);
            Assert.Inconclusive("无法验证不返回值的方法。");
        }

        /// <summary>
        ///analyzeInput 的测试
        ///</summary>
        [TestMethod()]
        public void analyzeInputTest()
        {
            WC target = new WC(); // TODO: 初始化为适当的值
            List<string> lstInput = null; // TODO: 初始化为适当的值
            target.analyzeInput(lstInput);
            Assert.Inconclusive("无法验证不返回值的方法。");
        }

        /// <summary>
        ///WordCount 的测试
        ///</summary>
        [TestMethod()]
        public void WordCountTest1()
        {
            WC target = new WC(); // TODO: 初始化为适当的值
            int expected = 0; // TODO: 初始化为适当的值
            int actual;
            actual = target.WordCount();
            Assert.AreEqual(expected, actual);
            Assert.Inconclusive("验证此测试方法的正确性。");
        }
    }
}

                 测试结果:

        

             3.3静态代码检查:工具是StyleCode 

              

                          注:项目中也存在一些问题,这里就不一一列举,会再进行重新设计,争取完成一个更好的版本。

 、项目总结

         1.总结:

           本次实验是对文件进行数据统计的一个小项目。在编程中发现,如果没有理解需求是根本很难完成代码编写的;其次,如果不进行结构设计,也很难完成。因此我自己会再对这个项目进行优化,重新设计结构,争取形成一个稳定运行的版本。

         从这次小项目中,可以看出来自己存在的很多严重的不足,往后还需更加注重代码维护性与代码设计方面,争取能够对代码进行优化,让自己有所收获。

            2.致谢:

           本作业中内容参考和借鉴华中科技大学wujianjie老师发布的作业https://www.cnblogs.com/ningjing-zhiyuan/p/8654132.html在此表示感谢。 

                                

 

posted on 2018-10-21 11:20  Juice-Dreamer  阅读(199)  评论(0编辑  收藏  举报