cannot be assigned to -- it is read only - C# - c#

public struct Osoba{
public string nazwisko;
[...]
}
for (int k = 0; k < l; k++)
{
dlugosc = osoba[k].nazwisko.Length;
[...]
if (c[0] == 's' && c[1] == 'k' && c[2] == 'i')
{
osoba[k].nazwisko[dlugosc - 3] = '*';
osoba[k].nazwisko[dlugosc - 2] = '*';
osoba[k].nazwisko[dlugosc - 1] = '*';
}
}
Hello there, I keep trying to replace 3 last letters of string, but i get this error:
Property or indexer 'string.this[int]' cannot be assigned to -- it is
read only\
I tried to google it, the solution was mostly adding getters and setters (i've yet to learn about it) but it didn't help me. Why can't I modify my string even thought i set everything as public?

Strings are immutable.You can't change a string after you created it.You need to create a new string and assign it back:
osoba[k].nazwisko = osoba[k].nazwisko.Substring(0, dlugosc - 3) + "***";

Strings are immutable in .NET. It's quite unclear what you are trying to achieve but if you want to directly manipulate the contents you could use a char array instead:
public struct Osoba
{
public char[] nazwisko;
[...]
}

Related

if statement does not work in c#

I have a fairly simple task which I want to do but something weird is happening. I just want to check if an element in a string equals zero and then set an integer accordingly.
This is my code
if (ssRow[(bar_position_row - 3)].Equals("0") && ssRow[(bar_position_row + 1)].Equals("0"))
{
back_row = 2;
front_row = 2;
}
else if (!ssRow[(bar_position_row - 3)].Equals("0") && !ssRow[(bar_position_row + 1)].Equals("0"))
{
back_row = 3;
front_row = 1;
}
else if (ssRow[(bar_position_row - 3)].Equals("0") && !ssRow[(bar_position_row + 1)].Equals("0"))
{
back_row = 2;
front_row = 1;
}
When I test my code, in several examples ssRow[(bar_position_row - 3)] and ssRow[(bar_position_row + 1)] equal zero but somehow the ssRow[(bar_position_row - 3)].Equals("0") and ssRow[(bar_position_row + 1)].Equals("0") are both FALSE. Does anyone know what my mistake is?
When you index into a string, what you get back is a char, not another string. You then compare this char to a string ("0"), and understandably get back false.
You should be comparing against '0' (a char), not "0" (a string). And since char is a value type, you can just use the == equality operator. If you had done so in the first place, this would have been a compile time error.
See example:
"abc"[0].Equals("a") //false
"abc"[0].Equals('a') //true
"abc"[0] == 'a' //true
"abc"[0] == "a" //compile-time error, can't compare char with string
I do not know the type of ssRow, if using index access on it does not return an string, then Equals("0") is doing object equality.
To fix it, consider using .ToString() first: ssRow[(bar_position_row - 3)].ToString().Equals("0")

How to reverse string in C# [duplicate]

I didn't get the problem - I was trying to do a simple action:
for(i = x.Length-1, j = 0 ; i >= 0 ; i--, j++)
{
backx[j] = x[i];
}
Both are declared:
String x;
String backx;
What is the problem ? It says the error in the title...
If there is a problem - is there another way to do that?
The result (As the name 'backx' hints) is that backx will contain the string X backwards.
P.S. x is not empty - it contains a substring from another string.
Strings are immutable: you can retrieve the character at a certain position, but you cannot change the character to a new one directly.
Instead you'll have to build a new string with the change. There are several ways to do this, but StringBuilder does the job in a similar fashion to what you already have:
StringBuilder sb = new StringBuilder(backx);
sb[j] = x[i];
backx = sb.ToString();
EDIT: If you take a look at the string public facing API, you'll see this indexer:
public char this[int index] { get; }
This shows that you can "get" a value, but because no "set" is available, you cannot assign values to that indexer.
EDITx2: If you're looking for a way to reverse a string, there are a few different ways, but here's one example with an explanation as to how it works: http://www.dotnetperls.com/reverse-string
String is immutable in .NET - this is why you get the error.
You can get a reverse string with LINQ:
string x = "abcd";
string backx = new string(x.Reverse().ToArray());
Console.WriteLine(backx); // output: "dcba"
String are immuatable. You have convert to Char Array and then you would be able to modify.
Or you can use StringBuilder.
for example
char[] wordArray = word.ToCharArray();
In C# strings are immutable. You cannot "set" Xth character to whatever you want. If yo uwant to construct a new string, or be able to "edit" a string, use i.e. StringBuilder class.
Strings are immutable in C#. You can read more about it here: http://msdn.microsoft.com/en-us/library/362314fe.aspx
Both the variables you have are string while you are treating them as if they were arrays (well, they are). Of course it is a valid statement to access characters from a string through this mechanism, you cannot really assign it that way.
Since you are trying to reverse a string, do take a look at this post. It has lot of information.
public static string ReverseName( string theName)
{
string revName = string.Empty;
foreach (char a in theName)
{
revName = a + revName;
}
return revName;
}
This is simple and does not involve arrays directly.
The code below simply swaps the index of each char in the string which enables you to only have to iterate half way through the original string which is pretty efficient if you're dealing with a lot of characters. The result is the original string reversed. I tested this with a string consisting of 100 characters and it executed in 0.0000021 seconds.
private string ReverseString(string testString)
{
int j = testString.Length - 1;
char[] charArray = new char[testString.Length];
for (int i = 0; i <= j; i++)
{
if (i != j)
{
charArray[i] = testString[j];
charArray[j] = testString[i];
}
j--;
}
return new string(charArray);
}
In case you need to replace e.g. index 2 in string use this (it is ugly, but working and is easily maintainbable)
V1 - you know what you want to put their. Here you saying in pseudocode string[2] = 'R';
row3String.Replace(row3String[2], 'R');
V2 - you need to put their char R or char Y. Here string[2] = 'R' if was 'Y' or if was not stay 'Y' (this one line if needs some form of else)
row3String.Replace(row3String[2], row3String[2].Equals('Y') ? 'R' : 'Y');

Example of Indexer

I'm learning about Indexers and stumble across the explanation and example of the tutorial I'm reading.
It says:
"An indexer allows an object to be indexed such as an array. When you define an indexer for a class, this class behaves similar to a virtual array. You can then access the instance of this class using the array access operator ([ ])"
What I understand with this paragraph is that you can access an instance of that class using the array access operatos.
But what I really dont understand of this explanation is the following:
"Declaration of behavior of an indexer is to some extent similar to a property. similar to the properties, you use get and set accessors for defining an indexer. However, properties return or set a specific data member, whereas indexers returns or sets a particular value from the object instance. In other words, it breaks the instance data into smaller parts and indexes each part, gets or sets each part".
I dont get the "It breaks the instance data into smaller parts and indexes each part"
After this it gives an example of Indexer:
using System;
namespace IndexerApplication
{
class IndexedNames
{
private string[] namelist = new string[size];
static public int size = 10;
public IndexedNames()
{
for (int i = 0; i < size; i++)
namelist[i] = "N. A.";
}
public string this[int index]
{
get
{
string tmp;
if( index >= 0 && index <= size-1 )
{
tmp = namelist[index];
}
else
{
tmp = "";
}
return ( tmp );
}
set
{
if( index >= 0 && index <= size-1 )
{
namelist[index] = value;
}
}
}
static void Main(string[] args)
{
IndexedNames names = new IndexedNames();
names[0] = "Zara";
names[1] = "Riz";
names[2] = "Nuha";
names[3] = "Asif";
names[4] = "Davinder";
names[5] = "Sunil";
names[6] = "Rubic";
for ( int i = 0; i < IndexedNames.size; i++ )
{
Console.WriteLine(names[i]);
}
Console.ReadKey();
}
}
}
Before that paragraph I thought Indexers where a form to index and instance of that class as an array, but that "smaller parts" I really dont understand.
It's really just giving an example of the use of an indexer. Returning an element from the array is, in a way, returning part of the array.
But it needn't be an array. For example, String has an indexer which returns the character at that position, e.g. "test"[0] returns the character in position zero, which is 't'.
Other objects may have other indexers which do other things. For example a DataTable DataRowCollection has an indexer which returns rows by number, and which has an indexer which returns columns by name:
myDataTable.Rows[12]["ID"].Value

changing the value of certain elements of a list

I am looping through a list and would like to add multiple occurrences, should I find them.
so far I have,
public struct optionsSort
{
public string name;
public string date;
public double strike;
public string callPut;
public double size;
public string isin;
}
List<List<optionsSort>> stocks = new List<List<optionsSort>>();
optionsSort tempStock1 = new optionsSort();
List<optionsSort> posCheckOptions = new List<optionsSort>();
then some code, then,
for(int k = 0; k<posCheckOptions.Count; k++)
{
for(int l = 0; l<posCheckOptions[l].Count; l++)
{
if(posCheckOptions[l+1] == null)
{
//finished the iteration
break;
}
else if
(posCheckOptions[k][l + 1].date == posCheckOptions[k][l].date
&& posCheckOptions[k][l + 1].strike == posCheckOptions[k][l].strike
&& posCheckOptions[k][l + 1].callPut == posCheckOptions[k][l].callPut)
{
posCheckOptions[k][l].size = posCheckOptions[k][l].size
+ posCheckOptions[k][l + 1].size;
}
}
}
Basicly, Im looking forward from the start of the list. asking the question, are certain elements of the list at i+1 the same as i, if so, add those elements to i and delete the entire row.
i get this error
"Error 1 Cannot modify the return value of 'System.Collections.Generic.List.this[int]' because it is not a variable C:\Users\WindowsFormsApplication1\WindowsFormsApplication1\ReadCSV.cs 890 25 WindowsFormsApplication1
"
Many Thanks for looking.
I believe your problem is that you are using a mutable struct. Mutable structs are evil.
The simplest solution is to change optionsSort to a class. That should fix the error message.
To explain the error message, when you call posCheckOptions[k][l], since optionsSort is a struct, it returns a copy of the value in the list. When you change size, it will update the copy, but not the one in the list. The copy would then be discarded. The compiler recognizes this and stops you.
I recommend you read up on the differences between reference types and value types.

How should I convert a number with a text suffix to an integer in c#?

What's the cleanest/best way in C# to convert something like 400AMP or 6M to an integer? I won't always know what the suffix is, and I just want whatever it is to go away and leave me with the number.
You could use a regular expression:
Regex reg = new Regex("[0-9]*");
int result = Convert.ToInt32(reg.Match(input));
Okay, here's a long-winded solution which should be reasonably fast. It's similar to Guffa's middle answer, but I've put the conditions inside the body of the loop as I think that's simpler (and allows us to fetch the character just once). It's a matter of personal taste really.
It deliberately doesn't limit the number of digits that it matches, because if the string is an integer which overflows Int32, I think I'd rather see an exception than just a large integer :)
Note that this also handles negative numbers, which I don't think any of the other solutions so far do...
using System;
class Test
{
static void Main()
{
Console.WriteLine(ParseLeadingInt32("-1234AMP"));
Console.WriteLine(ParseLeadingInt32("+1234AMP"));
Console.WriteLine(ParseLeadingInt32("1234AMP"));
Console.WriteLine(ParseLeadingInt32("-1234"));
Console.WriteLine(ParseLeadingInt32("+1234"));
Console.WriteLine(ParseLeadingInt32("1234"));
}
static int ParseLeadingInt32(string text)
{
// Declared before loop because we need the
// final value
int i;
for (i=0; i < text.Length; i++)
{
char c = text[i];
if (i==0 && (c=='-' || c=='+'))
{
continue;
}
if (char.IsDigit(c))
{
continue;
}
break;
}
return int.Parse(text.Substring(0, i));
}
}
It's possibly not the cleanest method, but it's reasonably simple (a one liner) and I would imagine faster than a regex (uncompiled, for sure).
var str = "400AMP";
var num = Convert.ToInt32(str.Substring(0, str.ToCharArray().TakeWhile(
c => char.IsDigit(c)).Count()));
Or as an extension method:
public static int GetInteger(this string value)
{
return Convert.ToInt32(str.Substring(0, str.ToCharArray().TakeWhile(
c => char.IsDigit(c)).Count()));
}
Equivalently, you could construct the numeric string from the result of the TakeWhile function, as such:
public static int GetInteger(this string value)
{
return new string(str.ToCharArray().TakeWhile(
c => char.IsNumber(c)).ToArray());
}
Haven't benchmarked them, so I wouldn't know which is quicker (though I'd very much suspect the first). If you wanted to get better performance, you would just convert the LINQ (extension method calls on enumerables) to a for loop.
Hope that helps.
There are several options...
Like using a regular expression:
int result = int.Parse(Regex.Match(input, #"^\d+").Groups[0].Value);
Among the fastest; simply looping to find digits:
int i = 0;
while (i < input.Length && Char.IsDigit(input, i)) i++;
int result = int.Parse(input.Substring(0, i));
Use LastIndexOfAny to find the last digit:
int i = input.LastIndexOfAny("0123456789".ToCharArray()) + 1;
int result = int.Parse(input.Substring(0, i));
(Note: breaks with strings that has digits after the suffix, like "123asdf123".)
Probably fastest; parse it yourself:
int i = 0;
int result = 0;
while (i < input.Length) {
char c = input[i];
if (!Char.IsDigit(c)) break;
result *= 10;
result += c - '0';
i++;
}
If all you want to do is remove an unknown postfix from what would otherwise be an int, here is how I would do it:
I like a utility static method I call IsInt(string possibleInt) which will, as the name implies, return True if the string will parse into an int. You could write this same static method into your utility class (if it's not there already) and try:
`string foo = "12345SomePostFix";
while (!Tools.ToolBox.IsInt(foo))
{
foo = foo.Remove(foo.Length - 1);
}
int fooInt = int.Parse(foo);`

Categories