一、前言:
字数统计,一直是个老大难问题!(主要是统计的精度。)
本人是名新手,经过多天的研究,已经完美解决此问题。(中英文输入状态下)
编程学习过程,借鉴了多人的经验。
现,将自己的经验分享,希望对你有所帮助!
二、编程思维与逻缉:
1.本人的信仰:“大道至简,任何事情,都有最简单的解决办法!”
自然编程也不例外!
2.编程逻缉:
先介绍下Word与WPS的字数统计逻缉:
首先:两个软件以【空格】为分隔,进行字数的计数。
其次:中文是直接进行计数;英文、数字等其它符号,则是以【空格】或【中文字符】为分隔后,再进行计数。
第三:【……】【——】这两个符号,比较特殊些,两个软件有些不同!这两个符号,WPS,是以“二”为单位进行计数;Word,则是【……】符号,以“二”为单位进行计数,【——】符号,不进行计数。
总上所述:影响字数统计的因素,也就是英文、数字等其它符号和第三条。
【补充说明】:在文件转换或复制粘贴文本到【Word】【WPS】中时,中文符号引号【“ ”】、逗号【,】、句号【。】、省略号【……】,在受到字体太小影响时,极容易出现转换错误的情况,进而导致两个软件统计出错。
整理编程的逻缉:
1.将影响字数统计精度的因素,看成三个因素:
一:空格
二:可计算字符(主要指:中文字符---键盘上能够输出的字符)。
三:非可计算字符(主要指:英文、数字等其它符号--键盘上能够输出的字符)。
2.以数组为主,进行编程(目的:逻辑上简单!)
三、整体代码:
using System.Collections;
using System.Text.RegularExpressions;
#region 字数统计
Char[] stat = richTextBox1.Text.ToArray();//字节数组
int[] thre = new int[stat.Length];//空的三元数组,用于存放三元元素。
Regex reg = new Regex(@"^[\u4e00-\u9fa5]$");//【中文汉字】正则表达式
//【可计算中文符号】数组。
string[] strC1 = { ",", "。", "、", ";", "‘", "!", "(", ")", "【", "】", "《", "》", "?", ":", "“", "”", "·" };
string[] strC2 = { "…", "—" };//【Word】中“——”不计数量;【WPS】中“——”统计数量!
ArrayList listC = new ArrayList(strC1);//使用声明的数组“strC1”,实例化一个“ArrayList”对象
ArrayList listC2 = new ArrayList(strC2);//使用声明的数组“strC2”,实例化一个“ArrayList”对象
for (int t = 0; t < thre.Length; t++)//将字节数组,转化为三元数组
{
if (Char.IsWhiteSpace(stat[t]) == true)
{//将字节数组中的“空格”,转化为【0】,并存入三元数组
thre[t] = 0;
}
else if (reg.IsMatch(stat[t].ToString()) == true | listC.Contains(stat[t].ToString()) == true | listC2.Contains(stat[t].ToString()) == true)
{//将字节数组中的“中文字符”,转化为【1】,并存入三元数组
thre[t] = 1;
}
else
{//将字节数组中的“其它字符”(英文、数字等键盘上可输入字符),转化为【2】,并存入三元数组
thre[t] = 2;
}
}
int w = 0;//统计空格数量(无扩展功能时,此项可省略)。
int n = 0;//统计“中文字符”【可计算】的数量。
int ot = 0;//统计“其它字符”【可统计】数量。
foreach(int m in thre)//遍历三元数组,对每种元素数量,进行统计
switch (m)
{
case 0:
w++;//(无扩展功能时,此项可省略)
break;
case 1:
n++;
break;
case 2:
ot++;
break;
default:
break;
}
//int pw1 = Array.IndexOf(thre, 0);//第一个空格位置
//int pw2 = Array.LastIndexOf(thre, 0);//最后一个空格位置
//【重要代码】
int[] pot = new int[ot];//“其它元素”位置索引数组
int pt = 0;//位置信息数组索引
for (int q = 0; q < thre.Length; q++)//遍历“其它字符”【可统计】数组,获取其索引
{
if (thre[q] == 2)
{
pot[pt] = q;//将三元数组中,“其它元素”位置索引,写入到索引数组中
pt++;
}
}
/*
foreach (int r in pot)
Console.WriteLine(r + " ");*/
//【重要代码】
int cot = 0;//其它元素的“可计算字符”【Word 中可以被计算】的数量。
for(int c = 0; c < pot.Length - 1; c++)
{//将存储在位置信息数组中,【其它可计算字符】值(上步骤中三元数组中的索引),前后元素对比。
if (pot[c + 1] - pot[c] == 1)//前后元素值差为【一】时:
{
continue;//跳过此次循环。
}
else//前后元素值差不为【一】时:
{
cot++;//其它元素的“可计算字符”【Word 中可以被计算】数量+1.
}
}
if (ot > 0)//当三元数组中,其它字符”【可统计】的数量大于1时:
{
label8.Text = (cot + 1 + n).ToString();//总的字数数量。
label6.Text = label8.Text;
label2.Text = w.ToString();
label4.Text = stat.Length.ToString();
}
else//当三元数组中,其它字符”【可统计】的数量小于1时:
{
label8.Text = (cot + n).ToString();//总的字数数量。
label6.Text = label8.Text;
label2.Text = w.ToString();
label4.Text = stat.Length.ToString();
}
#endregion
四、代码过程解释:
1.将richTextBox1 中的文本,转化为字节数组(万国码Char数组),便于后续的引用。
2.空的三元数组(一维),存储三种元素(影响统计精度的三个因素)。
【0】代表:空格
【1】代表:可计算字符(主要指:中文字符---键盘上能够输出的字符)。
【2】代表:非可计算字符(主要指:英文、数字等其它符号--键盘上能够输出的字符)。