个人项目——wc源程序特征统计

时间:2021-10-09 23:24:47

这一次要做的项目是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);
}


}


}

要读的文件

个人项目——wc源程序特征统计

运行结果如下

个人项目——wc源程序特征统计

扩展功能:

由于在基本功能中,没有考虑行的细分,必须要在扩展功能中考虑。在基本功能的基础上,信息又要再加上空行、代码行、注释行。

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
++;

}

读取的文件如下

个人项目——wc源程序特征统计

测试结果如下:

个人项目——wc源程序特征统计

高级功能:

要想实现这个能够显示图形界面,就要添加新项——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)
{

}
}


}

运行结果如下:个人项目——wc源程序特征统计

选择后点击打开

个人项目——wc源程序特征统计

输入的实现:

在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,打开窗体选择文件后总会弹出一个空白窗体(不将窗体关掉,,后续的显示文件信息无法进行),,情况入下:个人项目——wc源程序特征统计

在进一步的学习c#中终于找到原因,,窗体被创建后,显示前会执行Load事件,,在该事件中可以对一些控件进行赋初值,,来在显示时将控件的初值显示出来,,如果不想让窗体显示,不需要在窗体上做任何操作,直接结束(这种情况很少),就在Load事件里直接将其关闭即this.Close();解决代码如下

        private void Form1_Load(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
filename
= openFileDialog1.FileName;//获取文件名
this.Close();

}


}

这样就不会有空白窗体出现,而直接进行后续的运行。。。。。