根据c#中的长度动态构建字符串

时间:2018-02-15 10:24:15

标签: c# stringbuilder

我的目标是生成string。有以下条件。

首先,我将取一个空字符串,并根据长度开始构建字符串。

示例:

我有empty string ""

在第一步中,我想添加string至8个字符,表示我的string"",然后直到8个字符,我的字符串应包含值Hiwor所以最后我的字符串将为Hiwor如果没有值,则应在string填充空值。

在第二步中,我想将字符串meena添加到10个位置,因此我的最终字符串应为Hiwor meena。这样我想建立我的字符串。何我可以做到这一点。你能帮我吗?

样品: 初始字符串""

首先将字符Hiwor添加到8 positions

所以最终字符串应为Hiwor

第二步将字符串meena添加到10 postions

所以最终字符串应为Hiwor meena

直到现在我尝试了这样

 Dictionary<string, Int16> transLine = new Dictionary<string, Int16>();

            transLine.Add("ProductCode", 1);

            transLine.Add("ApplicantFirstName", 12);

            transLine.Add("ApplicantMiddleInitial", 1);

            transLine.Add("partner", 1);

            transLine.Add("employee", 8);

            List<string> list = new List<string>();
            list.Add("grouplife");
            list.Add("meena");
            list.Add("d");
            list.Add("yes");
            list.Add("yes");

            StringBuilder sb = new StringBuilder();
            foreach (var listItem in list)
            {
                foreach (var item in transLine)
                {
                    if (listItem == item.Key)
                    {
                        var length = item.Value;
                        sb.Insert(length, item.Key);
                    }
                }
            }

但它给我一个例外。Index was out of range. Must be non-negative and less than the size of the collection.

2 个答案:

答案 0 :(得分:3)

首先为StringBuilder定义一个扩展方法:

public static class StringBuilderExtensions
{
    public static void AppendPadded(this StringBuilder builder, string value, int length);
    {
        builder.Append($"{value}{new string(" ", length)}".Substring(0, length));
    }
    public static void AppendPadded(this StringBuilder builder, int value, int length);
    {
        builder.Append($"{new string("0", length)}{value}".Reverse().ToString().Substring(0, length).Reverse().ToString());
    }
}

然后使用:

StringBuilder builder = new StringBuilder();
builder.AppendPadded("Hiwor", 8);
builder.AppendPadded("meena", 10);
return builder.ToString();

或者用你的例子:

foreach (string item in list)
    builder.AppendPadded(item, transLine[item]);

编辑:好的,所以看起来你想要能够定义格式然后使用它来构建字符串。尝试:

(你需要为此引用System.ComponentModel.DataAnnotations和System.Reflection)

public abstract class AnItem
{
    private static int GetLength(PropertyInfo property)
    {
        StringLengthAttribute attribute = property.GetCustomAttributes(typeof(StringLengthAttribute), true).FirstOrDefault() as StringLengthAttribute;
        if (attribute == null)
            throw new Exception($"StringLength not specified for {property.Name}");
        return attribute.MaxLength();
    }
    private string GetPropertyValue(PropertyInfo property)
    {
        if (property.PropertyType == typeof(string))
            return property.GetValue(this);
        else if (property.PropertyType == typeof(int))
            return property.GetValue(this).ToString();
        else
            throw new Exception($"Property '{property.Name}' is not a supported type");
    }
    private static void SetPropertyValue(object item, PropertyInfo property, string value)
    {
        if (property.PropertyType == typeof(string))
            property.SetValue(item, value, null);
        else if (property.PropertyType == typeof(int))
            property.SetValue(item, int.Parse(value), null);
        else
            throw new Exception($"Property '{property.Name}' is not a supported type");
    }
    public string GetPaddedString()
    {
        StringBuilder builder = new StringBuilder();
        PropertyInfo[] properties = GetType().GetProperties();
        foreach (PropertyInfo property in properties)
            builder.AppendPadded(GetPropertyValue(property), GetLength(property));
        return builder.ToString();
    }
    public static T CreateFromPaddedString<T>(string paddedString) where T : AnItem, new()
    {
        T item = new T();
        int offset = 0;
        PropertyInfo[] properties = typeof(T).GetProperties();
        foreach (PropertyInfo property in properties)
        {
            int length = GetLength(property);
            if (offset + length > paddedString.Length)
                throw new Exception("The string is too short");
            SetPropertyValue(item, property, paddedString.Substring(offset, length)));
            offset += length;
        }
        if (offset < paddedString.Length)
            throw new Exception("The string is too long");
        return item;
    }
}
public class MyItem : AnItem
{
    [StringLength(1)]
    public string ProductCode { get; set; }

    [StringLength(12)]
    public string ApplicantFirstName { get; set; }

    [StringLength(1)]
    public string ApplicantMiddleInitial { get; set; }

    [StringLength(1)]
    public string Partner { get; set; }

    [StringLength(8)]
    public string Employee { get; set; }
}

然后使用它:

MyItem item = new MyItem
{
    ProductCode = "grouplife",
    ApplicantFirstName = "meena",
    ApplicantMiddleInitial = "d",
    Partner = "yes",
    Employee = "yes"
};

string paddedString = item.GetPaddedString();

读取字符串以获取项目:

MyItem item = AnItem.CreateFromPaddedString<MyItem>(paddedString);

答案 1 :(得分:0)

首先,我想谈谈你的例外情况:

  

指数超出范围。必须是非负数且小于集合的大小。

正如已经说过的例外。问题是您想要访问新StringBuilder sb中不存在的位置。

StringBuilder sb = new StringBuilder();

在此行之后,您的新sb为空。其中没有单一字符。因此,您只能访问位置0的索引。但是,几乎在内部for-each循环的第一次迭代中,您希望将索引1作为目标,并尝试将您的字符串插入到不存在的位置1

// length: 1 and item.Key: ProductCode
sb.Insert(length, item.Key); 

那么如何解决这个问题。您可以使用String.Format()或C#6中的字符串插值功能。

例如:

<强> String.Format()

var sb = new StringBuilder(string.Empty);      // sb: []
sb.Append(string.Format("{0, -8}", "Hiwor"));  // sb: [Hiwor   ]
sb.Append(string.Format("{0,-10}", "meena"));  // sb: [Hiwor   meena     ]

C#6字符串插值

var sb = new StringBuilder(string.Empty);  // sb: []
sb.Append($"{"Hiwor", -8}");               // sb: [Hiwor   ]
sb.Append($"{"meena", -10}");              // sb: [Hiwor   meena     ]

// ...

定位您的修改:

使用您给定的列表项,您将永远不会与任何词典键匹配。