LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-31-2014, 10:13 AM   #1
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Rep: Reputation: Disabled
Erroneous pointer monograph?


In a popular on-line C-programming monograph on pointers (Nick Parlante, “Linked List Problems”, Stanford U.), I’m running into the following dilemma with a suggested solution in the text, which I cannot make compile.
Though I have produced a satisfactory working solution, I’m wondering if anyone can identify if I’ve made a coding error while trying to employ the suggested solution, or is the suggested solution erroneous.

[I note that I still had to rem the last two code lines of AlternateSplit() to accomplish compiling-------don’t understand why those code lines were even included in the original]

The Problem, as stated, is:
Write a function AlternatingSplit() that takes one list and divides up its nodes to make two smaller lists. The sublists should be made from alternating elements in the original list. So if the original list is {a, b, a, b, a}, then one sublist should be {a, a, a} and the other should be {b, b}. You may want to use MoveNode() as a helper. The elements in the new lists may be in any order.
/*
Given the source list, split its nodes into two shorter lists.
If we number the elements 0, 1, 2, ... then all the even elements
should go in the first list, and all the odd elements in the second.
The elements in the new lists may be in any order.
*/
Code:
void AlternatingSplit(struct node* source,
struct node** aRef, struct node** bRef) {
// Your code
The Recommended Solution in the monograph is as follows:

Code:
void AlternatingSplit(struct node* source,
struct node** aRef, struct node** bRef) {
struct node* a = NULL; // Split the nodes to these 'a' and 'b' lists
struct node* b = NULL;
struct node* current = source;
while (current != NULL) {
MoveNode(&a, &current); // Move a node to 'a'
if (current != NULL) {
MoveNode(&b, &current); // Move a node to 'b'
}
}
*aRef = a;
*bRef = b;
}
This (my) version compiles and functions:

Code:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int i;
struct node* next;
};
//prototypes
void AlternatingSplit(struct node* source,struct node** aRef,struct node** bRef);
void MoveNode(struct node** destRef,struct node** sourceRef);
void Push(struct node** headref,int i);

int main(void)
{

int i;
struct node* head=NULL;
struct node* a=NULL;
struct node* b=NULL;
struct node* tail;
    Push(&head,0);  //build list
    tail=head;
    for(i=1;i<9;i++)
    {
    Push(&(tail->next),i);
    tail=tail->next;
    }
    AlternatingSplit(head,&a,&b); //split into lists a and b
}

void AlternatingSplit(struct node* source,struct node** aRef,struct node** bRef)
{
//struct node* a = NULL;
//struct node* b = NULL;
    while (source != NULL) 
    {
    MoveNode(aRef, &source); // Move node from source to 'a'
    if (source != NULL) 
        {
        MoveNode(bRef, &source); // Move node from source to 'b'
        }
    }
//*aRef = a;
//*bRef = b;
}

void MoveNode(struct node** destRef,struct node** sourceRef)
{
struct node* current;
current = *sourceRef;
*sourceRef = current->next;
current->next = *destRef;
*destRef = current;
}

void Push(struct node** headref,int i)
{
struct node* temp=malloc(sizeof(struct node));
temp->i = i;
temp->next = *headref;
*headref = temp;
}
However, this version, which is a suggested solution in the text, does not compile;
Code:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int i;
struct node* next;
};
//prototypes
void AlternatingSplit(struct node* source,struct node** aRef,struct node** bRef);
void MoveNode(struct node** destRef,struct node** sourceRef);
void Push(struct node** headref,int i);

int main(void)
{

int i;
struct node* head=NULL;
struct node* tail;
    Push(&head,0);  //build list
    tail=head;
    for(i=1;i<9;i++)
    {
    Push(&(tail->next),i);
    tail=tail->next;
    }
    AlternatingSplit(head,&a,&b); //split into lists a and b
}

void AlternatingSplit(struct node* source,struct node** aRef,struct node** bRef)
{
struct node* a = NULL;
struct node* b = NULL;
    while (source != NULL) 
    {
    MoveNode(aRef, &source); // Move node from source to 'a'
    if (source != NULL) 
        {
        MoveNode(bRef, &source); // Move node from source to 'b'
        }
    }
 //*aRef = a;
//*bRef = b;
}

void MoveNode(struct node** destRef,struct node** sourceRef)
{
struct node* current;
current = *sourceRef;
*sourceRef = current->next;
current->next = *destRef;
*destRef = current;
}

void Push(struct node** headref,int i)
{
struct node* temp=malloc(sizeof(struct node));
temp->i = i;
temp->next = *headref;
*headref = temp;
}
 
Old 10-31-2014, 12:51 PM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
It's quite easy too fix, eg:
Code:
#include <stdio.h>
#include <stdlib.h>

struct node
{
    int i;
    struct node* next;
};

void AlternatingSplit(struct node* source,struct node** aRef,struct node** bRef);
void MoveNode(struct node** destRef,struct node** sourceRef);
void Push(struct node** headref,int i);

int main(void)
{
int i;
struct node* head=NULL;
struct node* tail;
struct node *a, *b;

    Push(&head,0);  //build list
    tail=head;
    for(i=1;i<9;i++)
    {
    Push(&(tail->next),i);
    tail=tail->next;
    }
    AlternatingSplit(head,&a,&b); //split into lists a and b
}

void AlternatingSplit(struct node* source,struct node** aRef,struct node** bRef)
{
    struct node* a = NULL;
    struct node* b = NULL;

    while (source != NULL) 
    {
    MoveNode(aRef, &source); // Move node from source to 'a'
    if (source != NULL) 
        {
        MoveNode(bRef, &source); // Move node from source to 'b'
        }
    }
    *aRef = a;
    *bRef = b;
}

void MoveNode(struct node** destRef,struct node** sourceRef)
{
    struct node* current;

    current = *sourceRef;
    *sourceRef = current->next;
    current->next = *destRef;
    *destRef = current;
}

void Push(struct node** headref,int i)
{
    struct node* temp=malloc(sizeof(struct node));

    temp->i = i;
    temp->next = *headref;
    *headref = temp;
}

Last edited by NevemTeve; 10-31-2014 at 01:57 PM.
 
1 members found this post helpful.
Old 10-31-2014, 04:55 PM   #3
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Original Poster
Rep: Reputation: Disabled
Thanks (again) so much. Hard to believe that such errors in scholarly monographs are never corrected by the authors.
 
Old 11-06-2014, 03:12 PM   #4
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by NevemTeve View Post
It's quite easy too fix, eg:
Code:
#include <stdio.h>
#include <stdlib.h>

struct node
{
    int i;
    struct node* next;
};

void AlternatingSplit(struct node* source,struct node** aRef,struct node** bRef);
void MoveNode(struct node** destRef,struct node** sourceRef);
void Push(struct node** headref,int i);

int main(void)
{
int i;
struct node* head=NULL;
struct node* tail;
struct node *a, *b;

    Push(&head,0);  //build list
    tail=head;
    for(i=1;i<9;i++)
    {
    Push(&(tail->next),i);
    tail=tail->next;
    }
    AlternatingSplit(head,&a,&b); //split into lists a and b
}

void AlternatingSplit(struct node* source,struct node** aRef,struct node** bRef)
{
    struct node* a = NULL;
    struct node* b = NULL;

    while (source != NULL) 
    {
    MoveNode(aRef, &source); // Move node from source to 'a'
    if (source != NULL) 
        {
        MoveNode(bRef, &source); // Move node from source to 'b'
        }
    }
    *aRef = a;
    *bRef = b;
}

void MoveNode(struct node** destRef,struct node** sourceRef)
{
    struct node* current;

    current = *sourceRef;
    *sourceRef = current->next;
    current->next = *destRef;
    *destRef = current;
}

void Push(struct node** headref,int i)
{
    struct node* temp=malloc(sizeof(struct node));

    temp->i = i;
    temp->next = *headref;
    *headref = temp;
}
Thought the above correction (which compiled) was suitable, but I find that it leaves "a" and "b" empty. Is it valid to pass uninitialized pointers *a and *b in main() as arguments to AlternatingSplit() ?
I remain uncertain as to the whole "solution" listed by the author of the monograph.
 
Old 11-06-2014, 03:35 PM   #5
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by atlantis43 View Post
Thought the above correction (which compiled) was suitable, but I find that it leaves "a" and "b" empty. Is it valid to pass uninitialized pointers *a and *b in main() as arguments to AlternatingSplit() ?
I remain uncertain as to the whole "solution" listed by the author of the monograph.
I don't see why NevemTeve uncommented the lines
Code:
 //*aRef = a; 
 //*bRef = b;
I think those lines were correctly commented out in the original.

Adding the missing declaration of a and b in main was obviously needed. Beyond that, I didn't test and didn't desk check carefully.

Anyway, in answer to your question, it is perfectly valid to pass the addresses of uninitialized pointers. Something needs to initialize those before use, but that can be (probably should be) inside the function, rather than outside, such as:

Code:
void AlternatingSplit(struct node* source,struct node** aRef,struct node** bRef)
{
    *aRef = NULL;
    *bRef = NULL;
    while (source != NULL) 
    {
    MoveNode(aRef, &source); // Move node from source to 'a'
    if (source != NULL) 
        {
        MoveNode(bRef, &source); // Move node from source to 'b'
        }
    }
}

Last edited by johnsfine; 11-06-2014 at 03:46 PM.
 
Old 11-06-2014, 04:28 PM   #6
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Original Poster
Rep: Reputation: Disabled
Johnsfine:
Thanks for your info regarding passing uninitialized variables.
No, I was the one who commented out the lines
Code:
*aRef = a; 
*bRef = b;
as there was no need for a return value in my working solution: in fact, my version would not compile properly with those return values present, and I would get following errmsg on compilation:
Quote:
prob12.c:68:9: error: use of undeclared identifier 'a'
*aRef = a;
^
prob12.c:69:9: error: use of undeclared identifier 'b'
*bRef = b;
With NevemTeve's code, if I try using the following function to evaluate what is contained in a and b lists:
Code:
void Length_Vals(struct node* head)
{
struct node* current = head;
int count = 0;
while(current!=NULL)
    {
    count++;

    printf("%3d",current->i);
    current = current->next;
    }
printf("\n# of nodes in list is %d\n",count);
}
I get the following terminal output:
Quote:
0 1 2 3 4 5 6 7 8 9
# of nodes in [original] list is 10

# of nodes in list [a] is 0

# of nodes in list [b] is 0
I remain completely befuddled by the "suggested" solution.

Last edited by atlantis43; 11-06-2014 at 04:32 PM. Reason: addnl info
 
Old 11-06-2014, 07:17 PM   #7
norobro
Member
 
Registered: Feb 2006
Distribution: Debian Sid
Posts: 792

Rep: Reputation: 331Reputation: 331Reputation: 331Reputation: 331
I believe NevemTeve has a typo in his AlternatingSplit():
Code:
    while (source != NULL) 
    {
    MoveNode(aRef, &source); // Move node from source to 'a'
    if (source != NULL) 
        {
        MoveNode(bRef, &source); // Move node from source to 'b'
        }
    }
Should be &a and &b respectively.
 
2 members found this post helpful.
Old 11-06-2014, 09:40 PM   #8
atlantis43
Member
 
Registered: Feb 2013
Posts: 289

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by norobro View Post
I believe NevemTeve has a typo in his AlternatingSplit():
Code:
    while (source != NULL) 
    {
    MoveNode(aRef, &source); // Move node from source to 'a'
    if (source != NULL) 
        {
        MoveNode(bRef, &source); // Move node from source to 'b'
        }
    }
Should be &a and &b respectively.
Yes!!!, problem solved. Thanks to all.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] insert() in trie with erroneous count atlantis43 Programming 3 03-15-2014 07:47 AM
how is decision taken if the packet is erroneous in netfilter hemendra Linux - Newbie 1 07-26-2011 10:40 PM
can't remove a network printer with erroneous ip luxaeternam Linux - Networking 3 10-11-2006 11:39 AM
Erroneous PPC SIO Tx-driver ecsed Programming 0 06-17-2005 09:29 AM
erroneous touchpad behavior Mr_C Linux - Laptop and Netbook 2 04-10-2005 06:24 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:26 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration