2

To build a sparsely populated fixed width record, I would like to copy a string field into a StringBuilder object, starting at a given position. A nice syntax for this would have been

StringBuilder sb = new StringBuilder(' ', 100);
string fieldValue = "12345";
int startPos = 16; 
int endPos = startPos + fieldValue.Length - 1;
sb[startPos..endPos] = fieldValue; // no such syntax

I could obviously do this C style, one character at a time:

for (int ii = 0; ii++; ii < fieldValue.Length)
    sb[startPos + ii] = fieldValue[ii];

But this seems way too cumbersome for c#, plus it uses a loop where the resulting machine code could more efficiently use a bulk copy, which can make a difference if the strings involved were long. Any ideas for a better way?

4 Answers 4

2

Your original algorithm can be supported in the following way

var builder = new StringBuilder(new string(' ', 100));
string toInsert = "HELLO WORLD";
int atIndex = 10;
builder.Remove(atIndex, toInsert.Length);
builder.Insert(atIndex, toInsert);

Debug.Assert(builder.Length == 100);
Debug.Assert(builder.ToString().IndexOf(toInsert) == 10);
Sign up to request clarification or add additional context in comments.

3 Comments

It could be even slower than char-by-char replacing because of shifting tail back and forth. I'd not recommend that instead of a simple loop.
For a single algorithmic operation such as this, I'd just use a string and forget the builder altogether, it's overkill. For something I would perform multiple times, say, in a loop, I'd want efficiency, certainly, but also something easy to reason about. char replacement operations in an array would rank lower on the reasonability meter, so the presumed performance gain would need to be worth it.
It depends on the scenario heavily. If you read big file for example and replacing there several places in the beginning - this would be great loss of performance. And for readability for and Remote/Insert variants are almost equal here imo. So it is up to OP basically :)
1

You can write your own specialized string builder class that uses the efficient machinery of char[] and string underneath the hood, in particular String.CopyTo:

public class FixedStringBuilder
{
    char[] buffer;

    public FixedStringBuilder(int length)
    {
        buffer = new string(' ', length).ToCharArray();
    }

    public FixedStringBuilder Replace(int index, string value)
    {
        value.CopyTo(0, buffer, index, value.Length);
        return this;
    }

    public override string ToString()
    {
        return new string(buffer);
    }
}

class Program
{
    static void Main(string[] args)
    {
        FixedStringBuilder sb = new FixedStringBuilder(100);
        string fieldValue = "12345";
        int startPos = 16; 
        sb.Replace(startPos, fieldValue);
        string buffer = sb.ToString();
    }
}

1 Comment

Thanks - this is exactly I was looking for. Would never occur to me to look for it as a method of the immutable System.String :) Thanks!
0

The closest solution to your goal is to convert the source string in a char array, then substitute the cells. Any char array can be converted back to a string.

Comments

0

why are you pre-allocating memory in the string builder (it is only support performance).

i would append the known prefix, then the actual value and then the postfix to the string.

something like:

StringBuilder sb = new StringBuilder();
sb.Append(prefix).Append(value).Append(postfix);

1 Comment

This does not address the "seek" scenario, where you have a static character sequence of a known fixed length, and you want to overwrite an small area of it at a given "address".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.