This code must insert character 'p' before character 'q' how many times 'q' appear in list.
When I call function insert_before (insert_before('q','p') ) my program freezes. I don't write all the code here. The rest of the program works fine.
struct node
{
char character;
node* next;
};
node *fisrt , *end;
void insert_before(char val_search,char val_inserted)
{
node *c,*a;
c=first;
do {
if (c->next->character==val_search)
{
a= new node ;
a->character=val_inserted ;
a->next=c->next;
c->next=a;
c=c->next;
}
else
c=c->next;
} while (c) ;
}
When you find the value p, you insert a new entry before the found entry.
This means, next time you will find the same entry again and insert another new entry before the found entry
+---+ +---+
| x |->| p |
+---+ +---+
c
will become
+---+ +---+ +---+
| x |->| q |->| p |
+---+ +---+ +---+
c
and then it will become
+---+ +---+ +---+ +---+
| x |->| q |->| q |->| p |
+---+ +---+ +---+ +---+
c
and so on.
Because this will never end (until you run out of memory), the program appears to freeze.
The problems
Let's suppose that you have a list with a unique element 'q' in it: first and last would both point to that single node. And the next pointer of the node would be nullptr.
When you execute insert_before() you start with c=first. So c points to this unique node which has next being nullptr. Unfortunately this instruction: if (c->next->character==val_search) would dereference the nullptr. This is undefined behavior and might cause the symptoms that you describe.
If your searched value is not the first element, your code would work in principle. Unfortunately, after having inserted the element, you continue to loop: you'd then loop at the new element, and the condition would be true again, so that you will insert again a new element and so on, endlessly looping until your list exhausts all the memory. This also would cause freeze.
By the way, do you really want to insert 'p' before all the 'q's in the list ?
First correction
Just correct the loop, being more careful:
void insert_before(char val_search,char val_inserted)
{
node *c,*a;
for (c=first; c && c->next; c=c->next) {
if (c->next->character==val_search)
{
a= new node ;
a->character=val_inserted ;
a->next=c->next;
c->next=a;
c=a;
}
}
}
Note that this code, exactly as your code, doesn't handle properly the insertion in front of the list.
Second fix:
To be able to insert in front, you need something like this:
void insert_before(char val_search,char val_inserted)
{
node *c,*a, *prev=nullptr;
for (c=first; c ; prev=c, c=c->next) {
if (c->character==val_search)
{
a= new node ;
a->character=val_inserted ;
a->next=c;
if (prev)
prev->next=a;
else first=a;
}
}
}
Live demo
Inside if {}, change c=c->next to c=a->next.
Related
This may not be elegant. Chiefly because I am relatively new to C++, but this little program I am putting together is stumbling here.
I don't get it. Have I misunderstood arrays? The edited code is:
int diceArray [6][3][1] = {};
...
}else if (y >= xSuccess || x >= xSuccess){
// from here...
diceArray[2][1][0] = diceArray[2][1][0] + 1;
diceArray[2][1][1] = diceArray[2][1][1] + 1;
// ...to here, diceArray[2][2][0] increases by 1. I am not referencing that part of the array at all. Or am I?
}
By using comments I tracked the culprit down to the second expression. If I comment out the first one diceArray[2][2][0] does not change.
Why is diceArray[2][1][1] = diceArray[2][1][1] + 1 causing diceArray[2][2][0] to increment?
I tried..
c = diceArray[2][1][1] + 1;
diceArray[2][1][1] = c;
..as a workaround but it was just the same. It increased diceArray[2][2][0] by one.
You are indexing out of bounds. If I declare such an array
int data [3];
Then the valid indices are
data[0]
data[1]
data[2]
The analog to this is that you declare
int diceArray [6][3][1]
^
But then try to assign to
diceArray[2][1][0]
^
diceArray[2][1][1] // This is out of range
^
Since you are assigning out of range, due to pointer arithmetic you are actually assigning to the next dimension due to striding, etc.
The variable is declared as:
int diceArray [6][3][1] = {};
This is how it looks like in memory:
+---+ -.
| | <- diceArray[0][0] \
+---+ \
| | <- diceArray[0][1] > diceArray[0]
+---+ /
| | <- diceArray[0][2] /
+---+ -'
| | <- diceArray[1][0] \
+---+ \
| | <- diceArray[1][1] > diceArray[1]
+---+ /
| | <- diceArray[1][2] /
+---+ -'
. . .
. . .
. . .
+---+ -.
| | <- diceArray[5][0] \
+---+ \
| | <- diceArray[5][1] > diceArray[5]
+---+ /
| | <- diceArray[5][2] /
+---+ -'
The innermost component of diceArray is an array of size 1.
C/C++ arrays are always indexed starting from 0 and that means the only valid index in and array of size 1 is 0.
During the compilation, a reference to diceArray[x][y][z] is converted using pointer arithmetic to offset x*3*1+y*1+z (int values) using the memory address of diceArray as base.
The code:
diceArray[2][1][1] = diceArray[2][1][1] + 1;
operates on offset 8 (=2*3*1+1*1+1) inside diceArray. The same offset is computed using diceArray[2][2][0], which is a legal access inside the array.
The modern compilers are usually able to detect this kind of errors and warn you on the compilation.
This question already has answers here:
C++ Swapping Pointers
(7 answers)
Closed 6 years ago.
Here I have two swap functions
void kswap(int* a, int* b)
{
int* temp = a;
a = b;
b = temp;
}
void kswap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
The value only changed inside of the first function,
and the second function change the value permanently..
Can anyone tell me the different between two functions?
I thought as both functions take pointer type through parameter, the value would be changed through both functions..
In function swap, a and b are int *, aka integer pointers, that means
they contain address of an integer in memory. As seen in diagram below:
Memory
==================
+----------------+
| |
+------> | num1 = 5 |
| | |
| +----> | num2 = 6 |
| | | |
| | | |
| | |================|
| | | Function swap |
| | | |
+-(------------ a |
| | |
+------------ b |
| |
+----------------+
Here,
`*a` : should be read as : `value at address contined in a`
`*b` : should be read as : `value at address contined in b`
In first example
In first kswap, after executing below statements,
int* temp = a; /* A pointer which points to same place as 'a' */
a = b; /* 'a' will now point to where 'b' is pointing */
b = temp; /* 'b' will now point to where 'temp' is pointing
* that means where 'a' was previously pointing */
the result is:
Memory
==================
+----------------+
| |
+------> | num1 = 5 | <------+
| | | |
| +----> | num2 = 6 | |
| | | | |
| | | | |
| | |================| |
| | | Function swap | |
| | | | |
+ +------------ a | |
| | | |
+-------------- b | |
| | |
| temp -----------------+
+----------------+
Note that, neither *a or *b is assigned any value, so neither of:
`*a` : that is : `value at address contined in a`
`*b` : that is : `value at address contined in b`
are changed.
So as seen in above picture, num1 is still 5, and num2 is still 6.
Only thing that has happended is that a is pointing to num2, and b is
pointing to num1.
In second example
In second kswap, after executing below statements,
int temp = *a; /* An int variable which will contain the same value as the
* value at adress contained in a */
*a = *b; /* value at address contained in 'a' will be equal to value
* at address contained in 'b' */
*b = temp; /* value at address contained in 'b' will be equal to value
* contained in 'temp' */
the result is:
Memory
==================
+----------------+
| |
+------> | num1 = 6 |
| | |
| +----> | num2 = 5 |
| | | |
| | | |
| | |================|
| | | Function swap |
| | | |
+-(------------ a |
| | |
+------------ b |
| |
| temp = 5 |
+----------------+
Note that, both *a or *b are assigned new value, so both:
`*a` : that is : `value at address contained in a`
`*b` : that is : `value at address contained in b`
are changed.
And as seen in above picture, num1 is now 6, and num2 is now 5. So in the second example, values of variables num1 and num2 are permanently changed.
Assume each function is called as:
void f()
{
int x = 101, y = 999;
kswap(&x, &y);
}
Remember that in C++ arguments are passed by value, so kswap receives the values of the addresses where x, y reside. The rest of the answer is inlined in the code comments below.
The kswap that works.
void kswap(int* a, int* b)
{
int temp = *a; // `a` is the address of `int x`
// `*a` is the integer value at address `a`
// i.e. the value of `x` so temp == 101 now
*a = *b; // same as above `*b` is the value of `y` i.e. 999
// now this integer value is copied to the address where `a` points
// effectively overwriting the old `x` value `101` with `999`
*b = temp; // finally, this copies the value in `temp` i.e. 101
// to the address where `b` points and overwrites
// the old `y` value `999`, which completes the swap
}
The kswap which does not work.
void kswap(int* a, int* b)
{
int* temp = a; // this copies `a` i.e. the address of `x`
// to local variable `temp`
a = b; // this copies `b` to `a`
// since arguments `a` and `b` are pointers and passed by value
// this only modifies the value of variable `a`
// it does **not** change `x` or its address in any way
b = temp; // this copies 'temp' to 'b', same comments as above
// now 'a' holds the address of `y` and `b` holds the address
// of `x` but **neither** 'x' nor 'y' values have been modified
// and pointer variables `a`, `b` go out of scope as soon as
// the function returns, so it's all a big no-op in the end
}
The first function swaps the addresses, but not outside the scope of the function.
The second function swaps the values, and outside the function's scope.
Adding the * to the name, means you want the value, not where it's at.
I am trying to understand the concept of linked lists. So far this is what I know and where I'm having problems to understand.
//create node
struct list
{
int id; //member var
list* next; //pointer to link next list item
}
//int main()
//create list head and set it to NULL
list* head = NULL;
//instantiate list node
list* newList = new list;
//insert a list
newList->id = 20;
newList->next = NULL;
This I do not really understand what's going on.
newList->next = head;
head = newList;
NOTE: The memory "locations" I will reference in this answer are there purely for example are not meant to mimic the actual location these pointers might or might not ever point to.
Draw these relationships out on paper to visualize the results. Let's break it down by lines.
list *head = NULL;
And here is our visualization:
*head (0x00)
+-----------+
| |
| NULL |
| |
+-----------+
Now, we follow these next lines:
list *newList = new list;
newList->id = 20;
newList->next = NULL;
And that visualization:
*head (0x00) *newList (0x3a)
+-----------+ +----+------+
| | | id | next |
| NULL | +----+------+
| | | 20 | NULL |
+-----------+ +----+------+
And finally we end with your last bit:
newList->next = head;
And that alters the visualization thusly (reordered for clarity):
*newList (0x3a) +->*head (0x00)
+----+------+ | +-----------+
| id | next | | | |
+----+------+ | | NULL |
| 20 | head------+ | |
+----+------+ +-----------+
This has created the "link" that gives a LinkedList it's name. You link nodes together by some form of a reference. So what you've done is created a "head" or beginning of the list, and then you've created a secondary node in the list and placed it (logically) before head. Normally you'd then reassign your reference to newList to head since it's the new beginning of the list.
The next step would likely be (and I'm sure this what you meant with the erroneous bit that I ask about at the end of this question):
head = newList;
Which now changes the visualization to this:
*head (0x3a) +---> (0x00)
+----+------+ | +-----------+
| id | next | | | |
+----+------+ | | NULL |
| 20 | 0x00----+ | |
+----+------+ +-----------+
Also, what about the following line?
head = n; // What is 'n'? Where did you get it from? It doesn't appear anywhere else in your sample
EDIT
I altered the visualization to more accurately reflect what would be realistic. I wasn't paying attention to what I was doing when I posted the original answer so many thanks to José and his comment for bringing it to my attention the visualization was inaccurate.
In addition to altering the visuals I added a bit more information and wanted to take it a step further in saying that here's how you would use this linked list to loop over it's records.
list *node = head;
while (node != NULL) {
std::cout << "The id is " << node->id << std::endl;
node = node->next;
}
newList->next = head;
head = newList;
You start out with head set to NULL.
Then, you create a new node and let its next point to head, which is NULL.
Then, you set head to be the new node. Now, head points to a list that has one item in it.
Can somebody explain this to me:
(((((*(parent))->leaves))[7])->zone_id)
pointers to pointers are really confusing to me. This is the expression I got from the watch in debug mode. I am trying to access to the string zone_id inside the last element of tree (with 10 elements, each element for different number 0-9).
EDIT: this is the whole search function, hope it is enough to understand:
string Tree::search(string str, node** parent, int num) {
int value;
if (num < str.length()) {
value = boost::lexical_cast<int> (str.substr(num, 1));
if ((*parent)->leaves[value] != NULL && num != str.length() -1) {
search (str, &((*parent)->leaves[value]), num+1);
} else if (num == str.length() -1) {
if ( (*(parent)->leaves)[value]->zone_id.empty() )
cout<<"Yep.";
else
return (string) "No_results.";
}
}
}
and structure:
struct node {
string zone_id;
node* leaves [10];
};
Well let's get rid of some brackets to simplify it a bit:
(*parent)->leaves[7]->zone_id
Now it's much easier to understand. We are dereferencing parent (*parent) which gives us a pointer to some object that has an array member called leaves. So we access the element of that array with index 7, which gives us another pointer, this time pointing to an object that has a member called zone_id. We then access that zone_id member.
This is all assuming there's no operator overloading involved.
Diagrammatically (an arrow is "points to"):
________ _________ ___________ ___________
| parent |-->| *parent |-->| struct: | ,-->| struct: |
|________| |_________| | leaves[0] | | | zone_id |
| leaves[1] | | | ... |
| leaves[2] | |
| leaves[3] | |
| leaves[4] | |
| leaves[5] | |
| leaves[6] | |
| leaves[7] | --'
| leaves[8] |
| ... |
Removing the parenthesis makes it actually easier to read, in my mind:
(*parent)->leaves[7]->zone_id
So, we have a pointer to a pointer of leaves. (*parent) makes a dereference to that pointer (so fetches what it the pointer points at). So now we have a pointer to leaves, which is an array of 10, so we use element 7, and the pointer here is used to fetch the zone_id.
It does get a bit complicated, but this is far from the most complicated structure I have seen. If it helps you, you could break it down:
Parent *this_parent = *parent;
Leave *leaf = this_parent->leaves[7];
... use leaf->zone_id;
(
(
(
(
(
*(parent)
)
->leaves
)
)
[7]
)
->zone_id
)
dereference parent
access the leaves member
index the 7th element
access the zone_id member.
This is a program trying to make a linked list.
#include <iostream>
using namespace std;
struct node {
char name[20];
int age;
int height;
node* next; // Pointer to the next node
};
node* startPTR = NULL; // Start Pointer (root)
// This pointer permanantly points to the start of the list
// Initially there are no nodes
void addNode_AT_END(); // prototype for the function that 'adds nodes at the end'
int main() {
do {
addNode_AT_END();
cout << "Add more ?";
char ch;
cin >> ch;
} while( ch == 'y');
}
void addNode_AT_END() {
node *temp1;
node *temp2;
temp1 = new node; // We declare space for a pointer item and assign a temporary pointer to it
//*temp1 is the node that it points to
cout << "Enter the name : ";
cin >> temp1->name;
cout << endl << "Enter the age : ";
cin >> temp1->age;
cout << endl << "Enter height : ";
cin >> temp1->height;
temp1->next = NULL; // indicates that this node when inserted in the list will be the last node
if( startPTR == NULL) {
startPTR = temp1; // In the empty list last node will be the first node
} else {
temp2 = startPTR;
while( temp2->next != NULL )
temp2 = temp2->next;
temp2->next = temp1;
}
}
From this yet to be completed program this is what i understand :
If the figure after the second call to the function addNode_AT_END is true, then what does temp2->next in the statement while( temp2->next != NULL ) contain ?
It contains NULL, and that is because of this line:
temp1->next = NULL;
Every new node has nextpointer which you make NULL by doing the above step, and the new node is appended at the end of the list, as a result of which, the end of the list is alwaysNULL. The while loop is traversing to the end of the list, and while(temp2->next != NULL) sets the condition which says until next of temp2 becomes NULL, do temp2 = temp2->next.
Your diagrams are incorrect. start = temp2 does means that start and temp2 pointers both point to the same node. Your diagram shows the next field of the temp2 pointer holds the address of start . Also after doing start->next = temp1 does not mean that if you get some new node value in temp1 (in the next function call), the start->next will still keep pointing to the new value just allocated in temp1. It will hold the old value that was in before you overwrote it with the new one. start->next = temp1 simply copies the value in temp1 ie. an address to the variable (pointer variable) the next component of the node pointed by start which is start->next . After that there is no connection between start and temp1.
In linked list context "temp1 ----> temp2" means the next field of the node whose address is stored in temp1, holds the address of the node with an address which was held or is held by temp2 . Now after you change the value of the pointer variable temp2 does not change the next field of the node held at address stored in temp1. temp1->next still contains the value which it stored before.
The next links does not point to some variable name, that is, start->next = temp will not make start node's next node always pointing to the whatever node temp1 contains, but it start->next will contain the address which temp1 stored at the time of the assignment.
note that by saying "start is pointing to temp1" means that the address
while (temp2->next != NULL)
temp2 = temp2->next;
will break when temp2->next = NULL which means that temp2 points to the last node of the list. At this point temp2->next = temp1 links the newly allocated node after the node currently pointed by temp2. Which is simply adds the new node at the end.
At the end of the above while loop
temp2
|
V
(start) ----> (n1) ----> (n2) ----> (n3) . . . (n(n-1)) ----> (nn) ----> NULL
temp2->next = temp1 makes
temp2
|
V
(start) ----> (n1) ----> (n2) ----> (n3) . . . (n(n-1)) ----> (nn) ----> (temp1)--->NULL
because temp2 holds the address of (nn) therefore linking the new node to the next node of the last node.
UPDATE
First time:
start = NULL
a new address is allocated and the address stored into temp1 pointer. Also temp->next = NULL
if condition becomes true and temp1 is assigned to start
start = temp1
List state
start = addr1;
|
V
(addr1) ----> (NULL)
Second time:
a new node is allocated and the address of the new node is stored into `temp1`. Let this address be `addr2`. Now `temp1` contains the value `addr2`
start is NOT NULL, as start has addr1 in it from the last call.So the else part is true and we get the address of the start node `addr1` into temp2.
temp2 = start;
which means temp2 now points to `addr1`
while loop is encountered. The first iteration the condition `temp2->next != NULL` is FALSE. This is because `temp2` points to `addr1` and the next pointer field of `addr1` has NULL from the last time the function is called. Therefore the while loop terminates.
The next statement does `temp2->next = temp1` . `temp2` points to `addr1` address, and the address of the newly allocated node `addr2` contained in `temp1` is assigned into the next field of the node whose address is stored into `temp2`. Which actually assigns the address `addr2` to the next field of the node identified by the address `addr1`.
temp1 = addr2 after allocation
start = addr1;
|
V
(addr1) ----> (NULL) at begining
^
|
temp2
after temp2->next = temp1
start = addr1;
|
V
(addr1) ----> (addr2) ----> (NULL) at end
^
|
temp2
Third time:
temp1 = addr3 new node address allocated
start = addr1;
|
V
(addr1) ----> (addr2) ----> (NULL) at start
^
|
temp2
start = addr1;
|
V
(addr1) ----> (addr2) ----> (NULL) next iteration after temp2=temp2->next
^
|
temp2
we can see temp2->next = NULL and while condition is false. Note that temp2 contains itself the address addr2, and thus temp2->next is NOT addr2, it is NULL.
start = addr1;
|
V
(addr1) ----> (addr2) ----> (NULL) next iteration after temp2=temp2->next
^
|
temp2
After linking: temp2->next = temp1;
start = addr1; temp1 the address addr3 (new node)
| | is stored in temp1. this address is assigned
V V to the next node of temp2, replacing NULL
(addr1) ----> (addr2) ----> (addr3) ----> (NULL)
^
|
temp2
The pointers are the means to travel/traverse through the list. The starting address of the list is held in a pointer start. As the next field of each node points to the next node, if we get the start node, then by following the next fields sequentially we can visit each node. temp1 and temp2 are pointers with which the traversals are done, they act as temporary pointers, temp1 is used to hold the newly allocated node, and temp2 is used to travel through the list by following the next links till the last, when the last link is found (detected by the NULL pointer in the next field), the NULL link of this last node is replaced by the newly allocated node held by temp1 . As now the node held by temp1 is linked/added to the end of the list, temp1 is reused to hold another new node.