using System;
using System.Collections;
using System.Collections.Generic;
namespace StructScript
{
public sealed class StringScript : IEnumerable<char>, IEnumerable, IEquatable<StringScript>
{
private int mLength = 0;
private char[] mItems;
private static readonly char[] mEmptyArr = new char[0];
public static readonly StringScript Empty = new StringScript(mEmptyArr);
public StringScript(char[] value)
{
if (value != null)
{
int length = value.Length;
if (length == 0)
{
mItems = mEmptyArr;
}
else
{
mItems = new char[length];
for (int i = 0; i < length; i++)
{
mItems[i] = value[i];
}
mLength = length;
}
}
}
public char this[int index]
{
get
{
if (index >= mLength || index < 0)
{
throw new IndexOutOfRangeException();
}
return mItems[index];
}
set
{
if (index >= mLength || index < 0)
{
throw new IndexOutOfRangeException();
}
mItems[index] = value;
}
}
public int Length
{
get
{
return mLength;
}
}
public bool Equals(StringScript other)
{
if (this == null)
{
throw new ArgumentNullException();
}
if (other == null)
{
return false;
}
if (this.Length != other.Length)
{
return false;
}
if (Equals(this, other))
{
return true;
}
return false;
}
public static bool Equals(StringScript strA, StringScript strB)
{
int length = strA.Length;
bool isEqual = true;
for (int i = 0; i < length; i++)
{
if (strA[i] != strB[i])
{
isEqual = false;
}
}
if (isEqual)
{
return true;
}
return false;
}
public bool Contains(StringScript value)
{
int index;
return Contain(value, out index);
}
private bool Contain(StringScript value, out int index, int startIndex = 0)
{
index = 0;
if (value == null)
{
throw new ArgumentNullException();
}
int length = value.Length;
// mLength - length - startIndex比较的次数
for (int i = startIndex; i < mLength - length - startIndex; i++)
{
bool isEqual = true;
// 从索引0开始,遍历长度value.Length的数据,查找匹配的字符
for (int j = i; j < length + i; j++)
{
// j - i 保持需要比较的字符串的索引从0开始
if (mItems[j] != value[j - i])
{
isEqual = false;
}
}
if (isEqual)
{
index = i;
return true;
}
else
{
continue;
}
}
return false;
}
public StringScript Replace(StringScript oldValue, StringScript newValue)
{
if (oldValue == null)
{
throw new ArgumentNullException();
}
if(oldValue.Length > mLength)
{
return this;
}
char[] dataSource = new char[mLength];
char[] dataOld = new char[oldValue.Length];
char[] dataNew = new char[newValue.Length];
for (int i = 0; i < mLength; i++)
{
dataSource[i] = mItems[i];
}
for (int i = 0; i < dataOld.Length; i++)
{
dataOld[i] = oldValue[i];
}
for (int i = 0; i < dataNew.Length; i++)
{
dataNew[i] = newValue[i];
}
List<char> newCharList = new List<char>();
for (int i = 0; i < dataSource.Length; i++)
{
//找到与被替换数据第一个
if (dataSource[i] == dataOld[0])
{
//标志当前的i位置是不是要替换的位置
bool IsReplace = false;
//遍历被替换的数据
for (int j = 0; j < dataOld.Length; j++)
{
// dataOld需要替换的字符串长度 + 第一个匹配的替换索引,应该不超过原数据的长度
if (((i + j) < dataSource.Length) && (dataSource[i + j] == dataOld[j]))
{
IsReplace = true;
}
else
{
IsReplace = false;
break;
}
}
if (IsReplace)
{
//当前位置要加上被替换的数据的长度,不然只是替换了要被替换的数据的第一个char字符
i += dataOld.Length - 1;
//遍历你替换后的数据,添加到List里面
for (int k = 0; k < dataNew.Length; k++)
{
newCharList.Add(dataNew[k]);
}
}
else
{
//添加原数据的char[i]位置的字符
newCharList.Add(dataSource[i]);
}
}
else
{
//添加原数据的char[i]位置的字符
newCharList.Add(dataSource[i]);
}
}
return new string(newCharList.ToArray());
}
public bool EndsWith(StringScript value)
{
int length = value.Length;
bool isEqual = true;
for (int i = length - 1; i > 0; i--)
{
if (mItems[i] != value[i])
{
isEqual = false;
}
}
if (isEqual)
{
return true;
}
return false;
}
public bool StartsWith(StringScript value)
{
return Equals(value, this);
}
public int IndexOf(StringScript value)
{
int index;
if (Contain(value, out index))
{
return index;
}
return -1;
}
public int IndexOf(StringScript value, int startIndex)
{
int index;
if (Contain(value, out index, startIndex + 1))
{
return index;
}
return -1;
}
public StringScript[] Split(params char[] separator)
{
if (separator == null)
{
throw new ArgumentNullException();
}
//记录字符串中的分隔符总数和分隔符所在位置索引
int[] numArr = new int[mLength];
//分隔符的计数
int num = 0;
int length = separator.Length;
for (int j = 0; j < mLength; j++)
{
for (int i = 0; i < length; i++)
{
char item = separator[i];
if (mItems[j] == item)
{
numArr[num] = j;
num++;
break;
}
}
}
if (num == 0)
{
StringScript[] script = new StringScript[1];
script[0] = this;
return script;
}
//String的数组总数
int count = num + 1;
//每次子字符串截取开始的索引
int index = 0;
StringScript[] items = new StringScript[count];
for (int i = 0; i < count; i++)
{
StringScript str = null;
if (i == count - 1)
{
str = Substring(index, mLength - index);
}
else
{
str = Substring(index, numArr[i] - index);
}
// 当分隔符在索引为0或者mLength - 1时,截取的子字符串为空,不赋值给items数组
if (str != null)
{
items[i] = str;
}
index = numArr[i] + 1;
}
return items;
}
/// <summary>
/// 子字符串从指定的字符位置开始且具有指定的长度
/// </summary>
public StringScript Substring(int startIndex, int length)
{
if (startIndex + length > mLength || startIndex > mLength || length > mLength || startIndex < 0 || length < 0)
{
throw new IndexOutOfRangeException();
}
if (length == 0)
{
return null;
}
char[] items = new char[length];
for (int i = startIndex; i < startIndex + length; i++)
{
// i - startIndex 保持items数组的索引从0开始
items[i - startIndex] = mItems[i];
}
StringScript script = new StringScript(items);
return script;
}
/// <summary>
/// 转换为大写
/// 第一种实现方式,判断是否是大写,否,进行转换,mItems[i] - 32
/// 第二种实现方式,不用判断是否大小写,通过二进制转换 & 0101 1111,但C#中的& 默认操作的是十进制的数字
/// 所以需要转换成十进制95,或者十六进制0x5F
/// 原因,大小写字母在二进制上,只有第六个位置的值有不同(从右开始数)实际差10 0000 也就是32,实际为7位,这里前面添0方便比较
/// a 的2进制: 0110 0001 ascil: 97
/// A 的2进制: 0100 0001 ascil: 65
/// </summary>
/// <returns></returns>
public StringScript ToUpper()
{
char[] items = new char[mLength];
for (int i = 0; i < mLength; i++)
{
items[i] = (char)(mItems[i] & 0x5F);
}
return new StringScript(items);
}
/// <summary>
/// 转换为小写
/// 第一种实现方式,判断是否是小写,否,进行转换,mItems[i] + 32
/// 第二种实现方式,不用判断是否大小写,通过二进制转换 | 0010 0000,但C#中的& 默认操作的是十进制的数字
/// 所以需要转换成十进制32,或者十六进制0x20
/// 原因,大小写字母在二进制上,只有第六个位置的值有不同(从右开始数)实际差10 0000 也就是32,实际为7位,这里前面添0方便比较
/// a 的2进制: 0110 0001 ascil: 97
/// A 的2进制: 0100 0001 ascil: 65
/// </summary>
/// <returns></returns>
public StringScript ToLower()
{
char[] items = new char[mLength];
for (int i = 0; i < mLength; i++)
{
items[i] = (char)(mItems[i] | 0x20);
}
return new StringScript(items);
}
public IEnumerator<char> GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(this);
}
public struct Enumerator : IEnumerator<char>
{
private StringScript list;
private int index;
private char current;
public Enumerator(StringScript list)
{
this.list = list;
index = 0;
current = default(char);
}
public char Current
{
get
{
if (index <= 0 || index > list.Length)
{
throw new IndexOutOfRangeException();
}
return current;
}
}
object IEnumerator.Current
{
get
{
if (index <= 0 || index > list.Length)
{
throw new IndexOutOfRangeException();
}
return current;
}
}
public void Dispose()
{
}
public bool MoveNext()
{
if (index >= 0 && index < list.Length)
{
current = list[index];
index++;
return true;
}
return false;
}
public void Reset()
{
index = 0;
current = default(char);
}
}
public static implicit operator StringScript(string v)
{
if (v != null)
{
int length = v.Length;
if (length == 0)
{
return Empty;
}
else
{
char[] items = new char[length];
for (int i = 0; i < length; i++)
{
items[i] = v[i];
}
StringScript script = new StringScript(items);
return script;
}
}
return null;
}
public override string ToString()
{
return new string(mItems);
}
}
}
附上,测试用例:
using System;
namespace StructScript
{
class TestString
{
static void Main(string[] args)
{
StringScript string1a = "This is a StringScript created by assignment.";
Console.WriteLine(string1a.ToString());
Show(string1a);
StringScript string1a1 = "";
Show(string1a1);
StringScript string2a = "The path is C:\\PublicDocuments\\Report1.doc";
Show(string2a);
StringScript string3a = @"The path is C:\PublicDocuments\Report1.doc";
Show(string3a);
char[] chars = { 'w', 'o', 'r', 'd' };
StringScript string1 = new StringScript(chars);
Show(string1);
连接字符串
StringScript string2b = "This is one sentence. " + "This is a second. ";
string2b += "This is a third sentence.";
Show(string2b);
IndexOf Substring截取字符串
StringScript sentence = "This sentence has five words.";
// Extract the second word.
int startPosition = sentence.IndexOf(" ") + 1;
StringScript word2 = sentence.Substring(startPosition, sentence.IndexOf(" ", startPosition) - startPosition);
Console.WriteLine("Second word: " + word2);
EndsWith StartsWith
String[] strings = { "This is a string.", "Hello!", "Nothing.",
"Yes.", "randomize" };
foreach (var value in strings)
{
bool endsInPeriod = value.EndsWith(".");
bool startInPeriod = value.StartsWith("Th");
Console.WriteLine("'{0}' ends in a period: {1}",
value, endsInPeriod);
Console.WriteLine("'{0}' start in a period: {1}",
value, startInPeriod);
}
//split
String str = "sThis is a short string.s";
Char delimiter = 's';
String[] substrings = str.Split(delimiter);
foreach (var substring in substrings)
Console.WriteLine(substring);
replace
StringScript aaa = "The initial string";
aaa = aaa.Replace("i", "out");
Show(aaa);
//equals 大小写
Console.OutputEncoding = System.Text.Encoding.UTF8;
StringScript word = "File";
StringScript[] others = { word.ToLower(), word, word.ToUpper(), "fıle" };
foreach (var other in others)
{
if (word.Equals(other))
Console.WriteLine("{0} = {1}", word, other);
else
Console.WriteLine("{0} {1} {2}", word, '\u2260', other);
}
Console.ReadLine();
}
private static void Show(StringScript str)
{
if (str != null)
{
int length = str.Length;
for (int i = 0; i < length; i++)
{
Console.Write(str[i]);
}
Console.WriteLine();
}
}
}
}