使用 maxchar 剪切并换行字符串
Cut and take new line String with maxchar
我尝试创建一个函数来打印具有最大长度变量的所有帐单文章,但是当超过此最大长度时出现索引超出范围错误,或者在其他情况下总数和数量不出现在行:
最大长度变量:
private Int32 MaxCharPage = 36;
private Int32 MaxCharArticleName = 15;
private Int32 MaxCharArticleQuantity = 4;
private Int32 MaxCharArticleSellPrice = 6;
private Int32 MaxCharArticleTotal = 8;
private Int32 MaxCharArticleLineSpace = 1;
这是我当前的功能:
private IEnumerable<String> ArticleLine(Double Quantity, String Name, Double SellPrice, Double Total)
{
String QuantityChunk = (String)(Quantity).ToString("#,##0.00");
String PriceChunk = (String)(SellPrice).ToString("#,##0.00");
String TotalChunk = (String)(Total).ToString("#,##0.00");
// full chunks with "size" length
for (int i = 0; i < Name.Length / this.MaxCharArticleName; ++i)
{
String Chunk = String.Empty;
if (i == 0)
{
Chunk = QuantityChunk + new String((Char)32, (MaxCharArticleQuantity + MaxCharArticleLineSpace - QuantityChunk.Length)) +
Name.Substring(i * this.MaxCharArticleName, this.MaxCharArticleName) +
new String((Char)32, (MaxCharArticleLineSpace)) +
new String((Char)32, (MaxCharArticleSellPrice - PriceChunk.Length)) +
PriceChunk +
new String((Char)32, (MaxCharArticleLineSpace)) +
new String((Char)32, (MaxCharArticleTotal - TotalChunk.Length)) +
TotalChunk;
}
else
{
Chunk = new String((Char)32, (MaxCharArticleQuantity + MaxCharArticleLineSpace)) +
Name.Substring(i * this.MaxCharArticleName, this.MaxCharArticleName);
}
yield return Chunk;
}
if (Name.Length % this.MaxCharArticleName > 0)
{
String chunk = Name.Substring(Name.Length / this.MaxCharArticleName * this.MaxCharArticleName);
yield return new String((Char)32, (MaxCharArticleQuantity + MaxCharArticleLineSpace)) + chunk;
}
}
private void AddArticle(Double Quantity, String Name, Double SellPrice, Double Total)
{
Lines.AddRange(ArticleLine(Quantity, Name, SellPrice, Total).ToList());
}
例如:
private List<String> Lines = new List<String>();
private void Form1_Load(object sender, EventArgs e)
{
AddArticle(2.50, "EGGS", 0.50, 1.25); // Problem: Dont show the numbers like (Quantity, Sellprice, Total)
//AddArticle(100.52, "HAND SOAP /w EP", 5.00, 502.60); //OutOfRangeException
AddArticle(105.6, "LONG NAME ARTICLE DESCRIPTION", 500.03, 100.00);
//AddArticle(100, "LONG NAME ARTICLE DESCRIPTION2", 1500.03, 150003.00); // OutOfRangeException
foreach (String line in Lines)
{
Console.WriteLine(line);
}
}
控制台输出:
LINE1: EGGS
LINE2:105.6LONG NAME ARTIC 500.03 100.00
LINE3: LE DESCRIPTION
期望的输出:
LINE:2.50 EGGS 0.50 1.25
LINE:100. HAND SOAP /w EP 5.00 502.60
LINE: 52
LINE:105. LONG NAME ARTIC 500.03 100.00
LINE: 60 LE DESCRIPTION
LINE:100. LONG NAME ARTIC 1,500. 150,003.
LINE: 00 LE DESCRIPTION2 03 00
您正在尝试获取值(最终是字符串值)并从中提取指定的长度(块),其中给定组的每个单独的块在一行上,下一个块继续下一行。您发布的代码中存在几个挑战。最大的问题之一是您可能不了解 /
运算符的作用。当然,它用于除法,但它是 整数 除法,这意味着你得到一个整数作为结果。例如。 3 / 15 给你 0,而 17 / 15 给你 1。这意味着你的循环 永远不会 运行,除非值的长度大于指定的块限制。
另一个可能的问题是您只针对 Name
执行此检查,而不是其他项目(尽管出于简洁的原因您可能省略了它们的代码)。
您当前的代码还创建了很多 不必要的字符串,这将导致性能下降。请记住,在 C# 中,字符串是 immutable - 这意味着它们无法更改。当您 "change" 一个字符串的值时,您实际上是在创建 另一个 字符串的副本。
您的要求的关键是如何"chunk" 值以实现正确的输出。一种方法是创建一个 extension method that will take a string value and "chunkify" it for you. One such example is found here: Split String Into Array of Chunks。我稍微修改了它以使用 List<T>
,但数组也可以。
public static List<string> SplitIntoChunks(this string toSplit, int chunkSize)
{
int stringLength = toSplit.Length;
int chunksRequired = (int)Math.Ceiling(decimal)stringLength / (decimal)chunkSize);
List<string> chunks = new List<string>();
int lengthRemaining = stringLength;
for (int i = 0; i < chunksRequired; i++)
{
int lengthToUse = Math.Min(lengthRemaining, chunkSize);
int startIndex = chunkSize * i;
chunks.Add(toSplit.Substring(startIndex, lengthToUse));
lengthRemaining = lenghtRemaining - lengthToUse;
}
return chunks;
}
假设您有一个名为 myString
的 string
。你会像这样使用上面的方法:string[] chunks = myString.SplitIntoChunks(15);
,你会收到一个包含 15 个字符串的数组(取决于字符串的大小)。
快速浏览代码(因为页面上没有太多解释)。块的大小被传递到扩展方法中。记录字符串的长度,并使用 Math.Ceiling
函数确定该字符串的块数。
然后构造一个for
循环,以需要的chunk数量为上限。在循环内部,确定块的长度(使用块大小或字符串剩余长度中的较小者),根据块大小和循环索引计算起始索引,然后提取块通过 Substring
。最后计算剩余长度,一旦循环结束返回块。
在您的代码中使用此 extension method 的一种方法如下所示。扩展方法需要在一个单独的 static
class 中(我建议构建一个库,其中有一个 class 专门用于扩展方法,因为它们非常方便)。请注意,我没有时间对此进行测试,它对我的口味来说有点笨拙,但它至少应该让你朝着正确的方向前进。
private IEnumerable<string> ArticleLine(double quantity, string name, double sellPrice, double total)
{
List<string> quantityChunks = quantity.ToString("#,##0.00").SplitIntoChunks(maxCharArticleQuantity);
List<string> nameChunks = name.SplitIntoChunks(maxCharArticleName);
List<string> sellPriceChunks = sellPrice.ToString("#,##0.00").SplitIntoChunks(maxCharArticleSellPrice);
List<string> totalChunks = total.ToString("#,##0.00").SplitIntoChunks(maxCharArticleTotal);
int maxLines = (new List<int>() { quantityChunks.Count,
nameChunks.Count,
sellPriceChunks.Count,
totalChunks.Count }).Max();
for (int i = 0; i < maxLines; i++)
{
lines.Add(String.Format("{0}{1}{2}{3}",
quantityChunks.Count > i ?
quantityChunks[i].PadLeft(maxCharArticleQuantity) :
String.Empty.PadLeft(maxCharArticleQuantity),
nameChunks.Count > i ?
nameChunks[i].PadLeft(maxCharArticleName) :
String.Empty.PadLeft(maxCharArticleName, ' '),
sellPriceChunks.Count > i ?
sellPriceChunks[i].PadLeft(maxCharArticleSellPrice) :
String.Empty.PadeLeft(maxCharArticleSellPrice),
totalChunks.Count > i ?
totalChunks[i].PadLeft(maxCharArticleTotal) :
String.Empty.PadLeft(maxCharArticleTotal));
}
return lines;
}
上面的代码做了几件事。首先,它对四个变量中的每一个都调用 SplitIntoChunks
。
接下来,它使用 Max()
扩展方法(如果您还没有 System.Linq
,则需要添加对 System.Linq
的引用,再加上 using
指令) .以确定所需的最大行数(基于四个列表中的最高行数)。
最后,它使用 4for
循环来构建线条。请注意,我使用三元运算符 (?:
) 来构建每一行。我走这条路线的原因是为了使行的格式正确,即使 4 个值中的一个或多个值没有该行的内容。也就是说:
quantityChunks.Count > i
如果 quantityChunks
中的项目数大于 i
,则该行有该项目的条目。
quanityChunks[i].PadLeft(maxCharArticleQuantity, ' ')
如果条件评估为真,我们使用相应的条目(并用 spaces 填充它以保持对齐)。
String.Empty.PadLeft(maxCharArticleQuantity, ' ')
如果条件为假,我们只需输入 spaces 作为行中该位置的最大字符数。
然后你可以像这样打印输出:
foreach(string line in lines)
{
Console.WriteLine(line);
}
我检查最大行数和在 String.Format
中使用三元运算符的代码部分对我来说非常笨拙,但我没有时间将其巧妙地转化为更值得尊敬的东西。我希望这至少能为您指明正确的方向。
编辑
修复了 PadLeft
语法并删除了指定的字符,因为默认使用 space。
我尝试创建一个函数来打印具有最大长度变量的所有帐单文章,但是当超过此最大长度时出现索引超出范围错误,或者在其他情况下总数和数量不出现在行:
最大长度变量:
private Int32 MaxCharPage = 36;
private Int32 MaxCharArticleName = 15;
private Int32 MaxCharArticleQuantity = 4;
private Int32 MaxCharArticleSellPrice = 6;
private Int32 MaxCharArticleTotal = 8;
private Int32 MaxCharArticleLineSpace = 1;
这是我当前的功能:
private IEnumerable<String> ArticleLine(Double Quantity, String Name, Double SellPrice, Double Total)
{
String QuantityChunk = (String)(Quantity).ToString("#,##0.00");
String PriceChunk = (String)(SellPrice).ToString("#,##0.00");
String TotalChunk = (String)(Total).ToString("#,##0.00");
// full chunks with "size" length
for (int i = 0; i < Name.Length / this.MaxCharArticleName; ++i)
{
String Chunk = String.Empty;
if (i == 0)
{
Chunk = QuantityChunk + new String((Char)32, (MaxCharArticleQuantity + MaxCharArticleLineSpace - QuantityChunk.Length)) +
Name.Substring(i * this.MaxCharArticleName, this.MaxCharArticleName) +
new String((Char)32, (MaxCharArticleLineSpace)) +
new String((Char)32, (MaxCharArticleSellPrice - PriceChunk.Length)) +
PriceChunk +
new String((Char)32, (MaxCharArticleLineSpace)) +
new String((Char)32, (MaxCharArticleTotal - TotalChunk.Length)) +
TotalChunk;
}
else
{
Chunk = new String((Char)32, (MaxCharArticleQuantity + MaxCharArticleLineSpace)) +
Name.Substring(i * this.MaxCharArticleName, this.MaxCharArticleName);
}
yield return Chunk;
}
if (Name.Length % this.MaxCharArticleName > 0)
{
String chunk = Name.Substring(Name.Length / this.MaxCharArticleName * this.MaxCharArticleName);
yield return new String((Char)32, (MaxCharArticleQuantity + MaxCharArticleLineSpace)) + chunk;
}
}
private void AddArticle(Double Quantity, String Name, Double SellPrice, Double Total)
{
Lines.AddRange(ArticleLine(Quantity, Name, SellPrice, Total).ToList());
}
例如:
private List<String> Lines = new List<String>();
private void Form1_Load(object sender, EventArgs e)
{
AddArticle(2.50, "EGGS", 0.50, 1.25); // Problem: Dont show the numbers like (Quantity, Sellprice, Total)
//AddArticle(100.52, "HAND SOAP /w EP", 5.00, 502.60); //OutOfRangeException
AddArticle(105.6, "LONG NAME ARTICLE DESCRIPTION", 500.03, 100.00);
//AddArticle(100, "LONG NAME ARTICLE DESCRIPTION2", 1500.03, 150003.00); // OutOfRangeException
foreach (String line in Lines)
{
Console.WriteLine(line);
}
}
控制台输出:
LINE1: EGGS
LINE2:105.6LONG NAME ARTIC 500.03 100.00
LINE3: LE DESCRIPTION
期望的输出:
LINE:2.50 EGGS 0.50 1.25
LINE:100. HAND SOAP /w EP 5.00 502.60
LINE: 52
LINE:105. LONG NAME ARTIC 500.03 100.00
LINE: 60 LE DESCRIPTION
LINE:100. LONG NAME ARTIC 1,500. 150,003.
LINE: 00 LE DESCRIPTION2 03 00
您正在尝试获取值(最终是字符串值)并从中提取指定的长度(块),其中给定组的每个单独的块在一行上,下一个块继续下一行。您发布的代码中存在几个挑战。最大的问题之一是您可能不了解 /
运算符的作用。当然,它用于除法,但它是 整数 除法,这意味着你得到一个整数作为结果。例如。 3 / 15 给你 0,而 17 / 15 给你 1。这意味着你的循环 永远不会 运行,除非值的长度大于指定的块限制。
另一个可能的问题是您只针对 Name
执行此检查,而不是其他项目(尽管出于简洁的原因您可能省略了它们的代码)。
您当前的代码还创建了很多 不必要的字符串,这将导致性能下降。请记住,在 C# 中,字符串是 immutable - 这意味着它们无法更改。当您 "change" 一个字符串的值时,您实际上是在创建 另一个 字符串的副本。
您的要求的关键是如何"chunk" 值以实现正确的输出。一种方法是创建一个 extension method that will take a string value and "chunkify" it for you. One such example is found here: Split String Into Array of Chunks。我稍微修改了它以使用 List<T>
,但数组也可以。
public static List<string> SplitIntoChunks(this string toSplit, int chunkSize)
{
int stringLength = toSplit.Length;
int chunksRequired = (int)Math.Ceiling(decimal)stringLength / (decimal)chunkSize);
List<string> chunks = new List<string>();
int lengthRemaining = stringLength;
for (int i = 0; i < chunksRequired; i++)
{
int lengthToUse = Math.Min(lengthRemaining, chunkSize);
int startIndex = chunkSize * i;
chunks.Add(toSplit.Substring(startIndex, lengthToUse));
lengthRemaining = lenghtRemaining - lengthToUse;
}
return chunks;
}
假设您有一个名为 myString
的 string
。你会像这样使用上面的方法:string[] chunks = myString.SplitIntoChunks(15);
,你会收到一个包含 15 个字符串的数组(取决于字符串的大小)。
快速浏览代码(因为页面上没有太多解释)。块的大小被传递到扩展方法中。记录字符串的长度,并使用 Math.Ceiling
函数确定该字符串的块数。
然后构造一个for
循环,以需要的chunk数量为上限。在循环内部,确定块的长度(使用块大小或字符串剩余长度中的较小者),根据块大小和循环索引计算起始索引,然后提取块通过 Substring
。最后计算剩余长度,一旦循环结束返回块。
在您的代码中使用此 extension method 的一种方法如下所示。扩展方法需要在一个单独的 static
class 中(我建议构建一个库,其中有一个 class 专门用于扩展方法,因为它们非常方便)。请注意,我没有时间对此进行测试,它对我的口味来说有点笨拙,但它至少应该让你朝着正确的方向前进。
private IEnumerable<string> ArticleLine(double quantity, string name, double sellPrice, double total)
{
List<string> quantityChunks = quantity.ToString("#,##0.00").SplitIntoChunks(maxCharArticleQuantity);
List<string> nameChunks = name.SplitIntoChunks(maxCharArticleName);
List<string> sellPriceChunks = sellPrice.ToString("#,##0.00").SplitIntoChunks(maxCharArticleSellPrice);
List<string> totalChunks = total.ToString("#,##0.00").SplitIntoChunks(maxCharArticleTotal);
int maxLines = (new List<int>() { quantityChunks.Count,
nameChunks.Count,
sellPriceChunks.Count,
totalChunks.Count }).Max();
for (int i = 0; i < maxLines; i++)
{
lines.Add(String.Format("{0}{1}{2}{3}",
quantityChunks.Count > i ?
quantityChunks[i].PadLeft(maxCharArticleQuantity) :
String.Empty.PadLeft(maxCharArticleQuantity),
nameChunks.Count > i ?
nameChunks[i].PadLeft(maxCharArticleName) :
String.Empty.PadLeft(maxCharArticleName, ' '),
sellPriceChunks.Count > i ?
sellPriceChunks[i].PadLeft(maxCharArticleSellPrice) :
String.Empty.PadeLeft(maxCharArticleSellPrice),
totalChunks.Count > i ?
totalChunks[i].PadLeft(maxCharArticleTotal) :
String.Empty.PadLeft(maxCharArticleTotal));
}
return lines;
}
上面的代码做了几件事。首先,它对四个变量中的每一个都调用 SplitIntoChunks
。
接下来,它使用 Max()
扩展方法(如果您还没有 System.Linq
,则需要添加对 System.Linq
的引用,再加上 using
指令) .以确定所需的最大行数(基于四个列表中的最高行数)。
最后,它使用 4for
循环来构建线条。请注意,我使用三元运算符 (?:
) 来构建每一行。我走这条路线的原因是为了使行的格式正确,即使 4 个值中的一个或多个值没有该行的内容。也就是说:
quantityChunks.Count > i
如果 quantityChunks
中的项目数大于 i
,则该行有该项目的条目。
quanityChunks[i].PadLeft(maxCharArticleQuantity, ' ')
如果条件评估为真,我们使用相应的条目(并用 spaces 填充它以保持对齐)。
String.Empty.PadLeft(maxCharArticleQuantity, ' ')
如果条件为假,我们只需输入 spaces 作为行中该位置的最大字符数。
然后你可以像这样打印输出:
foreach(string line in lines)
{
Console.WriteLine(line);
}
我检查最大行数和在 String.Format
中使用三元运算符的代码部分对我来说非常笨拙,但我没有时间将其巧妙地转化为更值得尊敬的东西。我希望这至少能为您指明正确的方向。
编辑
修复了 PadLeft
语法并删除了指定的字符,因为默认使用 space。