个人项目——wc源程序特征统计
这一次要做的项目是wc——统计程序文件特征的命令行程序。
根据需求需求得到的模式为:wc.exe [parameter][filename]
在[parameter]中,用户通过输入参数与程序交互,需实现的功能如下:
1、基本功能
- 支持 -c 统计文件字符数
- 支持 -w 统计文件单词数
- 支持 -l 统计文件总行数
2、拓展功能
- 支持 -a 返回高级选项(代码行 空行 注释行)
- 支持 -s 递归处理符合条件的文件
3、高级功能
- 支持 -x 程序以图形界面与用户交互
[filename] 是待处理文件名。
最近在学习c#故而用c#实现本程序。
基本功能的实现:
为实现程序能够实现-c、-l、-w对应的功能,我在新建的解决方案下又添加了一个count类,在这个类中有一个文件的基本信息:字符数、单词数、行数。这些信息都保存在字段中(c#中有get、set方法的才叫属性),之后根据快捷键ctr+r+e生成各种对应的属性;
之后就是关于信息的获取,
1、建立void infile(sFilename)方法,来进入文件,循环读取文件每一行的内容,内容保存字符串str中,之后将读取的每一行的内容以参数的形式进入,统计文件一行信息的方法void perLineWord(str);
2、建立void perLineWord(str)方法,根据读取的文件的一行信息进行统计;先用循环将传进来的str中开头的空格遍历出去,空格数对应的加1,一旦读到的不是空格跳出循环,判断是不是字母,如果是字母就进入字母、数字、下划线的循环中,如果都不是就跳出循环,之后单词数加1;再判断导致循环结束的是不是空格,若是空格数加1;一直将str字符串读完,结束。代码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Diagnostics; namespace count_wc { class Count { int konggenum ;//空格及制表符 int charnum;//字符数 = 总个数—空格、制表符数 int wordsnum; int lines; string sFilename; public string SFilename { get { return sFilename; } set { sFilename = value; } } //属性 public int Konggenum { get { return konggenum; } set { konggenum = value; } } public int Charnum { get { return charnum; } set { charnum = value; } } public int Wordsnum { get { return wordsnum; } set { wordsnum = value; } } public int Lines { get { return lines; } set { lines = value; } } public Count() { konggenum = 0; charnum = 0; wordsnum = 0; lines = 0; } /// <summary> /// 进入文件 /// </summary> /// <param name="sFilename"></param> public void infile(string sFilename) { this.sFilename = sFilename; int length = 0;//总长度 // count.RunCmd(@"C:\WINDOWS\system32\cmd.exe ","aa"); try { // FileStream file = new FileStream(sFilename, FileMode.Open, FileAccess.Read, FileShare.Read); StreamReader sr = new StreamReader(sFilename, Encoding.Default); string str; while ((str = sr.ReadLine()) != null) { lines++; perLineWord(str); // perLineWord(str); } sr.Close(); } catch { Console.WriteLine("无此文件"); } charnum = length - konggenum; codeline = lines - nullline - noteline; } /// <summary> /// 文件中一行的情况 /// </summary> /// <param name="str"></param> public void perLineWord(string str) { // int tempkongge = 0; // int tempwords = 0; int i = 0;
StreamReader sr = new StreamReader(sFilename, Encoding.Default); while (str[i] == ' ' || str[i] == '\t')//去开头空格 { konggenum++; // tempkongge++; i++; if (i == str.Length) break; } while (i < str.Length) { //单词是以字母开头,字母、数字、_、组合的 if (('a' <= str[i] && str[i] <= 'z') || ('A' <= str[i] && str[i] <= 'Z')) { i++; while (('a' <= str[i] && str[i] <= 'z') || ('A' <= str[i] && str[i] <= 'Z') || ('0' <= str[i] && str[i] <= '9') || str[i] == '_') { i++; if (i == str.Length) break; } wordsnum++; // tempwords++; } else if (str[i] == ' ' || str[i] == '\t') { konggenum++; // tempkongge++; i++; } else i++; } // Console.WriteLine("字符数{0},,,{1}", i - tempkongge, tempwords); } } }
要读的文件
运行结果如下
扩展功能:
由于在基本功能中,没有考虑行的细分,必须要在扩展功能中考虑。在基本功能的基础上,信息又要再加上空行、代码行、注释行。
1、在void infile(sFilename)方法中进入void perLineWord(str)之前要判断读到的内容是否为空,若为空,空行加1,直接读下一行,若不为空,才进入 perLineWord(str)函数;
添加的代码如下:
if (str == "") { nullline++; } else { perLineWord(str); }
2、在void perLineWord(str)中,一开始就要先将用一变量保存str中的前后空格去掉后的情况,若只有“{”、“}”或“”就将空行数加1,若是“}//”就讲注释行加1。之后的和基本功能的内容一样。
添加的代码如下:
string temstr = str.TrimStart();//去除前后空格 if(temstr =="{"||temstr =="}"||temstr =="") { nullline++; } else if(temstr =="}//") { noteline++; }
读取的文件如下
测试结果如下:
高级功能:
要想实现这个能够显示图形界面,就要添加新项——windows窗体。
新建好后,在vs窗口中生成一个窗体,在工具对话框里拖拽一个openFileDialog控件。然后点击窗体查看代码,增加一个filename字段和属性(用于保存选择的文件名),在Form1的构造函数里,增加当一个点击打开按钮后将获取的文件名给新增的filename字段。
代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace count_wc { public partial class Form1 : Form { string filename;//保存选择的文件名 public string Filename { get { return filename; } set { filename = value; } } public Form1() { InitializeComponent(); if(openFileDialog1.ShowDialog()==DialogResult.OK) { filename = openFileDialog1.FileName;//获取文件名 } } private void Form1_Load(object sender, EventArgs e) { } } }
运行结果如下:
选择后点击打开
输入的实现:
在program类中main方法中将获取用户输入的信息保存在wininf中,当wininf==“-x”是就创建窗体,自然就能将文件对话框显示出来。再选择打开后总会有一个空白窗体显示出来,这个算一个不小的弊端了,由于时间紧急,现在还未处理好......(需注意的是main函数的上面必须要有“[STAThread]”,否则当命令是-x时程序就会出错)
之后就是要将输入信息拆分成命令信息和文件信息,再接着就是用一个方法public static void showResult(string sFilename,params object[] commond)来显示结果;
具体代码如下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Windows.Forms; namespace count_wc { class Program { [STAThread]//没有它程序运行到-x条件时会出错 static void Main(string[] args) { string wininf = ""; // 存储用户命令 while (wininf != "exit") { string sFilename; Console.Write("WC.exe "); wininf = Console.ReadLine(); // 得到输入命令 if (wininf == "-x") { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Form1 frm = new Form1(); Application.Run(frm); sFilename = frm.Filename; string[] commond = new string[3]; commond[0] = "-l"; commond[1] = "-c"; commond[2] = "-w"; showResult(sFilename, commond); } else { string[] arrwininf = wininf.Split(' '); // 分割命令 int infLength = arrwininf.Length; string[] commod = new string[infLength - 1]; // 获取命令参数数组 for (int i = 0; i < infLength - 1; i++) { commod[i] = arrwininf[i]; } // 获取文件名 sFilename = arrwininf[infLength - 1]; showResult(sFilename, commod); } Console.ReadKey(); } } public static void showResult(string sFilename,params object[] commond) { Count c1 = new Count(); c1.infile(sFilename); int len = commond.Length; for (int i = 0; i < len; i++) { string com = (string)commond[i]; switch (com) { case "-c": { Console.WriteLine("字符数:{0} ", c1.Charnum); break; } case "-w": { Console.WriteLine("单词数:{0} ", c1.Wordsnum); break; } case "-l": { Console.WriteLine("行数:{0} ", c1.Lines); break; } case "-a": { Console.WriteLine("代码行:{0} 空行:{1} 注释行:{2}", c1.Codeline, c1.Nullline, c1.Noteline); break; } case "-x": { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); break; } default: Console.WriteLine("字符数:{0} 单词数:{1} 行数:{2}", c1.Charnum, c1.Wordsnum, c1.Lines); break; } } } } }
学习c#ing,,不喜勿怪....... 全代码见https://coding.net/u/zht01/p/WC_c/git
更进:::
在上面提到的输入-x,打开窗体选择文件后总会弹出一个空白窗体(不将窗体关掉,,后续的显示文件信息无法进行),,情况入下:
在进一步的学习c#中终于找到原因,,窗体被创建后,显示前会执行Load事件,,在该事件中可以对一些控件进行赋初值,,来在显示时将控件的初值显示出来,,如果不想让窗体显示,不需要在窗体上做任何操作,直接结束(这种情况很少),就在Load事件里直接将其关闭即this.Close();解决代码如下
private void Form1_Load(object sender, EventArgs e) { if (openFileDialog1.ShowDialog() == DialogResult.OK) { filename = openFileDialog1.FileName;//获取文件名 this.Close(); } }
这样就不会有空白窗体出现,而直接进行后续的运行。。。。。