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.
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 am trying to copy strings from a field in one struct to another struct (a node), so that I can ultimately create a hashtable. However, I seem to be having some issues in the actual string copying. I've created a for loop to iterate over the strings in the source stuct, and I know the iteration is working fine, because if I printf the source strings (data[i].c_name), they print out fine. Unfortunately, when I try to printf the destination (class_id), it seems to be empty (and thus of course my hash function isn't doing much). Any insights into the potential problem here would be greatly appreciated. Please let me know if I haven't given enough context.
#define LENGTH 30
#define MAX_OBS 80000
typedef struct
{
char c_name[LENGTH];
char s_name[LENGTH];
double value[MAX_OBS];
}
sample;
typedef struct node
{
char class_id[LENGTH];
struct node *next;
}
node;
{
char class_id[LENGTH];
for (int i = 0; i < total_columns; i++)
{
// malloc a new node pointer for each new class label
node *new_node = malloc(sizeof(node));
// check that there was sufficient memory
if (new_node == NULL)
{
return 6;
}
// copy c_name into node -- failing - class_id is empty
strcpy(new_node->class_id, data[i].c_name);
printf("%s\n", class_id);
}
}
Drop the last char class_id[LENGTH]; that you print as it was never initialized. Then switch your printf() to use the actual target of the strcpy.
strncpy(new_node->class_id, data[i].c_name, LENGTH);
printf("%.*s\n", LENGTH, new_node->class_id);
I've also put a few LENGTH limits in my code to assure you don't do bad things on bad input without a terminal \0. Never blindly trust your C input unless you generated it in a fail-safe manner.
Disclaimer: desktop inspection changes. Actual debugging is left as an exercise to the student.
I'm a computer engineering student and I have to write BST as an assignment but the code is not like what everyone written(so far as I search for some example,so I'm desperate now) Here is my code so far(My classroom use C as a main language not C++)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct bst_node
{
int data;
struct bst_node *right;
struct bst_node *left;
}BST_NODE;
typedef struct bst
{
int size;
BST_NODE *root;
}BST;
void print(BST_NODE *pos)
{
printf("%d(0)",pos->data);
if(pos->left != NULL)
{
printf("%d(L)\n",pos->left->data);
pos=pos->left;
}
if(pos->right != NULL)
{
printf("%d(R)\n",pos->right->data);
pos=pos->right;
}
if(pos->left != NULL)
print(pos->left);
if(pos->right != NULL)
print(pos->right);
}
int main()
{
int number;
BST b;
BST_NODE *pos;
b.root=NULL;
while(1)
{
scanf("%d",&number);
printf("value=%d",number);
if(number<=0)
break;
if(b.root==NULL)
{
b.root=(BST_NODE*)malloc(sizeof(BST_NODE));
pos=b.root;
pos->data=number;
pos->left=NULL;
pos->right=NULL;
}
else
{
pos=b.root;
while(pos)
{
if(number>pos->data)
{
if(pos->right==NULL)
{
pos->right=(BST_NODE*)malloc(sizeof(BST_NODE));
pos->right->left=NULL;
pos->right->right=NULL;
pos->right->data= number;
pos=pos->right;
}
else
{
pos->right->data= number;
pos=pos->right;
}
}
if(number<pos->data)
{
if(pos->left==NULL)
{
pos->left=(BST_NODE*)malloc(sizeof(BST_NODE));
pos->left->left=NULL;
pos->left->right=NULL;
pos->left->data=number;
pos=pos->left;
}
else
{
pos->left->data=number;
pos=pos->left;
}
}
}
}
}
print(b.root);
return 0;
}
I don't know what wrong with this code because it can only receives 2 value then it stops working. The only thing I found out so far to be a problem is while(pos)loop and I try to fix this for week.I would be grateful,if anyone help me solve this problem. Print it out to would be great.
P.S -stop working mean the windows I run program in just freeze or hang.
You want to break out of your while(pos) loop as soon as you malloc a new node. You are done inserting so stop working.
Also you don't want to overwrite all ->data values while traversing the tree in your else branches.
When you add a value to the tree, it looks like you always replace the existing value with the input number instead of just traversing to the next level. Remove
pos->right->data = number;
And
pos->left->data = numbér;
From main()
You also should add an 'else' before the left node check. As it stands, you're checking the right branch and then the left branch every time through the loop. If you check the right branch and make a hit, you'll always check the left branch, too. Probably not a problem, but unnecessary.
Not sure that's the reason 'it stops working' as 'it stops working' is awful darn vague, but that looks suspicious to me.
Additionally...
Be consistent on your indentation. Sometimes the indentation is more spaces than other times
add spaces between struct definitions and Breen function declarations. Think of these things as chapters in a book. Use the whitespace to make separate things clearly separate.
add a prompt within the loop to indicate that it's expecting input. If you think your app has frozen, it may simply be waiting for input
add a check at the start of print() and sensibly handle null roots. This could occur if you type a negative number as your input the first time around. Missing such a check and typing a negative as your first input may crash.
Oh! And use calloc() instead of malloc(). Calloc initializes new memory to nulls, while malloc does not. Malloc just gives you whatever memory it happens to give you, containing whatever random garbage it may contain. If you use calloc, you will have less liklihood of issues with bad memory.
I have a function that adds one item to a list that I created. If it's the first time and the list points to NULL, it allocates the list and completes it, returning the address. If it's not the first time, it adds another item and again returns the first item (by now I could disregard this return). The list and the function WORKS fine, here is the prototype:
typedef struct structTAppConsoleList {
char *text;
void (*cbFunction)(int);
int number; // This is the item number
struct structTAppConsoleList *previous;
struct structTAppConsoleList *next;
} TList;
TList *AppConsoleListAddItem(TList *p_list, const char *p_string, void (*p_funcPtr)(int));
So, somewhere in my code I have to create a lot of them and I'm trying to make it as the code below shows. Thing is, I can't make it work... I want to create something to group the lists I want to create and then use it in the function. The code below is an idea of what I'm trying to do. Consider only the part where I try to allocate the 3 lists, the rest is not important for this example.
TList *list1;
TList *list2;
TList *list3;
int main(void)
{
int i,j;
TList **groupMyLists;
TList *temp;
groupMyLists=malloc(sizeof(TList)*3);
*groupMyLists =(TList*)&list1;
*(groupMyLists+1)=(TList*)&list2;
*(groupMyLists+2)=(TList*)&list3;
for(j=0;j<3;j++) {
temp=NULL;
for(i=0;i<10;i++) {
temp=AppConsoleListAddItem(temp,"some text",someFunc);
}
**groupMyLists=temp; // my make won't let me do this
groupMyLists++;
}
}
I'm pretty sure that this would do it, but I can't compile it.
In my head, (*groupMyLists) would be the same as (&list1), (&list2), (&list3), the same way that (**groupMyLists) would be the same as (list1), (list2) and (list3). So why I can't do (**groupMyLists=temp)? Anyone?
I hope I made myself clear!! I's not easy to explain this madness I'm trying to do...
Change this line, you are using the wrong indirection.
*groupMyLists=temp;
In addition to the above two answers about the incorrect indirection of **groupMyLists you probably also want to assign the list1,list2,list3 pointers correct pointer values instead of writing garbage values into the allocated memory in groupMyLists i.e.
TList * groupMyList = malloc(sizeof(TList)*3);
list1 = &groupMyList[0];
list2 = &groupMyList[1];
list3 = &groupMyList[2];
but, this does not really match the rest of your code as it seems that AppConsoleAddListItem allocates the temp list so in that case your malloc would be incorrect as it should allocate the space for the pointers instead of space for the lists as in:
TList ** groupMyList = (TList **)malloc(sizeof(TList *)*3);
TList * temp;
if (!groupMyList) {
/* Print allocation error warning or handle in some proper fashion */
exit(1);
}
for(j=0;j<3;j++) {
temp=NULL;
for(i=0;i<10;i++) {
temp=AppConsoleListAddItem(temp,"some text",someFunc);
}
groupMyLists[j]=temp; // Here you now assign the pointer in temp to the memory for // pointers that you allocated above
}
list1 = groupMyList[0]; // Here we need to assign the list1,2,3 after the AppConsole calls
list2 = groupMyList[1]; // as these calls will changes the pointer addresses written into
list3 = groupMyList[2]; // groupMyList
Although I can not be sure exactly what you are trying to do there are several inconsistencies of pointers and indirections in your original code and the above two examples can hopefully be of some guidance
This would do the job:
**groupMyLists = *temp;
of copying one struct referenced by temp to another struct referenced by *groupMyLists.
But only if *groupMyLists would reference any valid memory, which is does not do - at least not from the source you posted.
I made a list to do some data treatment and I'm having an issue that I don't find the cause, for me my code seems right but there are issues.
What I'm trying to do is the following :
I have a list that contains x elements. I want to add an element p in the list then take every x element, add p to the string they represent, and add them to the list. (the list by itself works great it's just that operation that causes troubles).
The problem is that when I do that and when I try to display the list the first x+p elements are displayed well, but after I see some strange characters that have nothing to do with the inputs.
Here are the functions I use :
void addFirst(struct list *l, char *key)
{
struct node *x = createNode(key) ;
if (l->size == 0)
{
l->first = x;
}
else
{
x->next = l->first;
l->first = x;
}
l->size++;
return;
}
void showList(struct list* l)
{
struct node *p=l->first;
while (p!=NULL)
{
printf("%s \n",p->key);
p=p->next;
}
return;
}
void copyPlus(struct list* l,char *ch)
{
struct node *p=l->first;
addFirst(l,ch);
while (p!=NULL)
{
int len1=strlen(p->key);
char cat[len1+2];
strcpy(cat,p->key);
strcat(cat,ch);
cat[len1+1] = '\0';
printf("[%s] \n",cat);
addFirst(l,cat);
printf("{%s} \n",l->first->key);
p=p->next;
}
return;
}
int main()
{
struct list *A=createList();
addFirst(A,"1");
addFirst(A,"2");
addFirst(A,"4");
copyPlus(A,"3");
printf("=%s= \n",A->first->key); //this one works!
printf("=%s= \n",A->first->next->key);
printf("=%s= \n",A->first->next->next->key);
showList(A);
deleteList(A);
}
I skipped the irrelevant stuffs, it's a classic list.
Node is defined that way :
struct node
{
struct node *next;
char *key;
};
After further ivestigation it appears that the process is working correctly (the two //printf in copyPlus work the way they should). And the last //printf doesn't display anything, even if I do A->first->next->next->next.
It shows 3 if I do A->first->next->next->next->next.
I really don't understand and it's starting to get on my nerves, the code is simple and short and I'm still not seeing the mistake.
Could someone help me? Thanks.
Ok, so strcat adds a terminating zero to the string, you need space for one more char. strlen will give you 1, you will allocate a char array with size 2. That's not enough - you need at least 3 for the first char, second char and terminating zero. That's still dangerous, as you don't know the length of the second string. The best solution is thus char* cat = malloc(len1 + len2 + 1).
The current problem is that char cat[len1+2]; is allocating space on the stack (that's where local function variables reside). You're basically keeping a pointer to an address inside of a stack frame, which gets destroyed after the function has finished. The first value works, because this was your last function call and still noone has decided to overwrite this memory (but anyone is free to do so). Allocating with malloc() will allocate on the heap and the value will be available until you explicitly call free.
After modifications output is:
[43]
{43}
[23]
{23}
[13]
{13}
=13=
=23=
=43=
13 23 43 3 4 2 1
A C++ solution can be found at http://pastebin.com/xNzyLQ2N .