I have a program with the following structs:
typedef struct slide
{
int number;
int maxX;
int y;
int r, g, b;
struct line *first;
} slide;
typedef struct line {
char content[256]; // number subject to change
int r, g, b;
struct line *prev;
struct line *next;
} line;
Creating instances of these structs is done with the following code:
slide* createSlideArray(int s) {
slide* slides = malloc(sizeof(struct slide)*s);
return slides;
}
line *nextLine(line *prev) {
line *n = malloc(sizeof(line));
n->prev = prev;
prev->next = n;
return n;
}
And finally here is the code to free the structs after the program loop finishes, and before a new file is opened:
void freeLines(line *l) {
line *next;
while(l) {
next = l->next;
free(l);
l = next;
}
}
in main:
int i;
for (i=0;i<slideCount;i++) {
freeLines(slides[i].first); // works through next till NULL
}
free(slides);
As you can see, an instance of the slide struct holds a "first" line struct, the line struct is a doubly linked list. The line's content is read to the screen (using ncurses)
While in the program loop the user can type a command :open filename to open a new file, this is where my issue lies.
This slides and lines should be freed. When the loop starts again it'll open a new file, create the slides and lines, and use them as the content. The content, however, is partially filled with garbage text. I'm pretty sure this issue is in the lines struct and how it is being free. I'm not seeing that I'm doing wrong however.
Edit: I should make it clear that on the first iteration of the program the text is perfect, it is only when I try to parse a new file that the garbage text appears, and it is very homogeneous (appears at the front of each line, same characters)
I'm on Ubuntu if that makes a difference.
Here is a link to the project: DSS
There are some clear issues that I can spot from reading the code in your post. I can't definitively say if these are responsible for your problem as the code in your post is not a compilable example and I didn't go delving into your linked project.
Your nextLine function:
You have neglected to set n->next.
You have also neglected setting the prev pointer of the following node if there is one. ( prev->next->prev if prev->next != NULL ).
You current design precludes you from using this function to setup the first node in the list. It also does not show how you intend to create that node.
This function does not allow you to add a node to the begining of the list.
Your createSlideArray function:
This function does not initialize the slides it creates. These slide instances must be initialized. It seems sensible to do it here, but you might have a good reason to do it elsewhere. In either case, initializing the slideObject.first member is critical. Without this you will not be able to tell if the slide has a list of lines or not and your freeLines function will fail as it will be passed garbage as its parameter.
Note:
A different way of implementing doubly linked lists is using a "head node" which is always present and links to the first and last node in the list. This simplifies some issues, but changes others. You can research this if you are interested.
I was able to fix the issue by simply making proper calls to memset. for lines I was able to do the following:
memset(l, 0, sizeof(*l));
It is important that you are getting the size of the value at the l pointer, and not the size of the pointer itself, otherwise you won't properly free the memory. This was the issue that I was facing.
Related
I'm trying to creating linear linked list recursively with c language,
but keep sticking from here and the code is not working with the error "Linker Tools Error LNK2019". Sadly i can't understand what's the matter. Here is my code.
Thanks for your big help in advance.
#include <stdio.h>
#include <stdlib.h>
struct node
{
char num; //Data of the node
struct node *nextptr; //Address of the next node
};
typedef struct node element;
typedef element *link;
link head;
void displayList(); // function to display the list
int main()
{
char s[] = "abc";
link stol(s);
{
link head;
if (s[0] == '\0')return(NULL);
else {
head = (link)malloc(sizeof(element));
head->num = s[0];
head->nextptr = stol(s + 1);
return(head);
}
}
printf("\n\n Linked List : To create and display Singly Linked List :\n");
printf("-------------------------------------------------------------\n");
displayList();
return 0;
}
void displayList()
{
link tmp;
if (head == NULL)
{
printf(" List is empty.");
}
else
{
tmp = head;
while (tmp != NULL)
{
printf(" Data = %d\n", tmp->num); // prints the data of current node
tmp = tmp->nextptr; // advances the position of current node
}
}
}
You redefine a link object called head in your main() function. It hides the global head variable.
Removing the definition inside main would fix your problem, but you should consider passing a link* as a parameter to your displayList function in any case.
I've just noticed this statement return(head); in main(). You program exits prematurely as a result as well.
Everytime I look at your app, I find more issues. If I were you, I'd start by creating a function that adds a node to the list. It's much easier to add new nodes to the front of the list, so you should try that first. Try adding to the tail once you get this running. Adding to the tail is very similar, but you have to 'walkthe list first to get to the last element, exactly as you already do indisplayList()` Another way is keeping the address of the last node* you've added to the list. Like I said, it adds a bit of complexity, so get it working with addToHead first.
void addToHead(link* l, node* n)
{
n->nextptr = l->nextptr;
l->nextptr = n;
}
in your main, you can allocate one new node at a time, as you already do with malloc(). Initialize its contents num with an integer, and let addToHead deal with the pointer stuff. Your use of pointers is terrible, but lists are quite easy, and addToList pretty much shows what can and what should be put in pointers - namely other pointers.
You can remove almost everything in main() before the first printf. You'll have to
start loop:
write a prompt so the user knows what to do using printf()
read input from user using scanf("%d", &n), or equivalent.
break from the loop if user enters a negative value.
malloc() a new node
set its data num = n
call addToHead to add the node.
Loop until user enters an empty string, or -1.
That should take about 8 to 10 lines of code. if in doubt, you will easily find documentation on scanf, with google or on http://en.cppreference.com/w/c.
FIX: I wasn't saving the locations back into world so I was just leaking the information. Credit to Skeeto.
while(!feof(fp)){
loc = readLocation(fp);
join(loc,world);
}
should actually be
while(!feof(fp)){
loc = readLocation(fp);
world = join(loc,world);
}
EDIT: As mentioned in the comments, yes I am a student, but I'm not looking for someone to do my work for me. I'm simply trying to locate possible logic errors because if I could fill this list properly, I can finish my project very easily. This is just a small portion of a very immersive project, helping with this will only allow me to continue the project, not complete it and turn it in. I only provided so much detail because 1) I've never posted here before so didn't know any better, and 2) wanted the reader to understand the workings of this in order to aid them in assisting me. Also, with any concerns as to skype, if that ended up being where successful help was given, I would provide the fix above this 'edit' as well as crediting the stackoverflow user for helping.
TLDR: Yes I'm a student, No im not trying to have someone do my project. This is a very small portion and will only allow me to continue, not complete. If help was given via skype I would update this post with the fix as well as credit the helper.
Hello and thank you for any help in advance.
I am trying to create a linked list that holds objects of type Location *.
I have Location defined as
typedef struct location{
char *name;
char *longer;
char *shorter;
char *north;
char *south;
char *east;
char *west;
char *logic;
int visited;
char *items[20];
} Location;
Furthermore I can succesfully read in all the values for the location and display all attributes so that is not an issue.
In the 'engine' of my game (the main), i attempt to read all the locations into a list as seen in the following (I'm certain readLocation works correctly because I threw a print statement into the loop printing the name of the locations using the loc variable)
world = 0;
FILE *fp = fopen("world.in","r");
char *garb = readToken(fp);
free(garb); //garbage token at begging of world.in just to check file exists
int count = 0; //used later, ignore for now
while(!feof(fp)){
loc = readLocation(fp);
join(loc,world);
}
world is global variable declared as Node * and initialized to 0 (I think i need to do that but am not sure)
In olist.h I create the node structure as
typedef struct node
{
Location *place;
struct node *next;
} Node;
and in olist.c this is how i construct the Node as well as join the nodes
//place is the attribute of the Node that holds the location and next points to the next Node in the list
Node *newNode(Location *loc,Node *next)
{
Node *n = malloc(sizeof(Node));
if (n == 0)
{
fprintf(stderr,"newNode: out of memory!\n");
exit(1);
}
n->place = loc;
n->next = next;
return n;
}
//s is the location i wish to join to the list and rest is list I'm joining to
Node *join(void *s,Node *rest)
{
return newNode(s,rest);
}
Unfortunately, after successfully reading in all locations, world is still an empty list. Thanks for any help and I will be happy to provide further information via this forum or skype: F3V3Rz_MoDz (its a very old name)
If I'm not mistaken, your problem is in the following line of code :
n->next = next;
The head of your linked list is world, but your newNode() function keeps sending world to the back of the list (n->next = next places next at the back). What you want here is to append at the end of your linked list.
Here is an example of code that you can use to do this :
Node *lastNode = next;
while (lastNode->next != NULL)
lastNode = lastNode->next;
lastNode->next = n;
Basically, you iterate through your linked list until you get to the end, then you append the newly created node.
EDIT :
The problem you were having is that the world variable is in the end of your linked list. Every time you call join() you are pushing world at the back of the list. Here's a representation of your list :
Before join() :
world -> null
After join() :
newnode -> world -> null
Therefore, everytime you try to iterate through the list, world does not see the newly created nodes that are before him.
My solution does the following :
world -> newnode -> null
Which basically keeps your world variable in front. So you don't have to do world = join(loc, world)
I'm trying to find a specific location in a linked list and then be able to access its attributes. I know how to sort through the linked list but I can not figure out how to access the name attribute of the Locations.
I define my Location * structure as (These locations are stored into the list later):
#ifndef NESW_STRUCT
#define NESW_STRUCT
typedef struct location{
char *name;
char *longer;
char *shorter;
char *tip;
char *north;
char *south;
char *east;
char *west;
char *logic;
int visited;
char *items[20];
} Location;
#endif
My instructor provides us with a module to create a linked list as well as various functions to manipulate the list. The linked list is comprised of Node * which I believe hold the Locations as well as point to the next node in the list.
typedef struct node
{
Location *loc;
struct node *next;
} Node;
So in my game loop I create a global variable 'world' that is my linked list of (I think) Locations:
Node *world;
and
extern Node* world;
In other modules that also access it.
I then run a simple while loop in my main that creates a Location structure and then joins it to the Linked list(excluded from this post), world, using join(location,world) with the following functions my instructor provided, modified by me to work with Locations rather than void objects. I don't initialize world to anything before joining the first location to it, I think I may need to, but since its a core dump and crashes either way, I can't tell if it makes a difference/is necessary:
Node *
newNode(Location *place,Node *next)
{
Node *n = malloc(sizeof(Node));
if (n == 0)
{
fprintf(stderr,"newNode: out of memory!\n");
exit(1);
}
n->loc = place;
n->next = next;
return n;
}
Node *
join(Location *s,Node *rest)
{
return newNode(s,rest);
}
This all works perfectly fine so far and I create my list successfully. However, elsewhere in my program I created a function that maps through the world list and find the location that has a matching name to whichever name I pass to the function, which, logically, works correctly . I created a temp list that is equal to 'world', and then compared the name attribute of the head of the list to the name of the location I was looking for using, strcmp, returning that location if it matches, and setting the list = to the tail of the list if it doesn't.
Head and Tail are defined here, again provided in the module from my instructor:
Location *
head(Node *items)
{
return items->loc;
}
Node *
tail(Node *items)
{
return items->next;
}
If I understand these functions correctly, using head(list) should return a Location right, not a pointer? Then I should be able to just use 'location->name' to access the name? Apparently not though...
To save time of running through all the game logic just get to the part where it needs to compare the names, I tried writing some temporary code similar to how it would be in the mapping function, to test getting a location from the list and then accessing the attributes.
The probably wrong code I'm using to try and test accessing the list is:
Location *test = 0; //creating an empty location, (not sure if it needs to be initialized to 0 before assigning the desired value but I think I remember a mention of that during class)
test = head(world); //I would like to believe this sets test equal to the location of the head of the list world, but I am fairly certain this is where my error occurs because what is getting assigned to test really isn't a location
printf("%s",test->name); //basic print of the name attribute, I know this works logically because I use it elsewhere when dealing with locations not accessed through world, however this is what causes the core dump because I think I'm trying to access a garbage value so to speak
The program compiles with no errors and successfully reads all the the locations based on a debugging print statement I added. Any help, advice, or tips are greatly welcomed. I know people hate on kids that post here because they think they are trying to get their work done for free, but this is a very small part of an immersive project and once I figure this out, the game is essentially done other than content. I'm at a minor roadblock that is a major inhibitor and have tried everything my friend and I could think of and have even just started changing random data types in the Node struct and join/newNode functions as well as the Location struct hoping to either get lucky or figure out a solution through different error messages that occurred but as you can guess, no luck.
Solution by OP.
Because each new item is joined to the front of the list, the very last Node read into (which is the first node read when going through the list because the list is filled backwards) is the null pointer.
Example: Because the join function used stores a pointer to a Location and then points to the next Node in the list, the list is reversed after reading in.
Say you want to read alpha, bravo, charlie, delta epsilon into the list and you read them in that order, the list in memory looks like this with null being the head in the list:
null<-epsilon<-delta<-charlie<-bravo<-alpha
Therefore when I was trying to print with
Node *spot = world;
Location *loc = 0;
loc = head(spot);
printf("%s",loc->name);
I was attempting the print the name for the location which was really just a null pointer and obviously doesn't exist...So a very easy fix was to set spot equal to the tail before actually working with any of the Nodes in the list.
Node *spot = world;
Location *loc = 0;
spot = tail(spot);
loc = head(spot);
printf("%s",loc->name);
I have to print a list of a set in c using linked lists (hence pointers). However,when I delete the first element of the list and try to print the list, it just displays a lot of addresses under each other. Any suggestions of what the problem might be? Thanks!
Delete function:
int delete(set_element* src, int elem){
if (src==NULL) {
fputs("The list is empty.\n", stderr);
}
set_element* currElement;
set_element* prevElement=NULL;
for (currElement=src; currElement!=NULL; prevElement=currElement, currElement=currElement->next) {
if(currElement->value==elem) {
if(prevElement==NULL){
printf("Head is deleted\n");
if(currElement->next!=NULL){
*src = *currElement->next;
} else {
destroy(currElement);
}
} else {
prevElement->next = currElement->next;
}
// free(currElement);
break;
}
}
return 1;
}
void print(set_element* start)
{
set_element *pt = start;
while(pt != NULL)
{
printf("%d, ",pt->value);
pt = pt->next;
}
}
If the list pointer is the same as a pointer to the first element then the list pointer is no longer valid when you free the first element.
There are two solutions to this problem:
Let all your list methods take a pointer to the list so they can update it when neccesary. The problem with this approach is that if you have a copy of the pointer in another variable then that pointer gets invalidated too.
Don't let your list pointer point to the first element. Let it point to a pointer to the first element.
Sample Code:'
typedef struct node_struct {
node_struct *next;
void *data;
} Node;
typedef struct {
Node *first;
} List;
This normally happens when you delete a pointer (actually a piece of the memory) which doesn't belong to you. Double-check your function to make sure you're not freeing the same pointer you already freed, or freeing a pointer you didn't create with "malloc".
Warning: This answer contains inferred code.
A typical linked list in C looks a little something like this:
typedef struct _list List;
typedef struct _list_node ListNode;
struct _list {
ListNode *head;
}
struct _list_node {
void *payload;
ListNode *next;
}
In order to correctly delete the first element from the list, the following sequence needs to take place:
List *aList; // contains a list
if (aList->head)
ListNode *newHead = aList->head->next;
delete_payload(aList->head->payload); // Depending on what the payload actually is
free(aList->head);
aList->head = newHead;
The order of operations here is significant! Attempting to move the head without first freeing the old value will lead to a memory leak; and freeing the old head without first obtaining the correct value for the new head creates undefined behaviour.
Addendum: Occasionally, the _list portion of the above code will be omitted altogether, leaving lists and list nodes as the same thing; but from the symptoms you are describing, I'm guessing this is probably not the case here.
In such a situation, however, the steps remain, essentially, the same, but without the aList-> bit.
Edit:
Now that I see your code, I can give you a more complete answer.
One of the key problems in your code is that it's all over the place. There is, however, one line in here that's particularly bad:
*src = *currElement->next;
This does not work, and is what is causing your crash.
In your case, the solution is either to wrap the linked list in some manner of container, like the struct _list construct above; or to rework your existing code to accept a pointer to a pointer to a set element, so that you can pass pointers to set elements (which is what you want to do) back.
In terms of performance, the two solutions are likely as close so as makes no odds, but using a wrapping list structure helps communicate intent. It also helps prevent other pointers to the list from becoming garbled as a result of head deletions, so there's that.
As you can see from the images attached below, adding the second element from the top of the list create a strange behaviour for the printf function.
the function that add a list node is:
void add_QUEUEnode_top(Item a)
{
if (head==NULL)
{
QUEUEinit(a);
}
else
{
QUEUEput_top(a);
}
return;
}
void QUEUEinit(Item a)
{
head=(link)malloc(sizeof(link*));
head->next=NULL;
head->item=a;
tail=head;
printf("Coda iniziallizata...\n\n");
}
void QUEUEput_top(Item a)
{
link tmp;
tmp=(link)malloc(sizeof(link*));
tmp->item=a;
tmp->next=head;
head=tmp;
return;
}
Here the functions that handle the items:
Item fill_item()
{
Item a;
int i;
for(i=0; i<DIM-1; i++)
{
a.stringa[i]=rand();
}
a.stringa[DIM-1]='\0';
a.numero=rand();
printf("\nOggetto generato: \n");
print_item(a);
return a;
}
void print_item(Item a)
{
printf("\nStringa elemento: ");
printf("%s", a.stringa);
printf("\nNumero elemento: %d\n", a.numero);
}
Here's the link to the codeblock project i'm editing. The function print_item(Item a) that call the "bugged" printf is in the item.c module, while the functions that generate a list item are inside the list.c module.
Any idea of what can cause this problem?
PS: i'm sorry for the captures located in italian
EDIT: definition of the items:
typedef struct
{
char stringa[DIM];
int numero;
} Item;
Definition of the link pointer:
typedef struct QUEUEnode *link;
definition of the link structure:
struct QUEUEnode
{
Item item;
link next;
};
You have several bugs - I'll try to go through and find more of them for you, but the specific problem you're asking about is related to this code:
for(i=0; i<DIM-1; i++)
{
a.stringa[i]=rand();
}
a.stringa[DIM-1]='\0';
You're just putting a random number in each character - many of them may not be interesting or even printable characters in your character set. That's why you get the crazy output you're seeing. If you want to put random printable characters into the string, do so in a more character-set-aware way.
Some more problems:
These allocation lines are wrong:
head=(link)malloc(sizeof(link*));
tmp=(link)malloc(sizeof(link*));
They should be:
head = malloc(sizeof(struct QUEUEnode));
tmp = malloc(sizeof(struct QUEUEnode));
That is, you should allocate enough size for an entire struct QUEUEnode, not just a pointer to one. (Or a pointer to a pointer to one, which is what you had). Hiding the pointer type inside a typedef like you do with typedef struct QUEUEnode *link; is one of those controversial style choices - I personally prefer not to, since it confuses issues like this one pretty fast.
You're passing around a lot of structures by value in this program. That's fine and valid C, it's just a bit non-idiomatic. Normally people pass around pointers instead. If your structure grows to any appreciable size, performance can start to suffer badly as a result of all of the implicit memory copying going on.
You are allocating random text to stringa and then setting numero to a random number. When you print those things you get, well, random output. Because you have not restricted the randomisation to printable characters weird things happen. You are printing control characters. Your second screenshot would indicate that you have printed a carriage return character. I'm sure you don't want to do that!
The program is doing exactly what you asked it to do. Since you did not say what set of characters you wanted to assign to stringa from, I really could not say what your program should be. You could make it choose values in the range A to Z with this change:
a.stringa[i] = 'A' + rand() % 26;
I'll bet that there are other problems with your code, but since the main focus of the question concerned printing, I'll not look any deeper.