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

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.

Related

C# Error when calling Reverse : System.Linq.Enumerable+ReverseIterator`1[System.Char]

a quite simple code:
string str = "hello world";
Console.WriteLine(str.GetType());
Console.WriteLine("str.Reverse().ToString():");
Console.WriteLine(str.Reverse().ToString());
and got the following output:
System.String
str.Reverse().ToString():
System.Linq.Enumerable+ReverseIterator`1[System.Char]
the question is , why there is the 'ReverseIterator`1' error ? thanks.
String does not have instance method Reverse, it is actually an extension method Enumerable.Reverse<TSource>(IEnumerable<TSource>) available on string due to the fact that it implements IEnumerable<char>:
public sealed class String : ICloneable,
IComparable,
IComparable<string>,
IConvertible,
IEquatable<string>,
System.Collections.Generic.IEnumerable<char>
Reverse returns IEnumerable<char> with underlying implementation missing overload for ToString so it outputs type name. I.e. next to lines will have the same output:
Console.WriteLine(str.Reverse().ToString());
Console.WriteLine(str.Reverse().GetType());
You can reverse string next "quick and dirty" solution:
var reversed = new string(str.Reverse().ToArray());
Or select one of answers provided here.
String does not have instance method Reverse. Your code str.Reverse().ToString() is actually splitting your string char-by-char and then reversing it using the Reverse method in the Array instance.
What you can do is manually split your string into a char array, reverse the array using the Reverse method in the Array instance and then join it using the Join method in String instance. Something like this:
string str = "hello world";
Console.WriteLine(str.GetType());
// Manually split the string into a char array,
// reverse the array and then join it.
Console.WriteLine("str.ToCharArray().Reverse():");
string NewStr = string.Join("", str.ToCharArray().Reverse());
Console.WriteLine(NewStr);
// Output: "dlrow olleh"
But if you want to stick with the code you wrote then you can do something like this:
string str = "hello world";
Console.WriteLine(str.GetType());
string NewStr = "";
Console.WriteLine("str.Reverse().ToString():");
// Split the string into a char array,
// reverse the char array and append the chars to a new string.
foreach (var i in str.Reverse())
{
NewStr += i.ToString();
}
Console.WriteLine(NewStr);
// Output: "dlrow olleh"
Hope it helped :)

is there a splitByCharacterType method in c# like there is in Java?

In Java there is a method splitByCharacterType that takes a string, for example 0015j8*(, and split it into "0015","j","8","*","(". Is there a built in function like this in c#? If not how would I go around building a function to do this?
public static IEnumerable<string> SplitByCharacterType(string input)
{
if (String.IsNullOrEmpty(input))
throw new ArgumentNullException(nameof(input));
StringBuilder segment = new StringBuilder();
segment.Append(input[0]);
var current = Char.GetUnicodeCategory(input[0]);
for (int i = 1; i < input.Length; i++)
{
var next = Char.GetUnicodeCategory(input[i]);
if (next == current)
{
segment.Append(input[i]);
}
else
{
yield return segment.ToString();
segment.Clear();
segment.Append(input[i]);
current = next;
}
}
yield return segment.ToString();
}
Usage as follows:
string[] split = SplitByCharacterType("0015j8*(").ToArray();
And the result is "0015","j","8","*","("
I recommend you implement as an extension method.
I don't think that such method exist. You can follow steps as below to create your own utility method:
Create a list to hold split strings
Define strings with all your character types e.g.
string numberString = "0123456789";
string specialChars = "~!##$%^&*(){}|\/?";
string alphaChars = "abcde....XYZ";
Define a variable to hold the temporary string
Define a variable to note the type of chars
Traverse your string, one char at a time, check the type of char by checking the presence of the char in predefined type strings.
If type is new than the previous type(check the type variable value) then add the temporary string(not empty) to the list, assign the new type to type variable and assign the current char to the temp string. If otherwise, then append the char to temporary string.
In the end of traversal, add the temporary string(not empty) to the list
Now your list contains the split strings.
Convert the list to an string array and you are done.
You could maybe use regex class, somthing like below, but you will need to add support for other chars other than numbers and letters.
var chars = Regex.Matches("0015j8*(", #"((?:""[^""\\]*(?:\\.[^""\\]*)*"")|[a-z]|\d+)").Cast<Match>().Select(match => match.Value).ToArray();
Result
0015,J,8

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..]}";

how to change nth element of the string

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();

how can I convert a char to a char* in c#?

how can I convert a char to a char* in c#?
I'm initializeing a String object like this:
String test=new String('c');
and I'm getting this error:
Argument '1': cannot convert from 'char' to 'char*'
That is a bit of a strange way to initialize a string, if you know beforehand what you want to store in it.
You can simply use:
String test="c";
If you have a specific need to convert a char variable to a string, you can use the built in ToString() function:
String test = myCharVariable.ToString();
unsafe
{
char c = 'c';
char *ch = &c;
}
Your example has a String and a compile error from using one of the String constructor overloads, so I'm guessing you really just want an array of chars, aka a String and maybe not a char*.
In which case:
char c = 'c';
string s = c.ToString(); // or...
string s1 = "" +c;
Also available:
unsafe
{
char c = 'c';
char* ch = &c;
string s1 = new string(ch);
string s2 = new string(c, 0);
}
string myString1 = new string(new char[] {'a'});
string myString2 = 'a'.ToString();
string myString3 = "a";
string myString4 = new string('a', 1);
unsafe {
char a = 'a';
string myString5 = new string(&a);
}
There is no overload of the public constructor for String that accepts a single char as a parameter. The closest match is
public String(char c, int count)
which creates a new String that repeats the char c count times. Thus, you could say
string s = new string('c', 1);
There are other options. There is a public constructor of String that accepts a char[] as a parameter:
public String(char[] value)
This will create a String that is initialized with the Unicode characters in value. Thus you could say
char c = 'c';
string s = new String(new char[] { c });
Another option is to say
char c = 'c'
string s = c.ToString();
But the most straightforward approach that most will expect to see is
string s = "c";
As for converting a char to a char * you can not safely do this. If you want to use the overload of the public constructor for String that accepts a char * as a parameter, you could do this:
unsafe {
char c = 'c';
char *p = &c;
string s = new string(p);
}
Can't hurt to have yet another answer:
string test = string.Empty + 'c';
The String class has many constructors, if all you're after is to create a string containing one character, you can use the following:
String test = new String(new char[] { 'c' });
If you are hard coding it, is there a reason you cant just use:
String test = "c";
How about:
var test = 'c'.ToString()
When using a char in the String constructor, you should also give a count parameter to specify how many times that character should be added to the string:
String test=new String('c', 1);
See also here.
use
String test("Something");
String test = new String(new char[]{'c'});
The easiest way to do this conversion from your example is just change the type of quotes you are using from single quotes
String test = new String('c');
to double quotes and remove the constructor call:
String test = "c";
char c = 'R';
char *pc = &c;
Using single quotes (as in your question: 'c') means that you are creating a char. Using double quotes, e.g. "c", means you creating a string. These are not interchangable types in c#.
A char*, as you might be aware, is how strings are represented in c++ to some extent, and c# supports some of the conventions of c++. This means that a char* can easily (for the programmer at least) be converted to a string in c#. Unfortunately a char is not inherently a char*, so the same cannot be done.

Categories