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)
Related
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.
i make a function to print an BTree in level order none recursive way.
and i have a problem to find my mistake.. the following problem showing up.
Run-Time Check Failure #2 - Stack around the variable 'pq' was corrupted.
if some one can tell where is the problem is, or how i can find it by my self next time...?
i add the full project if is needed.
enter link description here
void PrintTreeLevelOrder(bstree tree){ //The problem some where here.....
queue *pq = (queue*)malloc(sizeof(queue)); // is struct of : *front, *rear
node *current;// is struct of : root
create_queue(&pq);//create queue- items_num = 0,front = NULL,rear = NULL
if (tree.root == NULL) {
printf("Your Tree Is Empty:\n");
return;
}
current = tree.root;
enqueue(current, &pq);
printf("Your Tree Displayed As Queue:\n");
while ((size_of_queue(&pq) )!=0) {
current = pq->front;
printf("%d ", current->data);
if (current->left != NULL)
enqueue(current->left, &pq);
if (current->right)
enqueue(current->right, &pq);
dequeue(&pq, ¤t);
}
}
First of all, I want to say that your algorithm is correct, please read the below.
Your code has multiple mistakes that should take care of
You used the pq functions in a wrong way, you passed a pointer to a pointer instead of the original pointer, so you overwrote the code
Create_queue should allocate unless you call it init but that's not the main issue
You should check if create_queue succeeded
You are saving addresses in the queue which are queue* as int which is wrong and not portable for an architecture different than 32bit
you are assigning current which is a node (node tree struct) a queue_element element pointer struct, which is also not correct because they are different types and architectures
Please work on these points, if you want more details please contact me
I would be happy to help
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.
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);
So, I've done a little reading and consulted help from a friend. And I think I get it? Actually, my part in the project is just to store the table of characters and frequencies into a linked list. I've written down some codes, so is it possible if anyone can improve it.
Sample Input .txt file (the table of characters and frequencies):
B1
D3
E7
J9
The struct:
struct node {
char info;
int freq;
struct node * next;
struct node * left, *right, *father;
};
typedef struct node * nodeptr;
nodeptr getnode(){
return malloc(sizeof(struct node));
}
The main program (just until the part of storing the table into a linked list):
string input;
nodeptr list = NULL;
FILE *fopen();
int c;
list = fopen("Huffman Table.txt","r");
c = getc(input) ;
while (c!= EOF)
{
putchar(c);
c = getc(input);
}
getch();
fclose(input);
for (node * row = table; row != NULL; row = row->next){
fprintf(file, "%s %i %i", row->info, row->freq);
}
I'm not sure about this part though:
for (node * row = table; row != NULL; row = row->next)
Should I just use this instead?
for(i=0;i<strlen(input);i++){
I don't think
for (node * row = table; row != NULL; row = row->next)
would work because you're suppose to pass in an assignment before the first semicolon.
what you're doing is... i don't really know..
for(i=0;i<strlen(input);i++){
would work better. But i'm not sure, because i don't know what string input is suppose to hold and how you're using row and table
The used for loop is (syntactically) perfectly OK, and isn't that uncommon. However, what's the "table" pointer? Is it root of your list? Small remark - if you created "nodeptr" typedef, you should use it there. That's what it's for. There are some other parts of your code I'm concerned about
You said it was supposed to be a linked list, so why your struct has "father" pointer? It looks more like a tree to me. If it weren't the intent, remove that field.
I am not sure I understood the last piece of code you wrote. If you want to write contents of the list to a file, you should use the for loop mentioned above.
And as of general improvement to this code (which looks like a homework to me, and i guess should be tagged as such), is to use std::list<>. It can however be done only, if you're allowed to code in C++ rather in C.