how to change nth element of the string - c#

i have a code in c# like below
string s = new string('~',25);
int ind = 5;
s[ind] = 'A';
it gives an error
Property or indexer 'string.this[int]' cannot be assigned to -- it is read
so what is the problem, and how can i fix it.

Strings are immutable - you can't change an existing one.
Two options:
Use StringBuilder, e.g.
StringBuilder builder = new StringBuilder(new string('~', 25));
builder[5] = 'A';
string result = builder.ToString();
Build a new string from a char array:
char[] chars = new string('~', 25).ToCharArray();
chars[5] = 'A';
string result = new string(chars);
In both cases you could populate the mutable data without building a new string to start with if you want - that would involve more code, but would probably be more efficient.
Alternatively, you can take substrings and concatenate them together, as per another answer ...there are basically lots of ways of tackling this. Which one is appropriate will depend on your actual use case.

Following MSDN:
Strings are immutable--the contents of a string object cannot be changed after the object is created, although the syntax makes it appear as if you can do this.
Take a look at StringBuilder class or use char array instead.

C# strings are immutable which means that once constructed the cannot be changed. Try using an array of chars instead.

Try
s = s.Substring(0, ind) + "A" + s.Substring(ind + 1);

You can use Stringbuilder, in which you can assign to the indexer:
StringBuilder sb = s;
int ind = 5;
sb[ind] = 'A';
s = sb.ToString();

Related

Does using a Range to get part of a string create a new string in memory?

By using the C# 8 feature Range, does it create a new string in memory or does it provide a "pointer" to the memory parts of the previous string already there?
var x = "foo"[1..2];
Is compiled to;
int num = 1;
int length = 2 - num;
"foo".Substring(num, length);
And .Substring will create a new copy of the characters.
If you don't need a string, you could use "foo".AsSpan()[1..2];
I'm not following your question. A range of a string is not a string, its an array of char. string implements IEnumerable<char>.
If you want a substring, then you should use string.Substring, and yes, it will create a new string.

Inverse Count Issue C#

Not Quite what the title suggests, what i need is a way to count a string backwards like
string i = "3027"
i[0] = label1.Text
Result = 7 not 3 is there a way?
not sure if you need my code or not its not really important.
You can reverse the string using a number of approaches including
public static string ReverseString(string s)
{
char[] arr = s.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
http://www.dotnetperls.com/reverse-string
then access the portion of the reversed string that you are interested in.
Note that you cannot assign to i[0] as shown in your example code because strings are immutable in C# (why). If you want to construct a string a bit at a time, it is often most efficient to use StringBuilder.

string.insert multiple values. Is this possible?

Im still learning in C#, and there is one thing i cant really seem to find the answer to.
If i have a string that looks like this "abcdefg012345", and i want to make it look like "ab-cde-fg-012345"
i tought of something like this:
string S1 = "abcdefg012345";
string S2 = S1.Insert(2, "-");
string S3 = S2.Insert(6, "-");
string S4 = S3.Insert.....
...
..
Now i was looking if it would be possible to get this al into 1 line somehow, without having to make all those strings.
I assume this would be possible somehow ?
Whether or not you can make this a one-liner (you can), it will always cause multiple strings to be created, due to the immutability of the String in .NET
If you want to do this somewhat efficiently, without creating multiple strings, you could use a StringBuilder. An extension method could also be useful to make it easier to use.
public static class StringExtensions
{
public static string MultiInsert(this string str, string insertChar, params int[] positions)
{
StringBuilder sb = new StringBuilder(str.Length + (positions.Length*insertChar.Length));
var posLookup = new HashSet<int>(positions);
for(int i=0;i<str.Length;i++)
{
sb.Append(str[i]);
if(posLookup.Contains(i))
sb.Append(insertChar);
}
return sb.ToString();
}
}
Note that this example initialises StringBuilder to the correct length up-front, therefore avoiding the need to grow the StringBuilder.
Usage: "abcdefg012345".MultiInsert("-",2,5); // yields "abc-def-g012345"
Live example: http://rextester.com/EZPQ89741
string S1 = "abcdefg012345".Insert(2, "-").Insert(6, "-")..... ;
If the positions for the inserted strings are constant you could consider using string.Format() method. For example:
string strTarget = String.Format("abc{0}def{0}g012345","-");
string s = "abcdefg012345";
foreach (var index in [2, 6, ...]
{
s = s.Insert(index, "-");
}
I like this
StringBuilder sb = new StringBuilder("abcdefg012345");
sb.Insert(6, '-').Insert(2, '-').ToString();
String s1 = "abcdefg012345";
String seperator = "-";
s1 = s1.Insert(2, seperator).Insert(6, seperator).Insert(9, seperator);
Chaining them like that keeps your line count down. This works because the Insert method returns the string value of s1 with the parameters supplied, then the Insert function is being called on that returned string and so on.
Also it's worth noting that String is a special immutable class so each time you set a value to it, it is being recreated. Also worth noting that String is a special type that allows you to set it to a new instance with calling the constructor on it, the first line above will be under the hood calling the constructor with the text in the speech marks.
Just for the sake of completion and to show the use of the lesser known Aggregate function, here's another one-liner:
string result = new[] { 2, 5, 8, 15 }.Aggregate("abcdefg012345", (s, i) => s.Insert(i, "-"));
result is ab-cd-ef-g01234-5. I wouldn't recommend this variant, though. It's way too hard to grasp on first sight.
Edit: this solution is not valid, anyway, as the "-" will be inserted at the index of the already modified string, not at the positions wrt to the original string. But then again, most of the answers here suffer from the same problem.
You should use a StringBuilder in this case as Strings objects are immutable and your code would essentially create a completely new string for each one of those operations.
http://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.71).aspx
Some more information available here:
http://www.dotnetperls.com/stringbuilder
Example:
namespace ConsoleApplication10
{
class Program
{
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder("abcdefg012345");
sb.Insert(2, '-');
sb.Insert(6, '-');
Console.WriteLine(sb);
Console.Read();
}
}
}
If you really want it on a single line you could simply do something like this:
StringBuilder sb = new StringBuilder("abcdefg012345").Insert(2, '-').Insert(6, '-');

How to change 1 char in the string?

I have this code:
string str = "valta is the best place in the World";
I need to replace the first symbol. When I try this:
str[0] = 'M';
I received an error. How can I do this?
Strings are immutable, meaning you can't change a character. Instead, you create new strings.
What you are asking can be done several ways. The most appropriate solution will vary depending on the nature of the changes you are making to the original string. Are you changing only one character? Do you need to insert/delete/append?
Here are a couple ways to create a new string from an existing string, but having a different first character:
str = 'M' + str.Remove(0, 1);
str = 'M' + str.Substring(1);
Above, the new string is assigned to the original variable, str.
I'd like to add that the answers from others demonstrating StringBuilder are also very appropriate. I wouldn't instantiate a StringBuilder to change one character, but if many changes are needed StringBuilder is a better solution than my examples which create a temporary new string in the process. StringBuilder provides a mutable object that allows many changes and/or append operations. Once you are done making changes, an immutable string is created from the StringBuilder with the .ToString() method. You can continue to make changes on the StringBuilder object and create more new strings, as needed, using .ToString().
I suggest you to use StringBuilder class for it and than parse it to string if you need.
System.Text.StringBuilder strBuilder = new System.Text.StringBuilder("valta is the best place in the World");
strBuilder[0] = 'M';
string str=strBuilder.ToString();
You can't change string's characters in this way, because in C# string isn't dynamic and is immutable and it's chars are readonly. For make sure in it try to use methods of string, for example, if you do str.ToLower() it makes new string and your previous string doesn't change.
Strings are immutable. You can use the string builder class to help!:
string str = "valta is the best place in the World";
StringBuilder strB = new StringBuilder(str);
strB[0] = 'M';
While it does not answer the OP's question precisely, depending on what you're doing it might be a good solution. Below is going to solve my problem.
Let's say that you have to do a lot of individual manipulation of various characters in a string. Instead of using a string the whole time use a char[] array while you're doing the manipulation. Because you can do this:
char[] array = "valta is the best place in the World".ToCharArray();
Then manipulate to your hearts content as much as you need...
array[0] = "M";
Then convert it to a string once you're done and need to use it as a string:
string str = new string(array);
Merged Chuck Norris's answer w/ Paulo Mendonça's using extensions methods:
/// <summary>
/// Replace a string char at index with another char
/// </summary>
/// <param name="text">string to be replaced</param>
/// <param name="index">position of the char to be replaced</param>
/// <param name="c">replacement char</param>
public static string ReplaceAtIndex(this string text, int index, char c)
{
var stringBuilder = new StringBuilder(text);
stringBuilder[index] = c;
return stringBuilder.ToString();
}
I made a Method to do this
string test = "Paul";
test = ReplaceAtIndex(0, 'M', test);
// (...)
static string ReplaceAtIndex(int i, char value, string word)
{
char[] letters = word.ToCharArray();
letters[i] = value;
return string.Join("", letters);
}
str = "M" + str.Substring(1);
If you'll do several such changes use a StringBuilder or a char[].
(The threshold of when StringBuilder becomes quicker is after about 5 concatenations or substrings, but note that grouped concatenations of a + "b" + c + d + "e" + f are done in a single call and compile-type concatenations of "a" + "b" + "c" don't require a call at all).
It may seem that having to do this is horribly inefficient, but the fact that strings can't be changes allows for lots of efficiency gains and other advantages such as mentioned at Why .NET String is immutable?
I found a solution in unsafe context:
string str = "gg"; char c = 'H'; int index = 1;
fixed (char* arr = str) arr[index] = 'H';
Console.WriteLine(str);
It's so simple.
And in safe context:
string str = "gg"; char c = 'H'; int index = 1;
GCHandle handle = GCHandle.Alloc(str, GCHandleType.Pinned);
IntPtr arrAddress = handle.AddrOfPinnedObject();
Marshal.WriteInt16(arrAddress + index * sizeof(char), c);
handle.Free();
Console.WriteLine(str);
If speed is important, then you can do this:
String strValue = "$Some String Here!";
strValue = strValue.Remove(0, 1).Insert(0, "*");
This way, you don't really reconstruct the string, you keep the original object and just removing the first character and inserting a new one.
I usually approach it like this:
char[] c = text.ToCharArray();
for (i=0; i<c.Length; i++)
{
if (c[i]>'9' || c[i]<'0') // use any rules of your choice
{
c[i]=' '; // put in any character you like
}
}
// the new string can have the same name, or a new variable
String text=new string(c);
Can also be done using C# 8 ranges:
str = "M" + str[1..];
or + string interpolation:
str = $"M{str[1..]}";

Why string[0] = "new value" does not compile?

How I set new value for an string by index value?
I tried:
string a = "abc";
a[0] = "A";
not works for strings, but yes for chars. Why?
Strings in C# (and other .NET languages which use System.String in the base class library) are immutable. That is, you can't modify a string character by character that way (or for that matter, can you modify a string ever).
If you want to modify a string based on the index, you have to convert it to an array using System.String.ToCharArray() first. You convert it back to a string using System.String's constructor, passing in the modified array.
Your example would have to be changed to look like:
string a = "abc";
char[] array = a.ToCharArray();
array[0] = 'A'; //Note single quotes, not double quotes
a = new string(array);
The System.String type does not permit writing by index (or via any means -- to change a the content of a String variable, one must replace it with a reference to an entirely new String). The System.Text.StringBuilder type does, however, permit writing by index. One may create a new System.Text.StringBuilder object (optionally passing a string to the constructor), manipulate it, and then use its ToString method to convert it back to a string.
A replacement would be this:
string a = "abc";
a = a.Remove(0, 1);
a = a.Insert(0, "A");
or for the C say:
string a = "abc";
a = a.Remove(2, 1);
a = a.Insert(2, "C");
Also using a stringbuilder may work as per http://msdn.microsoft.com/en-us/library/362314fe.aspx
StringBuilder sb = new StringBuilder("abc");
sb[0] = 'A';
sb[2] = 'C';
string str = sb.ToString();
Use StringBuilder if you need a mutable String.
Also: a[0] can represent one character while "A" is a String object-it is illegal.
a[0] for a character is a address in memory to which you can assign a value.
string on the other hand is a class and in this case the a[0] is actually a function call to the overloaded operator[]. You can't assign values to functions.

Categories