473,385 Members | 1,707 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Linked list with void *

Hai,
I thank those who helped me to create a single linked list with int
type. Now I wanted to try out for a void* type. Below is the code:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<stddef.h>

struct node
{
void *data;
struct node *next;
};
struct node *insert(void *data,struct node **p)
{
void *temp;
struct node *q;
q = malloc(sizeof *q);
if(q == NULL)
{
printf("MEM ERROR\n");
exit(EXIT_FAILURE);
}
else
{
temp = malloc(sizeof *temp);
if(temp == NULL)
{
printf("MEM ERROR2\n");
exit(EXIT_FAILURE);
}
else
{
data = temp;
q ->data = data;
q -> next = *p;
q-> next = NULL;
*p = q;
return *p;
}
}
return NULL;
}

void disp(struct node *p)
{
for(;p != NULL; p=p->next)
printf("%s",p->data);
}
int main(void)
{
char *data;
int s=49,*a = &s;
struct node *p=NULL;
scanf("%s",data);
insert(data,&p);
disp(p);
insert(a,&p);
disp(p);
return 0;
}

OUTPUT:

lati˙˙˙˙ e

I have some questions:

1) When we use printf function to print something we use format
specifier for printing. (%s,%d etc). But when it comes to void*, do we
have a format specifier? If not then how will we print the void* in
the above type of program where the printing definition is in one
function and that function is called for the printing job?
2) The output I got is totally unexcepted. What ever I type I get the
same above out put. Why?
3) When we copy two void pointers shall we use just the assignment
operator or do we have to use memcpy, memset functions. Is the out put
in the above is different because of this being not used?

Thanks in advance.
Nov 13 '05 #1
6 9105
da***********@yahoo.com wrote in
news:a3**************************@posting.google.c om:
int main(void)
{
char *data;
What does data point to? Junk, that's what. You don't own what it points
to so scanf()'ing into is very bad. Malloc() some stinking memory for it
or declare as an array sufficient to hold what you expect the use to enter
(knowing that this still leave you open to buffer overrun).
int s=49,*a = &s;
struct node *p=NULL;
scanf("%s",data);


POP! You scanf'd into some place you shouldn't.

--
- Mark ->
--
Nov 13 '05 #2
> 1) When we use printf function to print something we use format
specifier for printing. (%s,%d etc). But when it comes to void*, do we
have a format specifier? If not then how will we print the void* in
the above type of program where the printing definition is in one
function and that function is called for the printing job?
A void* is identified with %p, just as any other pointer. If you make it to
hold different data (e.g. an integer), make sure you cast it when you feed
it to printf (and use the appropriate identifier).
3) When we copy two void pointers shall we use just the assignment
operator or do we have to use memcpy, memset functions. Is the out put
in the above is different because of this being not used?


If you want to copy the pointers themselves, just use the assignment
operator. If you want to copy what they point at, use memcpy or memmove (or
strcpy for strings) - memset fills a region of memory with a certain byte.

Good luck,

--
Martijn
http://www.sereneconcepts.nl
Nov 13 '05 #3


da***********@yahoo.com wrote:
...........snip..........
struct node
{
void *data;
struct node *next;
};
struct node *insert(void *data,struct node **p)
{
void *temp;
struct node *q;
q = malloc(sizeof *q);
if(q == NULL)
{
printf("MEM ERROR\n");
exit(EXIT_FAILURE);
}
else
{
temp = malloc(sizeof *temp);
...........snip.............

OUTPUT:

lati˙˙˙˙ e

I have some questions:

1) When we use printf function to print something we use format
specifier for printing. (%s,%d etc). But when it comes to void*, do we
have a format specifier? If not then how will we print the void* in
the above type of program where the printing definition is in one
function and that function is called for the printing job?
printf has different specifiers for different typed. The specifier for
void pointer is %p. However, in using the generic struct, you will
be converting the void *data to some other type. The code you write
and functions like printf will refer to this type. For example say
void *data will be pointing to a string. Then the specifier would
be %s and printf would look like this: printf("%s\n",(char *)q->data).
2) The output I got is totally unexcepted. What ever I type I get the
same above out put. Why?
The code has numerous errors. I am surprised that it compiled at all.
You have.
void *temp;
then you use function malloc.
..... malloc(sizeof *temp);
The sizeof operand, *temp, is an incomplete type and is not allowed.
3) When we copy two void pointers shall we use just the assignment
operator or do we have to use memcpy, memset functions. Is the out put
in the above is different because of this being not used?


The operations you use will depend on the data type you are using.
For example, a link list of names (strings), could be as follows.

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

struct node
{
void *data;
struct node *next;
};
struct node *insertName(const char *data,struct node **p)
{
void *temp;
struct node *q;

q = malloc(sizeof *q);
if(q != NULL)
{
temp = malloc(strlen(data)+1);
if(temp == NULL)
{
free(q);
q = NULL;
}
else
{
q ->data = temp;
strcpy(q->data,data);
q ->next = *p;
*p = q;
}
}
return q;
}

void dispNames(struct node *p)
{
for(;p != NULL; p=p->next)
printf("%s\n",(char *)p->data);
}

void freeAll( struct node **p)
{
struct node *tmp, *current;

for(current = *p; current; current = tmp)
{
tmp = current->next;
free(current->data);
free(current);
}
*p = NULL;
}

int main(void)
{
unsigned i,number;
char buf[80],*s;
struct node *names=NULL;

printf("Enter the number of names to add to the list: ");
fflush(stdout);
fgets(buf,sizeof buf, stdin);
number = atoi(buf);
putchar('\n');
for(i = 0;i < number;i++)
{
printf("Enter name #%d: ",i+1);
fflush(stdout);
fgets(buf,sizeof buf,stdin);
if((s = strrchr(buf,'\n')) != NULL) *s = '\0';
insertName(buf,&names);
}
puts("\n\nThe names in the list are");
dispNames(names);
freeAll(&names);
return 0;
}

--
Al Bowers
Tampa, Fl USA
mailto: xa*@abowers.combase.com (remove the x)
http://www.geocities.com/abowers822/

Nov 13 '05 #4
Al Bowers <xa*@abowers.combase.com> wrote in message news:<bl************@ID-169908.news.uni-berlin.de>...
da***********@yahoo.com wrote:
..........snip..........
struct node
{
void *data;
struct node *next;
};
struct node *insert(void *data,struct node **p)
{
void *temp;
struct node *q;
q = malloc(sizeof *q);
if(q == NULL)
{
printf("MEM ERROR\n");
exit(EXIT_FAILURE);
}
else
{
temp = malloc(sizeof *temp);


..........snip.............

OUTPUT:

lati˙˙˙˙ e

I have some questions:

1) When we use printf function to print something we use format
specifier for printing. (%s,%d etc). But when it comes to void*, do we
have a format specifier? If not then how will we print the void* in
the above type of program where the printing definition is in one
function and that function is called for the printing job?


printf has different specifiers for different typed. The specifier for
void pointer is %p. However, in using the generic struct, you will
be converting the void *data to some other type. The code you write
and functions like printf will refer to this type. For example say
void *data will be pointing to a string. Then the specifier would
be %s and printf would look like this: printf("%s\n",(char *)q->data).
2) The output I got is totally unexcepted. What ever I type I get the
same above out put. Why?


The code has numerous errors. I am surprised that it compiled at all.
You have.
void *temp;
then you use function malloc.
.... malloc(sizeof *temp);
The sizeof operand, *temp, is an incomplete type and is not allowed.
3) When we copy two void pointers shall we use just the assignment
operator or do we have to use memcpy, memset functions. Is the out put
in the above is different because of this being not used?


The operations you use will depend on the data type you are using.
For example, a link list of names (strings), could be as follows.

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

struct node
{
void *data;
struct node *next;
};
struct node *insertName(const char *data,struct node **p)
{
void *temp;
struct node *q;

q = malloc(sizeof *q);
if(q != NULL)
{
temp = malloc(strlen(data)+1);
if(temp == NULL)
{
free(q);
q = NULL;
}
else
{
q ->data = temp;
strcpy(q->data,data);
q ->next = *p;
*p = q;
}
}
return q;
}

void dispNames(struct node *p)
{
for(;p != NULL; p=p->next)
printf("%s\n",(char *)p->data);
}

void freeAll( struct node **p)
{
struct node *tmp, *current;

for(current = *p; current; current = tmp)
{
tmp = current->next;
free(current->data);
free(current);
}
*p = NULL;
}

int main(void)
{
unsigned i,number;
char buf[80],*s;
struct node *names=NULL;

printf("Enter the number of names to add to the list: ");
fflush(stdout);
fgets(buf,sizeof buf, stdin);
number = atoi(buf);
putchar('\n');
for(i = 0;i < number;i++)
{
printf("Enter name #%d: ",i+1);
fflush(stdout);
fgets(buf,sizeof buf,stdin);
if((s = strrchr(buf,'\n')) != NULL) *s = '\0';
insertName(buf,&names);
}
puts("\n\nThe names in the list are");
dispNames(names);
freeAll(&names);
return 0;
}


Sir,
Thanks for the code.It works well except that it prints the out put
in reverse order.
The function *insertName() takes only char pointer (string) as a
input. If some body wants to insert int data type then he has to
redefine a different function which takes int type as a input in its
parameter. I am trying to make the function *insertName() generic with
void pointer as a parameter. What to do? Cannot we make the whole
thing in a preprossor macro?

#define list(xxx) \
struct ann{ \
struct ann * next; \
xxx item; }*

int main(void)
{
list(int) fool1 = 10;
printf("%s\n",(int)fool1);
return 0;
}
OUTPUT:
10

Even though I am getting warning about the initialization I am getting
the output correctly! But I am not claming that the above code is
correct but may be to the point.
But we cannot make two objects with list(xxx). I don't know why?
Nov 13 '05 #5


da***********@yahoo.com wrote:
Thanks for the code.It works well except that it prints the out put
in reverse order.
The function *insertName() takes only char pointer (string) as a
input. If some body wants to insert int data type then he has to
redefine a different function which takes int type as a input in its
parameter. I am trying to make the function *insertName() generic with
void pointer as a parameter. What to do? Cannot we make the whole
thing in a preprossor macro?
You can make a macro. But not the way you did it here.
First of all you can make the insert function generic by including
a size argument where you can allocate the size and then use memcpy
to copy. The prototype:
struct node *insert(const void *data,size_t size, struct node **p);
And the call would be like:
insert(buf,sizeof buf,&names);

You can use the macro for the display (printing) of the list.

#define disp(NODE,SPEC,TYPE) {struct node *tmp;\
for(tmp = NODE;tmp != NULL; tmp=tmp->next)\
printf(#SPEC"\n",TYPE(tmp->data));}

There are probably better ways or languages to do this.

#define list(xxx) \
struct ann{ \
struct ann * next; \
xxx item; }*

int main(void)
{
list(int) fool1 = 10;
printf("%s\n",(int)fool1);
return 0;
}


Plug these ideas into your code and it appears to work.

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

struct node
{
void *data;
struct node *next;
};

#define disp(NODE,SPEC,TYPE) {struct node *tmp;\
for(tmp = NODE;tmp != NULL; tmp=tmp->next)\
printf(#SPEC"\n",TYPE(tmp->data));}

void freeAll( struct node **p);
struct node *insert(const void *data,size_t size, struct node **p);

int main(void)
{
int i,number;
char buf[80],*s;
struct node *names=NULL;

printf("Enter the number of names to add to the list: ");
fflush(stdout);
fgets(buf,sizeof buf, stdin);
number = atoi(buf);
putchar('\n');
for(i = 0;i < number;i++)
{
printf("Enter name #%d: ",i+1);
fflush(stdout);
fgets(buf,sizeof buf,stdin);
if((s = strrchr(buf,'\n')) != NULL) *s = '\0';
insert(buf,sizeof buf, &names);
}
puts("\n\nThe names in the list are");
disp(names,%s,(char *));
freeAll(&names);
puts("\n**********************\nList of integers");
printf("Enter the number of integers to add to the list: ");
fflush(stdout);
fgets(buf,sizeof buf, stdin);
number = atoi(buf);
putchar('\n');
for(i = 0;i < number;i++)
{
int value;
printf("Enter integer #%d: ",i+1);
fflush(stdout);
fgets(buf,sizeof buf,stdin);
value = atoi(buf);
insert(&value,sizeof value, &names);
}
puts("\n\nThe integers in the list are");
disp(names,%d,*(int*));
freeAll(&names);
puts("\n**********************\nList of type doubles");
printf("Enter the number of doubles to add to the list: ");
fflush(stdout);
fgets(buf,sizeof buf, stdin);
number = atoi(buf);
putchar('\n');
for(i = 0;i < number;i++)
{
double value;
printf("Enter double value #%d: ",i+1);
fflush(stdout);
fgets(buf,sizeof buf,stdin);
value = atof(buf);
insert(&value,sizeof value, &names);
}
puts("\n\nThe numbers(2 decimal places) in the list are");
disp(names,%.2f,*(double*));
freeAll(&names);
return 0;
}

struct node *insert(const void *data,size_t size, struct node **p)
{
void *temp;
struct node *q, *cur;

q = malloc(sizeof *q);
if(q != NULL)
{
temp = malloc(size);
if(temp == NULL)
{
free(q);
q = NULL;
}
else
{
q ->data = temp;
memcpy(q->data,data,size);
q ->next = NULL;
if(*p == NULL) *p = q;
else
{
for(cur = *p; cur->next; cur = cur->next) ;
cur->next = q;
}
}
}
return q;
}

void freeAll( struct node **p)
{
struct node *tmp, *current;

for(current = *p; current; current = tmp)
{
tmp = current->next;
free(current->data);
free(current);
}
*p = NULL;
}

--
Al Bowers
Tampa, Fl USA
mailto: xa*@abowers.combase.com (remove the x)
http://www.geocities.com/abowers822/

Nov 13 '05 #6
Al Bowers <xa*@abowers.combase.com> wrote in message news:<bl************@ID-169908.news.uni-berlin.de>...
da***********@yahoo.com wrote:
Thanks for the code.It works well except that it prints the out put
in reverse order.
The function *insertName() takes only char pointer (string) as a
input. If some body wants to insert int data type then he has to
redefine a different function which takes int type as a input in its
parameter. I am trying to make the function *insertName() generic with
void pointer as a parameter. What to do? Cannot we make the whole
thing in a preprossor macro?


You can make a macro. But not the way you did it here.
First of all you can make the insert function generic by including
a size argument where you can allocate the size and then use memcpy
to copy. The prototype:
struct node *insert(const void *data,size_t size, struct node **p);
And the call would be like:
insert(buf,sizeof buf,&names);

You can use the macro for the display (printing) of the list.

#define disp(NODE,SPEC,TYPE) {struct node *tmp;\
for(tmp = NODE;tmp != NULL; tmp=tmp->next)\
printf(#SPEC"\n",TYPE(tmp->data));}

There are probably better ways or languages to do this.

#define list(xxx) \
struct ann{ \
struct ann * next; \
xxx item; }*

int main(void)
{
list(int) fool1 = 10;
printf("%s\n",(int)fool1);
return 0;
}


Plug these ideas into your code and it appears to work.

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

struct node
{
void *data;
struct node *next;
};


Thanks for the code .Btw it is not a home work.
Nov 13 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Dream Catcher | last post by:
1. I don't know once the node is located, how to return that node. Should I return pointer to that node or should I return the struct of that node. 2. Also how to do the fn call in main for that...
10
by: Kent | last post by:
Hi! I want to store data (of enemys in a game) as a linked list, each node will look something like the following: struct node { double x,y; // x and y position coordinates struct enemy...
1
by: Booser | last post by:
// Merge sort using circular linked list // By Jason Hall <booser108@yahoo.com> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> //#define debug
6
by: Steve Lambert | last post by:
Hi, I've knocked up a number of small routines to create and manipulate a linked list of any structure. If anyone could take a look at this code and give me their opinion and details of any...
4
by: JS | last post by:
I have a file called test.c. There I create a pointer to a pcb struct: struct pcb {   void *(*start_routine) (void *);   void *arg;   jmp_buf state;   int    stack; }; ...
4
by: MJ | last post by:
Hi I have written a prog for reversing a linked list I have used globle pointer Can any one tell me how I can modify this prog so that I dont have to use extra pointer Head1. When I reverse a LL...
1
by: drewy2k12 | last post by:
Heres the story, I have to create a doubly linked list for class, and i have no clue on how to do it, i can barely create a single linked list. It has to have both a head and a tail pointer, and...
51
by: Joerg Schoen | last post by:
Hi folks! Everyone knows how to sort arrays (e. g. quicksort, heapsort etc.) For linked lists, mergesort is the typical choice. While I was looking for a optimized implementation of mergesort...
0
by: Atos | last post by:
SINGLE-LINKED LIST Let's start with the simplest kind of linked list : the single-linked list which only has one link per node. That node except from the data it contains, which might be...
7
by: QiongZ | last post by:
Hi, I just recently started studying C++ and basically copied an example in the textbook into VS2008, but it doesn't compile. I tried to modify the code by eliminating all the templates then it...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.