I am using a priority queue with a double as the priority. I am guessing this is the cause of the issues. I used these numbers first with no issues.
34.365681
34.481879
34.539832
36.715120
I then used these numbers and had a segmentation fault.
45.411042
40.481879
37.702110
38.951187
struct PRIORITYQUEUE
{
int x_pq;
int y_pq;
double heuristic_pq;
int priority;
int info;
struct PRIORITYQUEUE *next;
}*start, *q, *temp, *new;
typedef struct PRIORITYQUEUE *N;
void insert(int x, int y, double heuristic)
{
int item;
double itprio;
//new = ( N* ) malloc( sizeof( N ) );
new = malloc( sizeof( N ) );
itprio = heuristic;
new->x_pq = x;
new->y_pq = y;
new->heuristic_pq = itprio;
if ( start == NULL || itprio < start->heuristic_pq )
{
new->next = start;
start = new;
}
else
{
q = start;
while ( q->next != NULL && q->next->heuristic_pq <= itprio )
q = q->next;
new->next = q->next;
q->next = new;
}
}
void del()
{
if ( start == NULL )
{
printf( "\nQUEUE UNDERFLOW\n" );
}
else
{
new = start;
printf( "\nDELETED ITEM IS %d\n", new->info );
start = start->next;
free( start );
}
}
void display()
{
temp = start;
if ( start == NULL )
printf( "QUEUE IS EMPTY\n" );
else
{
printf( "QUEUE IS:\n" );
while ( temp != NULL )
{
printf( "\t x is %d y is %d[heuristic=%lf] \n", temp->x_pq, temp->y_pq, temp->heuristic_pq );
temp = temp->next;
}
}
}
Your problem lies with this code:
typedef struct PRIORITYQUEUE *N;
:
new = malloc( sizeof( N ) );
The type N is a pointer to that structure of yours, not the structure itself. That means that sizeof(N) is likely to be much smaller than the structure, meaning that you're not allocating enough memory.
You could see this by inserting this immediately after the allocation:
printf ("%zd %zd\n", sizeof (N), sizeof (struct PRIORITYQUEUE));
and you'll probably see a series of lines of the form 4 32 or 8 32, showing that, while you've allocated four or eight bytes, you need 32.
That's what's causing your crashes. Now, as to how to fix it, it's simply making sure you allocate enough space for the structure and this can be done with either of:
new = malloc (sizeof (struct PRIORITYQUEUE));
new = malloc (sizeof (*N));
But the one I prefer is:
new = malloc (sizeof (*new));
The reason I prefer it is that it ties the allocation quantity to the variable you using. While the earlier two will handle any changes to the structure size, this one will even survive declaring new as a totally different structure without having to change information in multiple places.
By that I mean, if you change the type of new thus:
struct FASTER_PRIO_Q *new;
then you would be required to change the allocation statements as well for the first two cases. Not so for the third.
Related
I'd like to add an element to a list of element. My list is a struct containing a double, an integer and a pointer to the next element. Could someone tell me how to do the Add function please
#include <stdio.h>
#include <stdlib.h>
typedef struct Liste Liste;
struct Liste{
double c;
int n;
Liste* next; // pointe sur l'élément suivant
};
void Add(Liste array, Liste item) {
Liste* last = array.next;
while (last != NULL) {
last = last->next;
}
array.next = &item;
printf("%p\n", array.next);
}
int main(){
Liste array = {12.4, 4, NULL};
printf("%f\n", array.c);
Liste item = {15.4, 7, NULL};
Add(array, item);
printf("%p\n", array.next);
return 0;
}
Pass-by-value
In Add, C makes a copy of all the function parameters; their scope is the function itself. When one returns, the function parameters are popped from the stack and there is no way to get them back, as you have seen. The way to mutate structures is to pass a pointer to the structure, then modify that pointer using the structure pointer dereference operator, (arrow ->.)
Design
The reason one would use a linked-list is it is very cheap to reorder it, but the head of your linked-list is fixed, so you can't change it. You might change this by delineating the container, the list itself, from the contents. This is similar to using a double-pointer, but I think less confusing.
struct Noeud {
double c;
int n;
struct Noeud* next; // pointe sur l'élément suivant
};
struct Liste {
struct Noeud *tete; // singly-linked-list est defini par un pointer seul
};
Then you can add, (I've included assert.h.)
/* `O(n)` */
static void AddQueue(struct Liste *liste, struct Noeud *item) {
assert(liste && item && item->next == NULL);
struct Noeud* last = liste->tete;
if(last == NULL) { // case spécieux
liste->tete = item;
} else {
while (last->next != NULL) {
last = last->next;
}
last->next = item;
}
}
However, it's much simpler and asymptotically faster to add at the beginning of the list.
Pointerstructures like a linked list are powerful tools with a wide rage of application.
But first you have to understand pointers.
A pointer is a datastructure which contains the address of a datastructure.
Whenever you call a function the arguments of it are copied (pushed) to the stack.
If the arguments require a lot of storage space you use a pointer instead.
the code below uses pointers to create a linked list
#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"
typedef struct List List;
struct List{
double c;
int n;
List *next;
};
void AddItemEnd( List *RootItem, List *Item )
{
List *Last = RootItem;
while( Last->next != NULL )
{
Last = Last->next;
}
Last->next = Item;
}
void AddItemAtPos( List *RootItem, List *Item, unsigned int Pos )
{
if( Pos == 0 )
{
Item->next = RootItem;
}
else
{
List *TempItem = RootItem;
for( unsigned int i = 1; i < Pos && TempItem->next != NULL; ++i )
{
TempItem = TempItem->next;
}
Item->next = TempItem->next;
TempItem->next = Item;
}
}
void RemoveItemAtPos( List *RootItem, unsigned int Pos )
{
if( Pos == 0 )
{
free( (void*) RootItem );
}
else
{
List *TempItem = RootItem;
for( unsigned int i = 1; i < Pos && TempItem->next != NULL; ++i )
{
TempItem = TempItem->next;
}
if( TempItem->next == NULL )
{
return;
}else if( TempItem->next->next != NULL )
{
List *ItemToDelete = TempItem->next;
TempItem->next = TempItem->next->next;
free( (void*) ItemToDelete );
}else
{
free( (void*) TempItem->next );
TempItem->next =NULL;
}
}
}
int main(void) {
List *RootItem = malloc( sizeof( List ));
RootItem->c = 12.4;
RootItem->n = 4;
RootItem->next = NULL;
List *Item1 = malloc( sizeof(List ));
Item1->c = 15.4;
Item1->n = 7;
Item1->next = NULL ;
AddItemEnd( RootItem, Item1 );
List *IterationItem;
printf( "List created with AddItemEnd()\n\n" );
for( IterationItem = RootItem; IterationItem != NULL; IterationItem = IterationItem->next )
{
printf( "c: %lf\nn: %d\n\n", IterationItem->c, IterationItem->n );
}
List *item2 = malloc( sizeof( List ));
item2->c = 23.4;
item2->n = 1846;
item2->next = NULL ;
AddItemAtPos( RootItem, item2, 1 );
printf( "\n\nList extended with AddItemAtPos()\n\n");
for( IterationItem = RootItem; IterationItem != NULL; IterationItem = IterationItem->next )
{
printf( "c: %lf\nn: %d\n\n", IterationItem->c, IterationItem->n );
}
RemoveItemAtPos(RootItem, 1 );
printf( "\n\nList after RemoveItemAtPos()\n\n");
for( IterationItem = RootItem; IterationItem != NULL; IterationItem = IterationItem->next )
{
printf( "c: %lf\nn: %d\n\n", IterationItem->c, IterationItem->n );
}
free( (void*) RootItem );
free( (void*) item2 );
return 0;
}
The key elements when dealing with lists is pointers
and using memory allocation.
If we disregard your add function and just do a simple
example you will probably get the geist of it.
First allocate you starting list like this
Liste* array = malloc(sizeof(Liste));
Now you have one uninitialized block of memory
that array points to. You then need to initialize
it.
array->c = 12.4;
array->n = 4;
array->next = NULL;
in order to add a new entry to your list you
need to again allocate memory for the next node and
initialize it plus set the previous node next pointer
to point to it i.e. array->next.
Liste* item = malloc(sizeof(Liste));
item->c = 15.4;
item->n = 7;
item->next = NULL;
array->next = item;
now you have a list of two elements where array points
to the first
printing your short list
Liste* p = array;
while (p != NULL)
{
printf("%lf %d %p\n", p->c, p->n, p->next);
p = p->next;
}
So your Add functions does not allocate memory and copies
the parameters so that is not going to work.
Your Add function should have a pointer either to either the first or last item in your list e.g.
void Add(Liste* start, double c, int n)
Then you do as I showed you above and create a new node and assign the values
If you want to be able to pass an empty list to Add then you need to do differently, since start is copied it cannot be changed, you need to pass the address of the pointer
void Add(List** start, double c, int n)
{
Liste* node = malloc(sizeof(Liste));
...
(* put node in the list *)
if (*start == NULL)
{
*start = node; // first
}
else
{
(* find last node, see print loop *)
(* once you have last item, set it to point to node)
}
...
}
int main()
{
Liste* start = NULL;
Add(&start, 12.4, 4);
Add(&start, 15.4, 7);
...
I am trying to create a singly linked list and initialize it with the first given n integers.But i am getting segmentation fault whenever i run it.This is my code.
typedef struct floatList{float fval;struct floatList * fnext;}node_f;
node_f* FL_firstInts(int n){
node_f *res=(node_f*)malloc(sizeof(node_f));
res=res->fnext;
for(int i=1;i<=n;i++){
res->fval=i;
res=res->fnext;
}
return res;
}
void FL_show(struct floatList *list, char *label){
int i=0;
while(list->fnext!=NULL){
printf("%d: %f\n",i,f->fval);
list=list->fnext;
i++;
}
}
And in order to test in the main function, i write the following
node_f *ten = FL_firstInts(10);
FL_show(ten,"10 first integers");
But as i run the program, i get segmentation fault,how do i fix it?
In the function FL_firstInts you allocated uninitialized object of the type node_f
node_f *res=(node_f*)malloc(sizeof(node_f));
So the following statement
res=res->fnext;
already invokes undefined behavior.
The function can be defined at least the following way
node_f * FL_firstInts( int n )
{
node_f *head = NULL;
node_f **current = &head;
`
for ( int i = 0; i < n; i++ )
{
*current = malloc( sizeof( node_f ) );
( *current )->fval = i;
( *current )->fnext = NULL;
current = &( *current )->fnext;
}
return head;
}
Th function FL_show has the same bug and moreover the parameter label is not used.
The function can be defined like
void FL_show( const node_f *head, const char *label )
{
if ( label ) puts( label );
for ( int i = 0; list != NULL; list = list->fnext )
{
printf( "%d: %f\n", i, f->fval );
i++;
}
}
node_f *res=(node_f*)malloc(sizeof(node_f));
res=res->fnext;
The reason for your crash is that you're never initialising the res->fnext pointer.
So before accessing it set it to the actual next element in your list.
In general your code is a bit fuzzy.
You're allocating memory for one node_f, but you're actually trying to put n elements into it.
To allocate memory for the n elements just multiply the size of one element by n.
node_f *res= (node_f*) malloc(sizeof(node_f) * n);
Afterwards initialise the fnext pointers.
for(size_t index{0}; index < n - 1; index++)
res[index].fnext = &res[index + 1];
res[n - 1].fnext = nullptr;
I have written a C program that constructs a binary search tree from an array. It goes through the following steps:
1: Sort the array with qsort().
2: Place the sorted elements of the array into a binary tree using the recursive function treeify():
2a: Take the middle element of the array (by dividing its length by 2) and place that as the content field of the tree struct (the root node of this subtree).
2b: Function then copies the left and right halves of the remaining elements into smaller arrays and calls itself for each of these arrays respectively.
2c: Return the tree via the root node.
3: Recursively traverse the tree and print its contents in indented format.
Basically, I used a divide-and-conquer paradigm to build the tree from the already-sorted array. Surprisingly (since this was my first time designing a D&C algorithm) this part went rather smoothly.
Where I really ran into trouble was in Step 3. Sometimes it works, and when it does, all of the elements are in the right order, so that part obviously works. But 90% of times I run the program, it segfaults when it gets to the first leaf node.
Here is the full program text. I've altered the printing function so that it prints the addresses of the nodes (for debugging purposes). Originally it displayed the numeric values...
#include <stdio.h>
#include <stdlib.h>
struct tree {
int content;
struct tree *left;
struct tree *right;
};
struct tree *treeify( int *, size_t );
void printtree( struct tree *, int );
int comp( int *, int * );
int main( int argc, char **argv ){
int array[] = { 5, 6, 7, 2, 3, 4, 9, 1, 8, 0 };
/* Sort array */
qsort( (void *) array, 10, sizeof( int ), (int (*)(const void *, const void *)) &comp );
for( int i = 0; i < 10; i++ ){
printf( "%d ", array[i] );
}
printf( "\n" );
/* Treeify array */
struct tree *rootnode = treeify( array, 10 );
/* Print tree */
printtree( rootnode, 0 );
return 0;
}
// Place sorted array elements in a tree
// Function is called for each subtree
struct tree *treeify( int *array, size_t size ){
struct tree *root = (struct tree *) malloc( sizeof( struct tree ) );
size_t middle = size/2;
int leftsize = middle, rightsize = size-middle-1;
int left[leftsize], right[rightsize];
for( int i = 0; i < leftsize; i++ ) left[i] = array[i];
for( int i = 0; i < rightsize; i++ ) right[i] = array[i+middle+1];
root->content = array[middle];
if( leftsize > 0 ) root->left = treeify( left, leftsize );
if( rightsize > 0 ) root->right = treeify( right, rightsize );
return root;
}
// Print tree contents in indented format
void printtree( struct tree *node, int level ){
for( int i = 0; i < level; i++ ) printf( " " );
printf( "%x\n", &(node->content) );
if( node->left ) printtree( node->left, level+1 );
if( node->right ) printtree( node->right, level+1 );
}
// Comparison function for qsort
int comp( int *xp, int *yp ){
int x = *xp, y = *yp;
if( x < y ) return -1;
if( x > y ) return 1;
return 0;
}
I've managed to isolate the problem by printing the addresses of the nodes when traversing the tree. Here is the output from a successful run:
0 1 2 3 4 5 6 7 8 9
cbe00000
cbe00020
cbe00040
cbe00060
cbe00080
cbe000a0
cbe000c0
cbe000e0
cbe00100
cbe00120
And an unsuccessful run:
f04032b0
f04032d0
f04032f0
f0403310
0
Segmentation fault: 11
Notice how the successful run only goes through three levels of the tree before returning and going back up. The unsuccessful run goes through four levels, reaching a null pointer.
Specifically, when the program gets to this line:
if( node->left ) printtree( node->left, level+1 );
It takes the branch despite node->left evaluating to zero (as indicated by the fifth line of the output).
This is what I can't for the life of me understand. The condition is clearly evaluating to false (I've verified that), and yet the program is still taking that branch as if it evaluated to true (and only in most, not all, cases).
This has literally never happened to me before. I'll need someone who knows a lot more about C than I do to shed some light on this for me.
The only possibilities I can think of:
Some quirky compiler optimization
I made a stupid single-character error somewhere
My CPU is partially fried
The problem is that you try to read from an unintialized member of the structure, the very first time it happens is here
if (node->left)
in printtree() function.
Uninitialized values, are kept like that and attempting to read them is undefined behavior, so that's why your program doesn't always behave the same.
You need to initialize both members, in fact it woule be better to have
struct tree *create_node(int content)
{
struct tree *node;
node = malloc(sizeof(*node));
if (node == NULL)
return NULL;
node->content = content;
node->left = NULL;
node->right = NULL;
return node;
}
You should also,
Avoid casting malloc() or any function returning void * because of what's discussed here.
Check that malloc() doesn't return NULL before using the pointer.
For starters the function comp shall be declared like
int comp( const void *, const void * );
Secondly in the function treeify either the data member left of the data member right will have indeterminate value in case when leftsize or rightsize are equal to 0.
The function can be implemented simpler without using auxiliary arrays.
struct tree * treeify( const int *array, size_t size )
{
struct tree *node = NULL;
if ( size )
{
node = malloc( sizeof( struct tree ) );
size_t middle = size / 2;
node->content = array[middle];
node->left = treeify( array, middle );
node->right = treeify( array + middle + 1, size - middle - 1 );
}
return node;
}
The function printtree( is wrong. For example it does not check whether the first parameter is equal to NULL.
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
struct tree
{
int content;
struct tree *left;
struct tree *right;
};
int comp( const void *, const void * );
struct tree * treeify( const int *, size_t );
void printtree( const struct tree *, int level );
int main(void)
{
int array[] = { 5, 6, 7, 2, 3, 4, 9, 1, 8, 0 };
const size_t N = sizeof( array ) / sizeof( *array );
qsort( array, N, sizeof( *array ), comp );
for ( size_t i = 0; i < N; i++ ) printf( "%d ", array[i] );
putchar( '\n' );
struct tree *rootnode = treeify( array, N );
printtree( rootnode, 0 );
return 0;
}
int comp( const void *left, const void *right )
{
int x = *( const int * )left;
int y = *( const int * )right;
return ( y < x ) - ( x < y );
}
struct tree * treeify( const int *array, size_t size )
{
struct tree *node = NULL;
if ( size )
{
node = malloc( sizeof( struct tree ) );
size_t middle = size / 2;
node->content = array[middle];
node->left = treeify( array, middle );
node->right = treeify( array + middle + 1, size - middle - 1 );
}
return node;
}
void printtree( const struct tree *node, int level )
{
if ( node )
{
printf( "%*s", level, "" );
printf( "%d\n", node->content );
if( node->left ) printtree( node->left, level + 1 );
if( node->right ) printtree( node->right, level + 1 );
}
}
Its output is
0 1 2 3 4 5 6 7 8 9
5
2
1
0
4
3
8
7
6
9
I would like some professional advice for making a char *x array of strings (of const char names with different sizes) Would someone help with mallocing a list to fit the size of a structure name ( qSep->front->name))
Attempt 1: Well my base case works, so I started making multiple print statements. The first one doesn't get put in. My gdb causes error at printf("Found in List %s has name\n", x[0]);
Code and then data structures below.
size_t separation( const User *user1, const User *user2 ) {
int len= 0;
char *x;
//use contains
queueSep *qSep =(struct queueSep*) malloc(sizeof(struct queueSep));
int count = 0;
//pre-condition: the user is not the same as user2
if ( user1->name == user2->name ) { //str compare
return 0;
}
qSep->front = convert(user1, NULL, count);
printf("Conversion complete for %s \n",qSep->front->name);
len++;
x = malloc(len*sizeof((const char*)qSep->front->name));
x[len-1] = qSep->front->name;
printf("Found in List %s has name\n", x[0]);
while( qSep->front != NULL) {
//check if front of the queue is the finish USER
if ( (const char*)qSep->front->name == user2->name ) {
return qSep->front->separationCount;
} else { //add all the neighbours on the queue with separation size incremented
struct node *currAmigo = qSep->front->sepAmigos->amigos_Queue->front;
if ( currAmigo == NULL ) {
//is that a bad thing?
}
while ( currAmigo != NULL ) {
for(int i = 0; i < len; ++i) {
printf("List amigo for %s has name %s\n", currAmigo->data->name, x[i]);
/*
//if(strcmp(x[i], currAmigo->data->name))
{
goto end_nested_loop;
}
*/
}
//make a qSep node
struct sepNode *node = convert(currAmigo->data, NULL, count+1);
len++;
x = realloc(x, len*sizeof(int));
x[len-1] = currAmigo->data->name;
//insert the sepNode into the end of the queue
que_insSepqueue(qSep, node);
//go to Next Amigo in top of Queue
currAmigo=currAmigo->next;
}
end_nested_loop:
count++;
//remove the node
que_deqSep( qSep );
}
}
return -1;
}
Converted Struct
typedef struct sepNode {
const char *name;
struct Friends_struct *sepAmigos;
size_t *separationCount;
struct sepNode *sepNodeNext;
}sepNode;
typedef struct queueSep{
struct sepNode *front; //front of queue
}queueSep;
//How to make a list
typedef struct User_struct {
const char *name;
Friends amigos;
} User;
EXTRA ( to convert a node to say separation length)
sepNode *convert( const User *user1, const User *user2, int count) {
sepNode *sepNode1=
sepNode1 = (struct sepNode*) malloc(sizeof(struct sepNode));
sepNode1->name = user1->name;
sepNode1->sepAmigos = user1->amigos;
sepNode1->separationCount = count;
sepNode1->sepNodeNext = NULL;
return sepNode1;
}
Using a pointer list
char *x;
You have indexes that need to be malloc instead of
x = malloc(len*sizeof((const char*)qSep->front->name));
x[len-1] = qSep->front->name;
Malloc the size of the first index with
x[len-1] = malloc(sizeof(char)*sizeof(qSep->front->name)); //redundant sizeof(char) =1
//just to illustrate
x[len-1] = qSep->front->name;
Also, if anyone knows if I can just free(x); in one line, that would be helpful in a comment.
I'm working on a homework assignment for CS1, and I almost have it finished but errors keep popping up in relation to a few functions I've tried to implement. The assignment is the classic addition and subtraction of big integers using linked lists. My issue isn't with any of mathematical functionality of the program, but rather getting the linked lists to print properly when finished. I'm pretty sure most of the problems reside within stripLeadingZeros(); the functions are as follows.
/*
* Function stripLeadingZeros
*
* #Parameter STRUCT** Integer
*
* Step through a linked list, recursively unlinking
* all leading zeros and making the first
* non-zero integer the head of the list.
*/
struct integer* stripLeadingZeros( struct integer *p )
{
// Are we at the end of the list?
if( p == NULL ) return NULL;
// Are we deleting the current node?
if( p->digit == 0 )
{
struct integer *pNext;
pNext = p->next;
// Deallocate the node
free( p );
// Return the pointer to the next node
return pNext;
}
// Recurse to make sure next node is not 0
p->next = stripLeadingZeros( p->next );
return p;
}
---///---
/*
* Function print
*
* #Parameter STRUCT* Integer
*
* Given a linked list, will traverse through
* the nodes and print out, one at a time,
* the digits comprising the struct integer that the
* linked list represents.
*
* TODO: Print to file
*/
void print( struct integer *p )
{
struct integer *head = p;
reverse( &p );
p = stripLeadingZeros( p );
while( p )
{
fprintf(outFile, "%d", p->digit);
p = p->next;
}
reverse( &head );
}
---///---
/*
* Function reverse
*
* #Parameter STRUCT** Integer
*
* Recursively reverses a linked list by
* finding the tail each time, and linking the
* tail to the node before it.
*/
void reverse (struct integer **p)
{
/*
* Example p: 1->2->3->4->NULL
*/
if( (*p)->next == NULL ) return;
struct integer *pCurr = *p, *i, *pTail;
// Make pCurr into the tail
while( pCurr->next )
{
i = pCurr;
pCurr = pCurr->next;
}
// Syntactic Sugar
pTail = pCurr;
pTail->next = i;
/*
* p now looks like:
* 1->2->3<->4
*/
i->next = NULL;
/*
* p now looks like:
* 1 -> 2 -> 3 <- 4
* |
* v
* NULL
*/
reverse( p ); // Recurse using p: 1 -> 2 -> 3;
*p = i;
}
The output I am currently getting for the whole program is:
888888888 + 222222222 = 11111111
000000000 - 999999999 = 000000001
000000000 - 999999999 = 000000001
whereas the expected output is
8888888888 + 2222222222 = 11111111110
10000000000 – 9999999999 = 1
10000000000 – 9999999999 = 1
Any help anyone could give would just be awesome; I've been working on this for so long that if I had any hair I'd have pulled it out by now.
EDIT My read_integer function is as follows:
/*
* Function read_integer
*
* #Parameter CHAR* stringInt
*
* Parameter contains a string representing a struct integer.
* Tokenizes the string by each character, converts each char
* into an integer, and constructs a backwards linked list out
* of the digits.
*
* #Return STRUCT* Integer
*/
struct integer* read_integer( char* stringInt )
{
int i, n;
struct integer *curr, *head;
int numDigits = strlen( stringInt ); // Find the length of the struct integer
head = NULL;
for( i = 0; i < numDigits; i++ )
{
n = stringInt[i] - '0'; // Convert char to an integer
curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
curr->digit = n; // Digit of current node is assigned to n
curr->next = head; // Move to the next node in the list.
head = curr; // Move head up to the front of the list.
}
return head; // Return a pointer to the first node in the list.
}
Simulate stripLeadingZeros() on "0004".
It does not work. Also you ignored an edge case: what if it is only "0". You must not strip the only 0 in that case.
Correct code:
struct integer* stripLeadingZeros( struct integer *p )
{
// Are we at the end of the list?
if( p == NULL ) return NULL;
// Are we deleting the current node? Also it should not strip last 0
if( p->digit == 0 && p->next != NULL)
{
struct integer *pNext;
pNext = p->next;
// Deallocate the node
free( p );
// Try to strip zeros on pointer to the next node and return that pointer
return stripLeadingZeros(pNext);
}
return p;
}
Consider the control flow of this function:
struct integer* stripLeadingZeros( struct integer *p )
{
// Are we at the end of the list?
if( p == NULL ) return NULL;
// Are we deleting the current node?
if( p->digit == 0 )
{
struct integer *pNext;
pNext = p->next;
// Deallocate the node
free( p );
// Return the pointer to the next node
return pNext;
}
// Recurse to make sure next node is not 0
p->next = stripLeadingZeros( p->next );
return p;
}
What happens when p starts with a zero? It enters the if statement, removes the one leading zero, and returns. It does not recurse because you've already returned within the if statement. This means that stripLeadingZeros will remove at most one zero.
Now what happens when p starts with a one? It skips the if statement, but it does recurse. This is also wrong, because once have seen a one, you want to stop removing zeroes, as they are no longer leading.
So what this function is actually doing is removing the first zero it encounters, leading or not, and then stopping. That's not what you want it to do.
You want to recurse after you have removed a zero, and only after you have removed a zero, so move the recursive call into the if statement. In other words, replace return pNext; with return stripLeadingZeros(pNext);, and remove the recursion from outside the loop.
You can improve your reverse function by reversing your original list into another list:
void reverse(struct integer** p)
{
struct integer* old = *p;
struct integer* new = NULL;
while(old != NULL)
{
struct integer* oldNext = old->next;
old->next = new;
new = old;
old = oldNext;
}
*p = new;
}
stripLeadingZeros( nodeptr s )
{
if(s!=NULL)
stripLeadingZeros(s->next);
if((s!=NULL)&&s->data==0&&on)
flg=1;
if((s!=NULL)&&(s->data!=0)&&flg)
on=0,flg=0,s->next=NULL;
if(flg)
s->next=NULL;
}
here's my code to strip leading zeros initial values of on and flg are 1 and 0 respectively .
http://programmingconsole.blogspot.in/2013/10/all-basic-calculator-functions-on-large.html
in your current version of stripLeadingZeros you can replace the while loop with an if statement that the result will be the same. Maybe that is the problem.
while (1) {
/* ... */
return 0; /* this "infinite loop" only runs once */
}
compare with
if (1) {
/* ... */
return 0;
}