Why Removing item from list in this way is impossible? - list

I have a problem that as i try to remove item from any list in following way i am unable to do that ... why is that so the error is "use of unassigned local variable" where is it is assigned as shown below:
public void RemoveFrmList(int ProdId)
{
int _index;
foreach (Products item in BoughtItems)
{
if (item.ProductID == ProdId)
{
_index = BoughtItems.IndexOf(item);
}
}
BoughtItems.RemoveAt(_index);
}
what can be done to remove this error?

the code inside the if statement does not necessarily occur. Initialize _index to -1 or some "not found" indicating value and the error should go away.

What is BoughtItems ? If it's List<T> just use RemoveAll
public void RemoveFrmList(int ProdId)
{
BoughtItems.RemoveAll( item => item.ProductID == ProdId );
}
Slightly offtopic but why is RemoveFrmLis missing the o? It just hurts readability. Use the full word.

_index is unassigned until you go in the loop. But if BoughtItems has no Product items, you will have a unnassigned variable _index. Or maybe you will never get an item with item.ProductID == ProdID.
So in other words:
int _index;
foreach (Products item in BoughtItems)
{
//Code here is not executed during runtime for reasons stated above.
}
BoughtItems.RemoveAt(_index); //error here because _index was not assigned!
To fix it, you could do something like
int _index = -1;
foreach (...)
{
//...
}
if (_index != -1){
BoughtItems.RemoveAt(_index);
}
else
{
//handle case if needed
}

Related

how to check if personID is in my_customers (see my example)

In C++, the interface for this file says
*If no soup left returns OUT_OF_SOUP
* If personID not found in my_customers AND numbBowlsSoupLeft>0 then give this person a bowl of soup (return BOWL_OF_SOUP)
* and record it by creating new customer struct using personID, numbBowlsSoup=1 and adding this struct to my_customers, be sure to decrement numbBowlsSoupLeft.
for my implementation, I'm trying to put
int Soupline::getSoup(int personID) {
if (numBowlsSoupLeft == 0) {
return OUT_OF_SOUP;
}
if (!(personID : my_customers) && numbBowlsSoupLeft > 0) {
}
But that second if statement is giving me syntax errros, I just want to know how to check to see if the personID is IN my_customers?
my_customers was created in the soupline interface using:
std::vector<customer> my_customers; // keeps track of customers
First you want to use find() to search a vector.
Second, please handle the case if numbBowlsSoupLeft < 0, because that can be a huge source of problem.
Third, your syntax error is the (personID : my_customers), the : is for iteration.
int Soupline::getSoup(int personID) {
if (numBowlsSoupLeft <= 0) { // handles negative numBowlsSoupLeft
return OUT_OF_SOUP;
}
bool found_customer = false;
for (auto c : my_customers) {
if (personID == c.person_id()) { // This is my guess on how the id is stored in customer class
// Logic to process soup for customer
found_customer = true;
break;
}
}
if (!found_customer) {
// Logic to process non-customer asking for soup?
}
}
Sorry i dunno what is the return integer is supposed to be, so it is not defined in my code example.

How to protect app against read access violation while accessing to pointer's value?

I've created some chain-like structure, where one object has pointers to the next and previous object of a chain. The code below loops through entire chain, looks for value specified in arguments and removes matching element (if exists).
void List::removeElementByValue(int value)
{
ListMember* nextElem = this->firstValue;
while (nextElem) {
if (nextElem == NULL || nextElem == nullptr) {
break;
}
if (nextElem->value == value) {
if (nextElem->prevValue)
(nextElem->prevValue)->nextValue = nextElem->nextValue;
if (nextElem->nextValue)
(nextElem->nextValue)->prevValue = nextElem->prevValue;
delete nextElem;
this->count--;
return;
}
nextElem = nextElem->prevValue;
}
}
The problem is: I'm getting this error when I'm trying to remove non-existent value from chain.
Exception thrown: read access violation. nextElem was 0xCDCDCDCD.
Function should do nothing in that case. It happens at this line:
if (nextElem->value == value) {
As you see, I've used multiple ways to check if nextElem is correct, but I'm still getting this error. Any ways I can prevent that?
if (nextElem == NULL || nextElem == nullptr)
This will always be false when while (nextElem) is true.
nextElem = nextElem->prevValue;
This needs to use nextValue instead of prevValue.
But, most importantly, you are not updating this->firstValue if the value is found in the first element of the list, so you end up deleting the firstValue and leave it pointing at invalid memory.
Try this instead:
void List::removeElementByValue(int value)
{
ListMember* elem = this->firstValue;
while (elem) {
if (elem->value == value) {
if (elem->prevValue)
elem->prevValue->nextValue = elem->nextValue;
if (elem->nextValue)
elem->nextValue->prevValue = elem->prevValue;
// ADD THIS!!!
if (elem == this->firstValue)
this->firstValue = elem->nextValue;
delete elem;
this->count--;
return;
}
elem = elem->nextValue; // NOT prevValue!
}
}
A better solution is to not implement a linked list manually in the first place. Use the standard std::list container instead, let it do all of the hard hard for you.
#include <list>
class List
{
private:
std::list<int> values;
...
};
...
#include <algorithm>
void List::removeElementByValue(int value)
{
auto iter = std::find(values.begin(), values.end(), value);
if (iter != values.end())
values.erase(iter);
}

is there a better way to make this software flow

I have several functions that try and evaluate some data. Each function returns a 1 if it can successfully evaluate the data or 0 if it can not. The functions are called one after the other but execution should stop if one returns a value of 1.
Example functions look like so:
int function1(std::string &data)
{
// do something
if (success)
{
return 1;
}
return 0;
}
int function2(std::string &data)
{
// do something
if (success)
{
return 1;
}
return 0;
}
... more functions ...
How would be the clearest way to organise this flow? I know I can use if statements as such:
void doSomething(void)
{
if (function1(data))
{
return;
}
if (function2(data))
{
return;
}
... more if's ...
}
But this seems long winded and has a huge number of if's that need typing. Another choice I thought of is to call the next function from the return 0 of the function like so
int function1(std::string &data)
{
// do something
if (success)
{
return 1;
}
return function2(data);
}
int function2(std::string &data)
{
// do something
if (success)
{
return 1;
}
return function3(data);
}
... more functions ...
Making calling cleaner because you only need to call function1() to evaluate as far as you need to but seems to make the code harder to maintain. If another check need to be inserted into the middle of the flow, or the order of the calls changes, then all of the functions after the new one will need to be changed to account for it.
Am I missing some smart clear c++ way of achieving this kind of program flow or is one of these methods best. I am leaning towards the if method at the moment but I feel like I am missing something.
void doSomething() {
function1(data) || function2(data) /* || ... more function calls ... */;
}
Logical-or || operator happens to have the properties you need - evaluated left to right and stops as soon as one operand is true.
I think you can make a vector of lambdas where each lambdas contains specific process on how you evaluate your data. Something like this.
std::vector<std::function<bool(std::string&)> listCheckers;
listCheckers.push_back([](std::string& p_data) -> bool { return function1(p_data); });
listCheckers.push_back([](std::string& p_data) -> bool { return function2(p_data); });
listCheckers.push_back([](std::string& p_data) -> bool { return function3(p_data); });
//...and so on...
//-----------------------------
std::string theData = "Hello I'm a Data";
//evaluate all data
bool bSuccess = false;
for(fnChecker : listCheckers){
if(fnChecker(theData)) {
bSuccess = true;
break;
}
}
if(bSuccess ) { cout << "A function has evaluated the data successfully." << endl; }
You can modify the list however you like at runtime by: external objects, config settings from file, etc...

Stuck with code using if statements

This might be a non-sense question, but i'm kind of stuck so I was wondering if someone can help. I have the following code:
bool while_condition=false;
do{
if(/*condition*/){
//code
}
else if(/*condition*/){
//code
}
else if(/*condition*/){
//code
}
...//some more else if
else{
//code
}
check_for_do_while_loop(while_condition, /*other parameters*/);
}while(while_condition);
the various if and else if exclude with each other but each have other if inside; if a certain condition is met (which can't be specified in a single if statement), then the code return a value and the do while loop is ended. But if, after entering a single else if, the conditions inside aren't met the code exit without actually doing nothing, and the while loop restart the whole.
I want the program to remember where he entered and avoid that part of the code, i.e. to avoid that specific else if he entered without any result, so he can try entering another else if. I thought about associating a boolean to the statements but I'm not quite sure on how to do it. Is there a way which allows me not to modify the code structure too much?
To give an idea of one way of approaching this that avoid loads of variables, here is an outline of how you might data-drive a solution.
class TestItem
{
public:
typedef bool (*TestFuncDef)(const state_type& state_to_test, std::shared_ptr<result_type>& result_ptr);
TestItem(TestFuncDef test_fn_parm)
{
test_fn = test_fn_parm;
already_invoked = false;
}
bool Invoke(const state_type& state_to_test, std::shared_ptr<result_type>& result_ptr)
{
already_invoked = true;
return test_fn(state_to_test, result_ptr);
}
bool AlreadyInvoked() const {return already_invoked; }
private:
TestFuncDef test_fn;
bool already_invoked;
};
std::shared_ptr<result_type> RunTest(std::list<TestItem>& test_item_list, state_type& state_to_test)
{
for(;;) {
bool made_a_test = false;
for (TestItem& item : test_item_list) {
std::shared_ptr<result_type> result_ptr;
if (!item.AlreadyInvoked()) {
made_a_test = true;
if (item.Invoke(state_to_test, result_ptr)) {
return result_ptr;
}
else
continue;
}
}
if (!made_a_test)
throw appropriate_exception("No conditions were matched");
}
}
This is not supposed to be a full solution to your problem but suggests another way of approaching it.
The important step not documented here is to build up the std::list of TestItems to be passed to RunTest. Code to do so might look like this
std::list<TestItem> test_item_list;
test_item_list.push_back(TestItem(ConditionFn1));
test_item_list.push_back(TestItem(ConditionFn2));
The definition of ConditionFn1 might look something like
bool ConditionFn1(const state_type& state_to_test, std::shared_ptr<result_type>& result_ptr)
{
// Do some work
if (....)
return false;
else {
result_ptr.reset(new result_type(some_args));
return true;
}
}

Dlist: using stableLinearRemove in a foreach loop

I've written the following code but it doesn't give the correct result (for instance if you enter [-1,-1], it returns [-1,-1,-1].
import std.stdio, std.range, std.container, std.algorithm;
DList!T strandSort(T)(DList!T list) {
static DList!T merge(DList!T left, DList!T right) {
DList!T res;
while (!left.empty && !right.empty) {
if (left.front <= right.front) {
res.insertBack(left.front);
left.removeFront();
} else {
res.insertBack(right.front);
right.removeFront();
}
}
res.insertBack(left[]);
res.insertBack(right[]);
return res;
}
DList!T result, sorted;
while (!list.empty) {
sorted.clear();
sorted.insertBack(list.front);
list.removeFront();
foreach (item; list) {
if (sorted.back <= item) {
sorted.insertBack(item);
list.stableLinearRemove(list[].find(item).take(1)));
}
}
result = merge(sorted, result);
}
return result;
}
void main() {
auto lst = DList!int([-1,-1]);
foreach (e; strandSort(lst))
writef("%d ", e);
}
Sometimes, the stableLinearRemove doesn't remove the item from the list. The question is, is it a bug in my code, or in Phobos?
See also the discusion on Rosettacode.org
Edit: I suspect it's caused by removeFront. It doesn't set the prev node pointer of the second node to null when the first node is removed. When the item to be removed from the list by linearRemove happens to be the first node, it won't be removed. The remove function checks "before" and "after" nodes and the "before" is still set. If I write it like this, it does work:
if (sorted.back <= item) {
sorted.insertBack(item);
if (list.front == item)
list.removeFront();
else
list.stableLinearRemove(list[].find(item).take(1)));
}
I don't think it's a bug in Phobos, but rather a gotcha. You shouldn't rely on linearRemove to remove an element if it might be the first in the list. Check for that first and use removeFront. Is also more efficient.
In the case above, a better solution would be to copy the list:
DList!T result, sorted, leftover;
while (!list.empty) {
leftover.clear();
sorted.clear();
sorted.insertBack(list.front);
list.removeFront();
foreach (item; list) {
if (sorted.back <= item)
sorted.insertBack(item);
else
leftover.insertBack(item);
}
result = merge(sorted, result);
list = leftover;
}
You are right, it is definitely a bug in removeFront.
Though I might point out that removing iterated elements via foreach is not going to be efficient even if it is supposed to be valid. you need a handle to the range. consider:
auto rng = list[];
while(!rng.empty) {
auto item = rng.front;
if(sorted.back <= item) {
sorted.insertBack(item);
auto rng2 = rng.save();
rng.popFront();
list.stableLinearRemove(rng2.take(1)); // O(1) removal!
}else{
rng.popFront();
}
}
Ah, well. Above probably doesn't work in light of the bug.