String.Replace method not usable when knowing index to replace

L

Lonifasiko

Hi,

Just want to replace character at index 1 of a string with another
character. Just want to replace character at that position. I thought
Replace method would be overloaded with an index parameter with which
you can write wanted character at that position. But no, Replace
method only allows replacing one known character with another. The
problem is I don't know the character to replace, just must replace
the character at a known index.

This is the first workaround I've found:

string s = "ihj";
s = s.Remove(1, 1).Insert(1, "p");

And here is the second one:

string s = "ihj";
char[] array = s.ToCharArray();
array[1] = 'p';
s = new string(array);

A bit complicated,, don't you think? I think String.Replace should be
overloaded with something like this:

string Replace (int index, char newCharacter);

Any comments?

Thanks in advance.
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

Lonifasiko said:
Hi,

Just want to replace character at index 1 of a string with another
character. Just want to replace character at that position. I thought
Replace method would be overloaded with an index parameter with which
you can write wanted character at that position. But no, Replace
method only allows replacing one known character with another. The
problem is I don't know the character to replace, just must replace
the character at a known index.

This is the first workaround I've found:

string s = "ihj";
s = s.Remove(1, 1).Insert(1, "p");

And here is the second one:

string s = "ihj";
char[] array = s.ToCharArray();
array[1] = 'p';
s = new string(array);

A bit complicated,, don't you think? I think String.Replace should be
overloaded with something like this:

string Replace (int index, char newCharacter);

Any comments?

Thanks in advance.

The problem is that it's not that easy. Strings are immutable, so you
always have to create a new string when you are changing it, you can't
change an existing string.

I think that when you change characters in a string in that manner, you
usually change more than one character, so a method in the string class
would not be very useful. It would rather be misleading, causing people
to inadvertently create a lot of intermediate strings without realising it.

Here is another way of doing it:

StringBuilder builder = new StringBuilder(s);
builder.Chars[1] = 'p';
s = builder.ToString();

The StringBuilder uses a mutable string internally. When you call
ToString you will get that string as a regular immutable string, so
there is no extra intermediate string or array created as with the other
methods you presented.
 
L

Lonifasiko

StringBuilder offers Replace method overload, but still forces me to
know which character I want to replace. See MSDN help:

- StringBuilder.Replace (Char, Char, Int32, Int32) Replaces, within a
substring of this instance, all occurrences of a specified character
with another specified character.

- StringBuilder.Replace (String, String, Int32, Int32) Replaces,
within a substring of this instance, all occurrences of a specified
string with another specified string.

The problem is I don't know which is the character that must be
replaced; I only know its position! I've tried both these methods
passing null, String.Empty and so on as the first parameter, but
crashes during execution.

StringBuilder sb = new StringBuilder("ihj");
sb = sb.Replace(null, "p", 1, 1); // Cannot specify "h" must be
changed cause character at position 1 it's not always "h"

Any other ideas?

Regards.
 
L

Lonifasiko

Sorry, did not read Göran's previous post ;-)

Ok, then another workaround would be:

StringBuilder sb = new StringBuilder("ihj");
sb[1] = 'p';

I think it's still a bit rudimentary, but well, I see there's nothing
more to do......

Thanks.
 
R

rossum

Hi,

Just want to replace character at index 1 of a string with another
character. Just want to replace character at that position. I thought
Replace method would be overloaded with an index parameter with which
you can write wanted character at that position. But no, Replace
method only allows replacing one known character with another. The
problem is I don't know the character to replace, just must replace
the character at a known index.

This is the first workaround I've found:

string s = "ihj";
s = s.Remove(1, 1).Insert(1, "p");

And here is the second one:

string s = "ihj";
char[] array = s.ToCharArray();
array[1] = 'p';
s = new string(array);

A bit complicated,, don't you think? I think String.Replace should be
overloaded with something like this:

string Replace (int index, char newCharacter);

Any comments?

Thanks in advance.
A String.Replace() as you ask for makes strings mutable, which will
break a number of design assumptions in many programs. If a string
changes, then all other references to that string will now reference
to changed string, not the original one. This effectively turns all
strings into volatile declarations.

Having given the warning, what you want can be done in unsafe code by
using a char pointer:


public static unsafe void ChangeStringChar(string text, int index,
char newChar) {
if (index < 0 || index >= text.Length) {
throw new IndexOutOfRangeException();
}
fixed (char* cp = text) {
cp[index] = newChar;
}
}

public static void Main() {

string oldText = "12345";
string secondRef = oldText;

Console.WriteLine("Old text before = {0}", oldText);
Console.WriteLine("Second ref before = {0}", oldText);

ChangeStringChar(oldText, 1, 'X');

Console.WriteLine("Old text after = {0}", oldText);
Console.WriteLine("Second ref after = {0}", oldText);
}

Notice how the second reference to the original text is also changed.
If you don't want this side-effect then avoid this method and use one
of the other methods suggested. The code is marked unsafe for a good
reason.

rossum
 
B

Bill Butler

Sorry, did not read Göran's previous post ;-)

Ok, then another workaround would be:

StringBuilder sb = new StringBuilder("ihj");
sb[1] = 'p';

I think it's still a bit rudimentary, but well, I see there's nothing
more to do......

Why do you think it is " a bit rudimentary"?
It seems perfectly logical.
Is the complaint that you had to convert to a StringBuilder first?
Or are you upset that the String class doesn't support this?

Just curious
Bill
 
G

Guest

A string build uses an array internally as there is no such thing as a
muttable string .net. the ToString method returns a new string created from
that array.


--
Ciaran O''Donnell
http://wannabedeveloper.spaces.live.com


Göran Andersson said:
Lonifasiko said:
Hi,

Just want to replace character at index 1 of a string with another
character. Just want to replace character at that position. I thought
Replace method would be overloaded with an index parameter with which
you can write wanted character at that position. But no, Replace
method only allows replacing one known character with another. The
problem is I don't know the character to replace, just must replace
the character at a known index.

This is the first workaround I've found:

string s = "ihj";
s = s.Remove(1, 1).Insert(1, "p");

And here is the second one:

string s = "ihj";
char[] array = s.ToCharArray();
array[1] = 'p';
s = new string(array);

A bit complicated,, don't you think? I think String.Replace should be
overloaded with something like this:

string Replace (int index, char newCharacter);

Any comments?

Thanks in advance.

The problem is that it's not that easy. Strings are immutable, so you
always have to create a new string when you are changing it, you can't
change an existing string.

I think that when you change characters in a string in that manner, you
usually change more than one character, so a method in the string class
would not be very useful. It would rather be misleading, causing people
to inadvertently create a lot of intermediate strings without realising it.

Here is another way of doing it:

StringBuilder builder = new StringBuilder(s);
builder.Chars[1] = 'p';
s = builder.ToString();

The StringBuilder uses a mutable string internally. When you call
ToString you will get that string as a regular immutable string, so
there is no extra intermediate string or array created as with the other
methods you presented.
 
M

Marc Gravell

Göran is correct; it is a private string (m_StringValue). It breaks a
fair few rules, but it gets away with it on the grounds that it never
lets you see the string that it is abusing.

However, this is entirely an implementation detail, and may change
between framework versions. The behavior is the same, though.

The point is that non-core code should never see a mutable string.

Marc
 
G

Guest

Ciaran said:
A string build uses an array internally as there is no such thing as a
muttable string .net. the ToString method returns a new string created from
that array.

No, it does not.

Download a copy of .NET Reflector, and have a look at the code yourself.
 
C

Chris Shepherd

rossum said:
string Replace (int index, char newCharacter);
[...]
A String.Replace() as you ask for makes strings mutable, which will
break a number of design assumptions in many programs. If a string

No it doesn't. Existing versions of Replace work in this exact same way
-- they take the parameters, using them they create a new string, which
is then returned as the method's return value.

Converting the string to a character array and modifying the particular
index in the array seems the sensible way to solve this to me...

Chris.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top