一位同学碰到的问题,详细的题目不清楚大概的要点也就是考点如下:
1、要求从txt文件中读取,是对IO的考验;
2、对Int32的理解,要求知道大概的大小;
3、对操作大数字方案的解决 ;
前两者没什么问题,在IO的时候注意编码方式就好,不过因为是电话号码,一般都为数字所以都无所谓。当然这里没有考虑‘#’等特殊字符。
比较难的是第三点,也是比较经典的问题,一般情况下用长整形就可以解决,整整64位大小的数存储20位以下的整形不是问题。但是万一这个数大小更大呢,所以比较好的方案就是能够处理竟可能大的数字,还要考虑到效率。下面我的方案是以Int32作为单元以Int32数组作为存储数的数据结构,这样就避开了数据大小的问题,如果有更好的方案希望你告诉我。下面用了很多C#中的集合函数,还有一些C、C++中没有的东西,所以用这两种语言就要稍微麻烦点。
稍微解释下(非C#程序员)
List<T>:简单说就是一个可操作集合,T指可以替换任何类型,所以List<int[]>就是一个int[]的可变集合。
foreach:就是遍历当前集合的所有元素。
如果有啥问题请留言。
结果图:
代码如下:
Code
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace phoneNumberAnlyse
{
class Program
{
const string path = "number.txt";
const int numberCount = 100;//假设生成100个测试数据
const int Maxlength = 20;//不多于20位数
const int MinLength = 8;//电话号码不少于8位数
const int unitMax = 9;//10的10次方,int32最大大约是20多亿
static int repeatMax = 30;
static void Main(string[] args)
{
#region 创建测试数据
File.Delete(path);
if (!File.Exists(path))
{
using (FileStream fs = File.Create(path))
{
TextWriter streamWriter = new StreamWriter(fs);
int i = numberCount;
Random rand = new Random();//随机长度
string num = string.Empty;
while (i-- > 0)
{
int l = rand.Next(MinLength, Maxlength);
if (num != string.Empty && rand.Next(0, 2) == 1&&repeatMax-->0)
{
streamWriter.WriteLine(num);
continue;
}
num= string.Empty;//用string作为电话号码的存储介质,不用担心大小限制,C里也一样
for (int j = l / unitMax + 1; j > 0; j--)
{
int u = rand.Next();
string uStr = u.ToString("000000000");
if (j == 1) uStr = uStr.Substring(0, l % unitMax);//当数字个数少于9个时切去多余部分
num += uStr;
}
streamWriter.WriteLine(num);
}
}
}
#endregion
string[] nums;
#region 读取数据
//读取并展示已经存储的数据
using (StreamReader reader = new StreamReader(path))
{
List<string> strs = new List<string>();
while (!reader.EndOfStream)
{
strs.Add(reader.ReadLine());
}
nums = strs.ToArray();
Console.WriteLine("Oregion Numbers Readed!");
//foreach (string str in nums)
// Console.WriteLine("Number:{0}", str);
}
#endregion
#region 测试数据
//将字符串转化为对应的数字数组
List<int[]> numberList = new List<int[]>();
foreach (string str in nums)
numberList.Add(ToNumArry(str));
//显示存储的数据
//foreach (int[] ints in numberList)
//{
// foreach (int i in ints)
// Console.Write("{0}\t", i);
// Console.WriteLine();
//}
//方法1 简单但是屏蔽了对比的过程
//Dictionary<int[], int> result = new Dictionary<int[], int>();
//foreach (int[] number in numberList)
//{
// if(!result .ContainsKey (number ))result .Add (number ,0);
// result [number]++;
//}
//方法2
List<int[]> resultList=new List<int[]> ();
foreach (int[] number in numberList )
{
bool isExist=false;
foreach (int[] n in resultList )
if(Compare (n,number )) { isExist =true;break;}
if(!isExist)
{
resultList .Add (number );
int count=0;
foreach (int[] n in numberList )
if(Compare (n,number))count ++;
string outS=string.Empty ;
foreach (int i in number )outS+=i.ToString ();
Console .WriteLine ("Number:{0}\tTimes:{1}",outS,count);
}
}
#endregion
}
static int[] ToNumArry(string str)
{
List<int> nums = new List<int>();
while (str.IndexOf('0') == 0) str = str.Substring(1);//去掉每个数前的0
while (str.Length > 0)
{
string temp = str.Substring(0, str.Length > unitMax ? unitMax : str.Length);
nums.Add(int.Parse(temp));
str = str.Replace(temp, string.Empty);
}
return nums.ToArray();
}
static bool Compare(int[]i1,int[]i2)
{
if (i1.Length != i2.Length) return false;
for (int i = 0; i < i1.Length; i++)
{
if (i1[i] != i2[i]) return false;
}
return true;
}
}
}