By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,691 Members | 1,152 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,691 IT Pros & Developers. It's quick & easy.

Is this a valid data structure??

P: n/a
Dan
I'm trying to creat a data structure, that can be either a integer,
double, string, or linked list. So I created the following, but don't
know if it is the data structure itself causing problems, or something
I am doing in the rest of the program.

This is the data structure.

struct node
{
char type;
union data
{
int integer;
double number;
char* word;
struct node* list;
}data;

struct node *next;
};
And this is the program I am using it in.

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

struct node
{
char type;
union data
{
int integer;
double number;
char* word;
struct node* list;
}data;

struct node *next;
};

typedef struct node node;
typedef struct node* node_ptr;
node_ptr new_node(char type);
void add_node(node_ptr destination, node_ptr source);
void print_node(node_ptr value);

int main()
{
node_ptr A;
node_ptr B;
node_ptr C;
node_ptr D;

A=new_node('I');
A->data.integer = 1;
printf("%i ", A->data.integer);

B=new_node('S');
B->data.word = "Hello";
printf("%s ", B->data.word);

C=new_node('D');
C->data.number = 1.567;
printf("%f ", C->data.number);

D=new_node('L');
add_node (D,A);
print_node(D);
}
node_ptr new_node(char type)
{
node_ptr ret_ptr = (node_ptr) malloc (sizeof(node));
ret_ptr->type = type;
switch (toupper(type))
{
case 'I':

ret_ptr->data.integer=0;
break;

case 'D':

ret_ptr->data.number=0;
break;

case 'S':

ret_ptr->data.word = "";
break;

case 'L':

ret_ptr->data.list = NULL;
break;

default:

printf("Error");
return NULL;
}

ret_ptr->next = NULL;
return ret_ptr;
}

void add_node(node_ptr destination, node_ptr source)
{
node_ptr next_ptr;
node_ptr prev_ptr;
printf("%c ", destination->type);
if (destination->type =! 'L')
{
printf("Error");
return;
}
if (destination->data.list == NULL)
{
destination->data.list = source;
printf("%c ", destination->type);
return;
}
next_ptr = destination->data.list;
while (next_ptr->data.list != NULL)
{
prev_ptr = next_ptr;
next_ptr= next_ptr->next;
}

prev_ptr->next = next_ptr;
}
void print_node(node_ptr value)
{
if (value == NULL)
return;

printf("%c ",value->type);

switch (value->type)
{
case 'I':

printf("% i", value->data.integer);
break;

case 'D':
printf("% f", value->data.number);
break;

case 'S':
printf("% s", value->data.word);
break;

case 'L':
printf("[");
print_node(value->data.list);
printf("]");
break;

default:
printf("Error");
return;
}

print_node(value->next);
}

The bug is in add node with a list, 'L', why does it change the actual
node itself. Maybe I don't see the logic but why does this line

destination->data.list = source;

change the actual destination node itself to something else. It seems
to me it would just change the list data member in the inner union to
point to the source pointer. But it seems change the actual
destination pointer itself.

Arggh...C drives me nuts.

Any help would be appreciated.

Thanks,

Dan
Nov 13 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
On Mon, 06 Oct 2003 20:33:06 -0700, Dan wrote:
I'm trying to creat a data structure, that can be either a integer,
double, string, or linked list. So I created the following, but don't
know if it is the data structure itself causing problems, or something
I am doing in the rest of the program.

This is the data structure.

struct node
{
char type;
union data
{
int integer;
double number;
char* word;
struct node* list;
}data;

struct node *next;
};
And this is the program I am using it in.

#include <stdio.h>
#include <malloc.h>
there is no <malloc.h> header. malloc() is declared in <stdlib.h>
so you can remove this.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

struct node
{
char type;
union data
{
int integer;
double number;
char* word;
struct node* list;
}data;

struct node *next;
};

typedef struct node node;
typedef struct node* node_ptr;
I think you're better off not typedefing pointers. It makes it harder
to read your code. It does solve the problem of putting the '*'s in
right place, but that can also be solved by putting each variable
declaration on a line by itself, which is good to do anyway.
node_ptr new_node(char type)
{
node_ptr ret_ptr = (node_ptr) malloc (sizeof(node));
node * ret_ptr = malloc(sizeof *ret_ptr);
void add_node(node_ptr destination, node_ptr source)
{
node_ptr next_ptr;
node_ptr prev_ptr;
printf("%c ", destination->type);
if (destination->type =! 'L')
I suspect this is the problem you are talking about. It should be

if (destination->type != 'L')

You really should turn on all of the warnings on your compiler to
help you catch this sort of thing. If they are already on, then stop
ignoring them.
if (destination->data.list == NULL)
{
destination->data.list = source;
printf("%c ", destination->type);
return;
}
This looks fine
next_ptr = destination->data.list;
while (next_ptr->data.list != NULL)
{
prev_ptr = next_ptr;
next_ptr= next_ptr->next;
}

prev_ptr->next = next_ptr;
Big problems here. First, I assume you want to tack the struct
pointed to by 'source' onto the end of the list, but 'source' doesn't
ever appear in this piece of code, so that will never work.

Second, you appear to be confusing your 'head of list' pointer with
your 'link' pointers. destination->data.list is supposed to point
at the first element in a linked list, but presumably you mean to
use next_ptr->next to link the elements in the list.

Third, you don't need a previous pointer for a singly linked list
like this.

Look at this replacement code. notice that the new elements are
simply linked onto the end of the list using the 'next' pointer.

next_ptr = destination->data.list;
while (next_ptr->next != NULL)
next_ptr = next_ptr->next;

next_ptr->next = source;

void print_node(node_ptr value)
{ ... case 'L':
printf("[");
print_node(value->data.list);
printf("]");
break;


this will only print out the value of the first element of the
list. You can write a loop to traverse the list as above, or
simply recurse (assuming the list isn't too long) like this:

case 'L':
printf("[");
print_node(value->data.list); /* print this node */
print_node(value->next); /* print the next node */
printf("]");
break;

-Sheldon
Nov 13 '05 #2

P: n/a
Dan
Sheldon Simms <sh**********@yahoo.com> wrote in message news:<pa**************************@yahoo.com>...
On Mon, 06 Oct 2003 20:33:06 -0700, Dan wrote:
I'm trying to creat a data structure, that can be either a integer,
double, string, or linked list. So I created the following, but don't
know if it is the data structure itself causing problems, or something
I am doing in the rest of the program.

This is the data structure.

struct node
{
char type;
union data
{
int integer;
double number;
char* word;
struct node* list;
}data;

struct node *next;
};
And this is the program I am using it in.

#include <stdio.h>
#include <malloc.h>
there is no <malloc.h> header. malloc() is declared in <stdlib.h>
so you can remove this.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

struct node
{
char type;
union data
{
int integer;
double number;
char* word;
struct node* list;
}data;

struct node *next;
};

typedef struct node node;
typedef struct node* node_ptr;


I think you're better off not typedefing pointers. It makes it harder
to read your code. It does solve the problem of putting the '*'s in
right place, but that can also be solved by putting each variable
declaration on a line by itself, which is good to do anyway.
node_ptr new_node(char type)
{
node_ptr ret_ptr = (node_ptr) malloc (sizeof(node));


node * ret_ptr = malloc(sizeof *ret_ptr);
void add_node(node_ptr destination, node_ptr source)
{
node_ptr next_ptr;
node_ptr prev_ptr;
printf("%c ", destination->type);
if (destination->type =! 'L')


I suspect this is the problem you are talking about. It should be

if (destination->type != 'L')


Oh thanks for spotting this. That is the kind of bug that would have
me pulling my hair out.
You really should turn on all of the warnings on your compiler to
help you catch this sort of thing. If they are already on, then stop
ignoring them.
if (destination->data.list == NULL)
{
destination->data.list = source;
printf("%c ", destination->type);
return;
}


This looks fine
next_ptr = destination->data.list;
while (next_ptr->data.list != NULL)
{
prev_ptr = next_ptr;
next_ptr= next_ptr->next;
}

prev_ptr->next = next_ptr;


Big problems here. First, I assume you want to tack the struct
pointed to by 'source' onto the end of the list, but 'source' doesn't
ever appear in this piece of code, so that will never work.

Second, you appear to be confusing your 'head of list' pointer with
your 'link' pointers. destination->data.list is supposed to point
at the first element in a linked list, but presumably you mean to
use next_ptr->next to link the elements in the list.

Third, you don't need a previous pointer for a singly linked list
like this.

Look at this replacement code. notice that the new elements are
simply linked onto the end of the list using the 'next' pointer.

next_ptr = destination->data.list;
while (next_ptr->next != NULL)
next_ptr = next_ptr->next;

next_ptr->next = source;

void print_node(node_ptr value)
{

...
case 'L':
printf("[");
print_node(value->data.list);
printf("]");
break;


this will only print out the value of the first element of the
list. You can write a loop to traverse the list as above, or
simply recurse (assuming the list isn't too long) like this:

case 'L':
printf("[");
print_node(value->data.list); /* print this node */
print_node(value->next); /* print the next node */
printf("]");
break;

-Sheldon


I was thinking that the recursive call at the end of the function
would take care of this. But you're suggestion is probably better.
Nov 13 '05 #3

P: n/a
On Tue, 07 Oct 2003 10:25:26 -0700, Dan wrote:
Sheldon Simms <sh**********@yahoo.com> wrote in message news:<pa**************************@yahoo.com>...
On Mon, 06 Oct 2003 20:33:06 -0700, Dan wrote:
> void add_node(node_ptr destination, node_ptr source)
> {
> node_ptr next_ptr;
> node_ptr prev_ptr;
> printf("%c ", destination->type);
> if (destination->type =! 'L')


I suspect this is the problem you are talking about. It should be

if (destination->type != 'L')


Oh thanks for spotting this. That is the kind of bug that would have
me pulling my hair out.


My compiler spotted it.

Nov 13 '05 #4

P: n/a
gi*****@aol.com (Dan) wrote:
> if (destination->type =! 'L')


I suspect this is the problem you are talking about. It should be

if (destination->type != 'L')


Oh thanks for spotting this. That is the kind of bug that would have
me pulling my hair out.


Format comparisons to constants with the constant first, as

if ('L' =! destination->type)

That will get an error from you compiler because it attempts
assignment to an improper lvalue, the constant 'L'. This also
works for the typo "=" where "==" was meant, though many
compilers can catch that one anyway.

Here are other examples,

if (0 != ioctl(...)) {

and

if (NULL == (fp = fopen(...))) {

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) fl***@barrow.com
Nov 13 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.