Changing the Value of an Element in a List of Structs

Changing the value of an element in a list of structs


MyList[1] = new MyStruct("bob");

structs in C# should almost always be designed to be immutable (that is, have no way to change their internal state once they have been created).

In your case, what you want to do is to replace the entire struct in specified array index, not to try to change just a single property or field.

Changing the value of an element in a struct

For starters the order of evaluation of arguments in a function call is unspecified.

So in this call

 printf("%d %d\n",strleng(A),A.length);

the evaluation of the argument expression A.length can occur before calling the function strleng or vice versa.

Secondly the function strleng declared like

int strleng(stru A);

deals with a copy of the original object A declared in main and used as an argument. So changing the copy does not influence on the original object.

You need to pass the object by reference through a pointer to it.

unsigned int strleng( stru *A){
unsigned int i=0;
while(A->string[i]!='\0'){
i++;
}
A->length =i;
return i;
}

and in main you should write for example

unsigned int n = strleng( &A );
printf("%u %u\n", n, A.length );

Pay attention to that on one hand, the data member length is declared as having the type unsigned int

unsigned int length;

On the other hand, within your original function strleng you are using an object of the signed type int and the function return type is also int. The function should use at least the same type unsigned int instead of the type int.

c# modifying structs in a List T

Looking at the for-loop approach, the reason (and solution) for this is given in the documentation for the compilation error:

An attempt was made to modify a value
type that is produced as the result of
an intermediate expression but is not
stored in a variable. This error can
occur when you attempt to directly
modify a struct in a generic
collection.

To modify the struct, first assign it
to a local variable, modify the
variable, then assign the variable
back to the item in the collection.

So, in your for-loop, change the following lines:

catSlots[s].subItems.Clear();
catSlots[s].subItems = sortedSubTemp; // ERROR: see below

...into:

slotInfo tempSlot = gAllCats[0].items[s];
tempSlot.subItems = sortedSubTemp;
gAllCats[0].items[s] = tempSlot;

I removed the call to the Clear method, since I don't think it adds anything.

How to update variable in single element of struct list

This is a perfect example why using mutable strcuts is pure evil. Basically whenever your values might change you should consider to use a class instead of struct.

As of MSDN:

X DO NOT define mutable value types

The problem you got arises from the fact that structs are value-types which get copied whenever passed to or returned from a member - in your case List.Find. Thus any updates to the instance you recieved via Find won´t be reflected to the instance within the list. You could strangly bypass this by using an array instead of a list, but that´s also a bad idea as it hides the actual problem.

How can I change the element in an array of struct

Pair is a struct, so value semantics apply. This means that here, you made a copy of each item in data.pairs:

var pair = data?.pairs[index]

And you are changing the copies, not the originals.

One way to solve this is to assign the changed copies back to data.pairs:

if /* some test */ {
print ("Found match")
pair?.setValue(Point(1,2))
data?.pairs[index] = pair // here!
}

Or, don't make a copy in the first place:

if /* some test */ {
print ("Found match")
data?.pairs[index].setValue(Point(1,2))
}

Or, make Pair a class, so reference semantics apply, and you won't be making copies.

Search for and replace a value in a vector of structs

To change the elements in the vector, you need to take a reference in the range-for loop:

for (auto &e : data)

Otherwise you are making a copy, which doesn't change the original elements.

The 4th parameter of replace_if needs to take an info object, not just the new_name value.

Instead of replace_if, the appropriate algorithm to use here would be for_each, which modifies the info objects as needed:

std::for_each(data.begin(), data.end(), 
[old_name, new_name](info &i) {
if (i.name == old_name)
i.name = new_name;
});

However, in this case, the range-for loop is probably less code, and easier to read and write.

Also, please avoid using namespace std;, it's bad practice.



Related Topics



Leave a reply



Submit