i'm trying to adapt the example code from this site https://www.codesdope.com/blog/article/making-a-queue-using-linked-list-in-c/
but i can't get it to work properly, when changing the node datatype to somesting "more complex"
thought it would be simple but when i call display it outputs all "0"
// #include "include/main.h"
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define QUEUE_SIZE 30
typedef float dataArray[20];
struct node
{
dataArray *data;
struct node *next;
};
typedef struct node node;
struct queue
{
int count;
node *front;
node *rear;
};
typedef struct queue queue;
void initialize(queue *q);
int is_empty(queue *q);
void enqueue(queue *q, dataArray value);
void dequeue(queue *q, dataArray *outputArray);
void display(node *head);
float random_float();
void initialize(queue *q)
{
q->count = 0;
q->front = NULL;
q->rear = NULL;
}
int is_empty(queue *q)
{
return (q->rear == NULL);
}
void enqueue(queue *q, dataArray value)
{
if (q->count == QUEUE_SIZE)
{
dataArray tmp;
dequeue(q, &tmp);
free(tmp);
}
node *tmp;
tmp = malloc(sizeof(node));
printf("[enqueue] sizeof node %d\r\n", (uint) sizeof(node));
// memcpy(tmp->data, value, sizeof(value));
tmp->data = &value;
tmp->next = NULL;
printf(" contents of value in enqueue\n");
for (int i = 0; i < 20; i++)
{
printf("%f\n", value[i]);
}
printf(" contents of tmp-node in enqueue\n");
for (int i = 0; i < 20; i++)
{
printf("%f\n", tmp->data[i]);
}
if (!is_empty(q))
{
q->rear->next = tmp;
q->rear = tmp;
}
else
{
q->front = q->rear = tmp;
}
q->count++;
}
void dequeue(queue *q, dataArray *outputArray)
{
node *tmp;
outputArray = q->front->data;
printf("dequeue output before freeing memory\r\n===========\r\n");
for (int i = 0; i < 20; i++)
{
printf("%f\n", outputArray[i]);
}
printf("[dequeue] size %d - %d\r\n", (uint) sizeof(q->front->data), (uint) sizeof(q->front->data[0]));
tmp = q->front;
q->front = q->front->next;
q->count--;
free(tmp);
}
void display(node *head)
{
if (head == NULL)
{
printf("NULL\r\n");
}
else
{
for (int i = 0; i < 20; i++)
{
printf("%f\n", head->data[i]);
}
display(head->next);
}
}
float random_float()
{
srand((unsigned int)time(NULL));
float a = 50.0;
return ((float)rand() / (float)(RAND_MAX)) * a;
}
int main()
{
queue *q;
q = malloc(sizeof(queue));
initialize(q);
srand((unsigned int)time(NULL));
dataArray tmp;
for (int i = 0; i < 20; i++)
{
tmp[i] = random_float();
}
printf("display dataArray before fill\r\n===========\r\n");
for (int i = 0; i < 20; i++)
{
printf("%f\n", tmp[i]);
}
enqueue(q, tmp);
printf("Queue display after init and fill\r\n===========\r\n");
// THIS WILL PRINT 0 <<<<--------------------------------------- what it shouldn't
display(q->front);
printf("Queue before dequeue\r\n===========\r\n");
printf("Queue #1 element count: %d\r\n", q->count);
// Nächsten Queue Eintrag holen
dataArray *queData = malloc(sizeof(dataArray));
dequeue(q, queData);
printf("Queue after dequeue\r\n===========\r\n");
printf("Queue #1 element count: %d\r\n", q->count);
for (int i = 0; i < 20; i++)
{
printf("%f\n", queData[i]);
}
return 0;
}
does anybody know what i'm doing wrong?
(also first i wanted to give enqueue the pointer of my temp-array so it don't has to copy it but that worked even worse)
EDIT
this is the version where i'm passing the pointer of the array to enqueue, but in this version even within enqueue the output is not correct (only for the first value of the array)
// #include "include/main.h"
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define QUEUE_SIZE 30
typedef float dataArray[20];
struct node
{
dataArray *data;
struct node *next;
};
typedef struct node node;
struct queue
{
int count;
node *front;
node *rear;
};
typedef struct queue queue;
void initialize(queue *q);
int is_empty(queue *q);
void enqueue(queue *q, dataArray *value);
void dequeue(queue *q, dataArray *outputArray);
void display(node *head);
float random_float();
void initialize(queue *q)
{
q->count = 0;
q->front = NULL;
q->rear = NULL;
}
int is_empty(queue *q)
{
return (q->rear == NULL);
}
void enqueue(queue *q, dataArray *value)
{
if (q->count == QUEUE_SIZE)
{
dataArray tmp;
dequeue(q, &tmp);
free(tmp);
}
printf(" contents of value in enqueue\n");
for (int i = 0; i < 20; i++)
{
printf("%f\n", *value[i]);
}
node *tmp;
tmp = malloc(sizeof(node));
printf("[enqueue] sizeof node %d\r\n", (uint) sizeof(node));
// memcpy(tmp->data, &value, sizeof(value));
tmp->data = value;
tmp->next = NULL;
printf(" contents of tmp-node in enqueue\n");
for (int i = 0; i < 20; i++)
{
printf("%f\n", tmp->data[i]);
}
if (!is_empty(q))
{
q->rear->next = tmp;
q->rear = tmp;
}
else
{
q->front = q->rear = tmp;
}
q->count++;
}
void dequeue(queue *q, dataArray *outputArray)
{
node *tmp;
outputArray = q->front->data;
printf("dequeue output before freeing memory\r\n===========\r\n");
for (int i = 0; i < 20; i++)
{
printf("%f\n", outputArray[i]);
}
printf("[dequeue] size %d - %d\r\n", (uint) sizeof(q->front->data), (uint) sizeof(q->front->data[0]));
tmp = q->front;
q->front = q->front->next;
q->count--;
free(tmp);
}
void display(node *head)
{
if (head == NULL)
{
printf("NULL\r\n");
}
else
{
for (int i = 0; i < 20; i++)
{
printf("%f\n", head->data[i]);
}
display(head->next);
}
}
float random_float()
{
srand((unsigned int)time(NULL));
float a = 50.0;
return ((float)rand() / (float)(RAND_MAX)) * a;
}
int main()
{
queue *q;
q = malloc(sizeof(queue));
initialize(q);
srand((unsigned int)time(NULL));
dataArray tmp;
for (int i = 0; i < 20; i++)
{
tmp[i] = random_float();
}
printf("display dataArray before fill\r\n===========\r\n");
for (int i = 0; i < 20; i++)
{
printf("%f\n", tmp[i]);
}
enqueue(q, &tmp);
printf("Queue display after init and fill\r\n===========\r\n");
display(q->front);
printf("Queue before dequeue\r\n===========\r\n");
printf("Queue #1 element count: %d\r\n", q->count);
// Nächsten Queue Eintrag holen
dataArray *queData = malloc(sizeof(dataArray));
dequeue(q, queData);
printf("Queue after dequeue\r\n===========\r\n");
printf("Queue #1 element count: %d\r\n", q->count);
for (int i = 0; i < 20; i++)
{
printf("%f\n", queData[i]);
}
return 0;
}
"yes that would explain why the first example won't work, but the second SHOULD" -- No, no it won't.
First, enable Full Warnings in your compiler1. Now try and compile your second example. Notice the problems in all of your attempted printf() statements where %f expects a double arguments, but you are passing float * (a pointer to float). Why aren't there more descriptive errors? What do the comments under your question say to remove? (hint: your typedef is masking errors)
So go to your second example and comment the typedef, e.g.
// typedef float dataArray[20];
Why was that causing problems? Look at your parameters, e.g.
void enqueue(queue *q, dataArray *value) { ...
What is your dataArray *value? It's float *value[20]; What's that? It is float *[20], an array of 20 pointers to float. When you assign tmp->data = value; what are you assigning? C18 - 6.3.2.1 Lvalues, arrays, and function designators(p3) tells you. value is converted to a pointer to it's first element (a pointer-to-pointer-to float, e.g. float**). What is tmp->data? It is an array of pointers to float and it is not an lvalue -- see 6.3.2.1(p1). You cannot assign to an array, but your typedef is masking the problem.
Now remove your typedef (throughout your code) and try again, e.g.:
void enqueue(queue *q, float *value[20])
{
if (q->count == QUEUE_SIZE)
{
float tmp[20];
dequeue(q, &tmp);
// free(tmp); /* you can't free what's not allocated */
}
printf(" contents of value in enqueue\n");
for (int i = 0; i < 20; i++)
{
printf("%f\n", *value[i]);
}
node *tmp;
tmp = malloc(sizeof(node));
printf("[enqueue] sizeof node %d\r\n", (uint) sizeof(node));
// memcpy(tmp->data, &value, sizeof(value));
tmp->data = value;
tmp->next = NULL;
...
(you had memcpy(), you were closer there but your types are messed up)
It doesn't work. Now the compiler easily sees the attempt to assign to a non-lvalue and provides a proper diagnostic:
source.c:65:15: error: assignment to expression with array type
tmp->data = value;
^
That problem runs throughout your code. Where does the mismatch begin? In main(). Look at what you are trying to pass to enqueue(), e.g.
int main()
{
...
dataArray tmp; /* e.g. float tmp[20] */
...
enqueue(q, &tmp);
...
}
When you take the address of tmp the type is float (*)[20], a pointer-to-array-of float[20], not an array-of-pointers-to float (20 of them). A pointer-to-array has type float (*)[20] while the array-of-pointers* is float *[20] -- completely different types and pointer arithmetic is completely different between the two.
So when you pass &tmp with enqueue(q, &tmp); (where tmp is passed as value to void enqueue(queue *q, dataArray *value)) and then do value[i] in your first loop, for values of i > 0, you invoke undefined behavior reading beyond the end of the array (passed as a pointer-to-array, value[1] is one past the end of your array tmp in main() of float[20])
Can You Make It Work?
Yes, just fix the types and remove the second call to srand() in random_float() that is messing up your fill and fix your memcpy() call. (there are numerous other small issues, memory not validated and memory not freed, etc..) Carrying the removal of your typedef through the rest of your code and making the types consistent, you would end up with something like:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define QUEUE_SIZE 30
#define ASZ 20
// typedef float dataArray[20];
typedef unsigned uint;
struct node
{
float data[ASZ];
struct node *next;
};
typedef struct node node;
struct queue
{
int count;
node *front;
node *rear;
};
typedef struct queue queue;
void initialize(queue *q);
int is_empty(queue *q);
void enqueue(queue *q, float *value);
void dequeue(queue *q, float *outputArray);
void display(node *head);
float random_float();
void initialize(queue *q)
{
q->count = 0;
q->front = NULL;
q->rear = NULL;
}
int is_empty(queue *q)
{
return (q->rear == NULL);
}
void enqueue(queue *q, float *value)
{
if (q->count == QUEUE_SIZE)
{
float tmp[ASZ];
dequeue(q, tmp);
// free(tmp);
}
printf(" contents of value in enqueue\n");
for (int i = 0; i < ASZ; i++)
{
printf("%f\n", value[i]);
}
node *tmp;
tmp = malloc(sizeof(node));
printf("[enqueue] sizeof node %d\r\n", (uint) sizeof(node));
// memcpy(tmp->data, &value, sizeof(value));
memcpy (tmp->data, value, ASZ * sizeof *value);
tmp->next = NULL;
printf(" contents of tmp-node in enqueue\n");
for (int i = 0; i < ASZ; i++)
{
printf("%f\n", tmp->data[i]);
}
if (!is_empty(q))
{
q->rear->next = tmp;
q->rear = tmp;
}
else
{
q->front = q->rear = tmp;
}
q->count++;
}
void dequeue(queue *q, float *outputArray)
{
node *tmp;
outputArray = q->front->data;
printf("dequeue output before freeing memory\r\n===========\r\n");
for (int i = 0; i < ASZ; i++)
{
printf("%f\n", outputArray[i]);
}
printf("[dequeue] size %d - %d\r\n", (uint) sizeof(q->front->data),
(uint) sizeof(q->front->data[0]));
tmp = q->front;
q->front = q->front->next;
q->count--;
free(tmp);
}
void display(node *head)
{
if (head == NULL)
{
printf("NULL\r\n");
}
else
{
for (int i = 0; i < ASZ; i++)
{
printf("%f\n", head->data[i]);
}
display(head->next);
}
}
float random_float()
{
float a = 50.0;
return ((float)rand() / (float)(RAND_MAX)) * a;
}
int main()
{
queue *q;
q = malloc(sizeof(queue));
initialize(q);
srand((unsigned int)time(NULL));
float tmp[ASZ];
for (int i = 0; i < ASZ; i++)
{
tmp[i] = random_float();
}
printf("display dataArray before fill\r\n===========\r\n");
for (int i = 0; i < ASZ; i++)
{
printf("%f\n", tmp[i]);
}
enqueue(q, tmp);
printf("Queue display after init and fill\r\n===========\r\n");
display(q->front);
printf("Queue before dequeue\r\n===========\r\n");
printf("Queue #1 element count: %d\r\n", q->count);
// Nächsten Queue Eintrag holen
float *queData = malloc(sizeof(float[ASZ]));
dequeue(q, queData);
printf("Queue after dequeue\r\n===========\r\n");
printf("Queue #1 element count: %d\r\n", q->count);
for (int i = 0; i < ASZ; i++)
{
printf("%f\n", queData[i]);
}
return 0;
}
Example Use/Output
Now your second example compiles without warning and, to the extent the logic is correct, produces reasonable output (whether it is correct is left to you to determine), e.g.
$ ./bin/llqueue
display dataArray before fill
===========
5.864568
15.599927
1.622677
6.834927
18.953743
43.170605
37.056793
21.260620
44.568668
41.187069
43.298340
8.273252
13.328741
33.927246
32.561504
14.666824
20.176983
30.163134
21.064775
8.606315
contents of value in enqueue
5.864568
15.599927
1.622677
6.834927
18.953743
43.170605
37.056793
21.260620
44.568668
41.187069
43.298340
8.273252
13.328741
33.927246
32.561504
14.666824
20.176983
30.163134
21.064775
8.606315
[enqueue] sizeof node 88
contents of tmp-node in enqueue
5.864568
15.599927
1.622677
6.834927
18.953743
43.170605
37.056793
21.260620
44.568668
41.187069
43.298340
8.273252
13.328741
33.927246
32.561504
14.666824
20.176983
30.163134
21.064775
8.606315
Queue display after init and fill
===========
5.864568
15.599927
1.622677
6.834927
18.953743
43.170605
37.056793
21.260620
44.568668
41.187069
43.298340
8.273252
13.328741
33.927246
32.561504
14.666824
20.176983
30.163134
21.064775
8.606315
NULL
Queue before dequeue
===========
Queue #1 element count: 1
dequeue output before freeing memory
===========
5.864568
15.599927
1.622677
6.834927
18.953743
43.170605
37.056793
21.260620
44.568668
41.187069
43.298340
8.273252
13.328741
33.927246
32.561504
14.666824
20.176983
30.163134
21.064775
8.606315
[dequeue] size 80 - 4
Queue after dequeue
===========
Queue #1 element count: 0
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
-0.001425
Note: this isn't an effort to correct ALL of the issues with your code. This merely gets you back on track from your typedef fiasco. While there are times where typedef'ing arrays makes sense (for experienced kernel developers, etc..), it's not something to do lightly for the reasons explained below. Pointers should not be typedef'ed either. See Is it a good idea to typedef pointers?.
footnotes:
Always compile with warnings enabled, and do not accept code until it compiles without warning. To enable warnings add -Wall -Wextra -pedantic to your gcc/clang compile string (also consider adding -Wshadow to warn on shadowed variables). Turn on -Werror to treat all warnings as errors. For VS (cl.exe on windows), use /W3. All other compilers will have similar options. Read and understand each warning -- then go fix it. The warnings will identify any problems, and the exact line on which they occur. You can learn a lot by listening to what your compiler is telling you.
Related
Following this tutorial on Hash Tables, I implemented a sort of simplified version. However, whenever delete_entry is called on every 4th index(4,8,12...), I get a segmentation fault. Else, it works fine
Here's the code I run:
#include <stdio.h>
typedef struct {
int key;
int value;
} entry;
typedef struct{
int length;
int count;
entry** items;
} table;
entry *new_entry(const int, const int);
table *create_table();
void destroy_table(table *t);
void delete_entry(entry *e);
void table_insert(table *, const int, const int);
int main(){
table *new_table = create_table();
printf("[INFO] Created new table successfully!!\n");
for(int i=0; i<16; i++){
table_insert(new_table,i,i+i);
}
printf("[INFO] Inserted %d items\n",new_table->count);
destroy_table(new_table);
printf("[INFO] Destroyed table successfully!!\n");
return 0;
}
table *create_table(){
table *new_table = malloc(sizeof(table));
if(new_table == NULL){
printf("[WARNING] Malloc failure, returning NULL");
return NULL;
}
new_table->length = 16;
new_table->count = 0;
new_table->items = calloc((size_t)new_table->length, sizeof(entry*));
return new_table;
}
entry *new_entry(const int k, const int val){
entry *new_item = malloc(sizeof(entry));
if(new_item == NULL){
printf("[WARNING] Malloc failure, returning NULL");
return NULL;
}
new_item->key = k;
new_item->value = val;
return new_item;
}
void destroy_table(table *t){
for(int i=0; i<t->count; i++){
if(i== 4 || i == 8|| i==12) //Without this program terminates after 3rd index
continue;
entry *e = t->items[i];
if (e != NULL){
delete_entry(e);
}
}
free(t->items);
free(t);
}
void delete_entry(entry *e){
free(e->key);
free(e->value);
free(e);
}
void table_insert(table *t, const int k, const int v){
entry *e = new_entry(k, v);
t->items[t->count] = e;
t->count++;
}
Try to replace delete_entry() with:
void delete_entry(entry *e){
free(e);
}
Freeing values of integers e->key and e->value will likely result in Undefined Behavior. You should use free() only on objects produced by malloc() and friends.
so basically I wrote a program to initialize, insert, and output the whole hash table. I thought I did pretty good, but there's many issues.
First issue being, some names are displayed with an additional weird character, why??
Second issue being, I can only input a size parameter (for initialize(size) function) of <8. Anything above 7 will output "Out of Space!" but why?? I thought I managed the space pretty well from what I was taught at uni:((
Please help!
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list_node *node_ptr;
struct list_node
{
node_ptr next;
char *key;
char *value;
};
typedef node_ptr LIST;
typedef node_ptr position;
struct hash_table
{
LIST *list_ptr_arr;
unsigned int table_size;
};
typedef struct hash_table *HASHTABLE;
unsigned long long int
hash(const char *key, unsigned int hash_size)
{
unsigned long long int hash;
for(int i = 0; key[i]; i++)
{
hash = (hash<<32)+key[i];
}
return (hash%hash_size);
}
unsigned int
next_prime(int number)
{
int j;
for(int i = number; ; i++)
{
for(j = 2; j<i; j++)
{
if(i%j == 0){break;}
}
if(i==j){return j;}
}
}
HASHTABLE
initialize(unsigned int table_size)
{
HASHTABLE H;
H = (HASHTABLE) malloc(sizeof(struct hash_table));
if(H==NULL){printf("Out of Space!"); return 0;}
H->table_size = next_prime(table_size);
H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
if(H->list_ptr_arr==NULL){printf("Out of Space!"); return 0;}
H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);
for(unsigned int i = 0; i<H->table_size; i++)
{
if(H->list_ptr_arr[i]==NULL){printf("Out of Space!"); return 0;}
H->list_ptr_arr[i]=NULL;
}
return H;
}
position
set(const char *key, const char *value)
{
position entry = (position) malloc(sizeof(struct list_node));
entry->value = (char*) malloc(strlen(value)+1);
entry->key = (char*) malloc(strlen(key)+1);
strncpy(entry->key,key,strlen(key));
strncpy(entry->value,value,strlen(value));
entry->next = NULL;
return entry;
}
void
insert(const char *key, const char *value, HASHTABLE H)
{
unsigned int slot = hash(key, H->table_size);
node_ptr entry = H->list_ptr_arr[slot];
node_ptr prev;
if(entry==NULL)
{
H->list_ptr_arr[slot] = set(key, value);
return;
}
while(entry!=NULL)
{
if(strcmp(entry->key, key)==0)
{
free(entry->value);
entry->value = malloc(strlen(value)+1);
strncpy(entry->value,value,strlen(value));
return;
}
prev = entry;
entry = prev->next;
}
prev->next = set(key, value);
}
void
dump(HASHTABLE H)
{
for(unsigned int i = 0; i<H->table_size; i++)
{
position entry = H->list_ptr_arr[i];
if(H->list_ptr_arr[i]==NULL){continue;}
printf("slot[%d]: ", i);
for(;;)
{
printf("%s|%s -> ", entry->key, entry->value);
if(entry->next == NULL)
{
printf("NULL");
break;
}
entry = entry->next;
}
printf("\n");
}
}
int main()
{
HASHTABLE H = initialize(7);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
Then I tried to change it up a bit:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list_node *node_ptr;
struct list_node
{
node_ptr next;
char *key;
char *value;
};
typedef node_ptr LIST;
typedef node_ptr position;
struct hash_table
{
LIST *list_ptr_arr;
unsigned int table_size;
};
typedef struct hash_table *HASHTABLE;
unsigned long long int
hash(const char *key, unsigned int hash_size)
{
unsigned long long int hash;
for(int i = 0; key[i]; i++)
{
hash = (hash<<32)+key[i];
}
return (hash%hash_size);
}
unsigned int
next_prime(int number)
{
int j;
for(int i = number; ; i++)
{
for(j = 2; j<i; j++)
{
if(i%j == 0){break;}
}
if(i==j){return j;}
}
}
HASHTABLE
initialize(unsigned int table_size)
{
HASHTABLE H;
H = (HASHTABLE) malloc(sizeof(struct hash_table));
if(H==NULL){printf("Out of Space!1"); return 0;}
H->table_size = next_prime(table_size);
H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
if(H->list_ptr_arr==NULL){printf("Out of Space!2"); return 0;}
H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);
for(unsigned int i = 0; i<H->table_size; ++i)
{
if(H->list_ptr_arr[i]==NULL){printf("Out of Space!3"); return 0;}
H->list_ptr_arr[i]->value="HEAD";
H->list_ptr_arr[i]->next=NULL;
}
return H;
}
void
insert(const char *key, const char *value, HASHTABLE H)
{
unsigned int slot = hash(key, H->table_size);
LIST entry = H->list_ptr_arr[slot], newNode;
newNode = (position) malloc(sizeof(struct list_node));
if(newNode==NULL){printf("Out of Space4!"); return;}
newNode->next = entry->next;
strncpy(newNode->key,key,strlen(key));
strncpy(newNode->value,value,strlen(value));
entry->next = newNode;
}
void
dump(HASHTABLE H)
{
for(unsigned int i = 0; i<H->table_size; i++)
{
position entry = H->list_ptr_arr[i];
position p = entry->next;
if(p==NULL){continue;}
printf("slot[%d]: ", i);
for(;;)
{
printf("%s|%s -> ", p->key, p->value);
if(p->next == NULL)
{
printf("NULL");
break;
}
p = p->next;
}
printf("\n");
}
}
int main()
{
HASHTABLE H = initialize(4);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
Thank you!
I modified the second piece of code, it runs correctly on my computer.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 256
// typedefing struct list_node multiple times is confusing, so I remove these typedefs
struct list_node {
struct list_node *next;
// strings need storage space in the memory,
// declaring key and value as array here can save some calls to malloc()
char key[MAX_SIZE];
char value[MAX_SIZE];
};
struct hash_table {
struct list_node **list_ptr_arr;
unsigned int table_size;
};
// it's better not to hide pointer type using typedef
typedef struct hash_table HASHTABLE;
unsigned long long int hash(const char *key, unsigned int hash_size) {
// hash is not initialized originally (the value is choosed randomly)
unsigned long long int hash = 5;
for (int i = 0; key[i]; i++) {
hash = (hash << 32) + key[i];
}
return (hash%hash_size);
}
unsigned int next_prime(int number) {
int j;
for (int i = number; ; i++) {
for (j = 2; j < i; j++) {
if (i%j == 0) { break; }
}
if (i == j) { return j; }
}
}
HASHTABLE *initialize(unsigned int table_size) {
HASHTABLE *H;
// you don't need to type cast malloc() result in C
H = malloc(sizeof(*H));
H->table_size = next_prime(table_size);
// I suppose list_ptr_arr is a pointer to an array of struct list_node * object
H->list_ptr_arr = malloc(sizeof(*(H->list_ptr_arr)) * H->table_size);
for (unsigned int i = 0; i < H->table_size; ++i) {
// malloc() for H->list_ptr_arr only allocated area for struct list_node * array, the struct list_node pointed to is not allocated yet, so malloc() here
H->list_ptr_arr[i] = malloc(sizeof(*(H->list_ptr_arr[i])));
strcpy(H->list_ptr_arr[i]->value, "HEAD");
H->list_ptr_arr[i]->next = NULL;
}
return H;
}
void insert(const char *key, const char *value, HASHTABLE *H) {
unsigned int slot = hash(key, H->table_size);
struct list_node *entry = H->list_ptr_arr[slot], *newNode;
newNode = malloc(sizeof(*newNode));
newNode->next = entry->next;
// strlen() doesn't count the '\0', just use strcpy here
strcpy(newNode->key, key);
strcpy(newNode->value, value);
entry->next = newNode;
}
void dump(HASHTABLE *H) {
for (unsigned int i = 0; i < H->table_size; i++) {
struct list_node *entry = H->list_ptr_arr[i];
struct list_node *p = entry->next;
if (p == NULL) { continue; }
printf("slot[%d]: ", i);
for (;;) {
printf("%s|%s -> ", p->key, p->value);
if (p->next == NULL) {
printf("NULL");
break;
}
p = p->next;
}
printf("\n");
}
}
int main() {
HASHTABLE *H = initialize(4);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
P.S. Don't forget to free the hashtable.
Basically I made a create_app() function to allocate 2 nodes in the stack, each having a pointer to an array[max]; undo() pops the last element, and before returning it, it adds it into the REDO node's array. redo() does the opposite, pops the last element in it's array, putting it into Undo's array before returning it. What did I do wrong ?
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node *node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack != NULL){printf("Out of space!");}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return(S->tos==-1);
}
int
isFull(STACK S)
{
return(S->tos>=S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
int
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
int
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Some small errors were in your code, like these ones in create_app() which seem like typos.
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
^
|
if(UNDO->arr_stack != NULL){printf("Out of space!");}
^
|
...
and some int returning functions did not return anything in the else part which gave some warnings.
Here is the modified code, which worked fine for me
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node* node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack = (int *) malloc(max * sizeof(int));
REDO->arr_stack = (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack == NULL){printf("Out of space!");
return NULL;}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return (S->tos == -1);
}
int
isFull(STACK S)
{
return (S->tos >= S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
void
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
void
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Result:
3223
However, always take precaution in deallocating the memory malloced using free().
Hi am trying to create a generic list iterator that stores elements of integer or string.I am trying to test a case where it calls the IteratorG advance(IteratorG it, int n) function which takes in the list it and if n is a positive integer,it advances(moves) towards the first element by n times.If n is negative,it advances towards the last element in the list by n times.The elements are then copied to a newly created list lis and the list returned.If advancing by n times is not possible,the function returns NULL.
This is tested in test case 3 under the test cases below.
However,it is responding with a segmentation fault error and i tried using gdp to diagnose the problem and i suspect it is from the advance function at the line add(lis,&(tem->value));
This is the advance function:
IteratorG advance(IteratorG it, int n){
int zero;
zero=0;
IteratorG lis;
lis = malloc(sizeof (struct IteratorGRep));
assert (lis != NULL);
lis->numofit = 0;
lis->head = NULL;
lis->tail = NULL;
lis->curr = NULL;
Node *tem;
if ((tem = malloc(sizeof(Node))) == NULL) {
return 0;
}
if(n<0 && distanceFromStart(it)!=0 )
{
for(tem=it->curr;n!=zero;it->curr=it->curr->prev)
{
add(lis,&(tem->value));
zero++;
}
return lis;
}
if(n>0 && distanceToEnd(it)!=0)
{
for(tem=it->curr;n!=zero;it->curr=it->curr->next)
{
add(lis,&(tem->value));
zero++;
}
return lis;
}
//To be implemented
//move forward by n times
return NULL;
}
I am using a Linux environment and the errors are indicative from the results. The rest of the functions that are required to test this(test in test case 3 under the test code) should be working fine.Here is the code for the whole program:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "iteratorG.h"
typedef struct Node {
void *value; // value of thee list item
struct Node *prev;
// pointer previous node in list
struct Node *next;
// pointer to next node in list
// implemented struct here ..
} Node;
typedef struct IteratorGRep {
int numofit; // count of items in list
Node *head; // first node in list
Node *curr; // current node in list
Node *tail; // last node in list
ElmCompareFp cmpElm;
ElmNewFp newElm;
ElmFreeFp freeElm;
// implemented struct here ..
} IteratorGRep;
/*
//Your functions below ....
*/
IteratorG newIterator(ElmCompareFp cmpFp, ElmNewFp newFp, ElmFreeFp freeFp){
IteratorG newit;
if ((newit = malloc(sizeof (struct IteratorGRep)))==NULL)
{
printf("Error...! \n");
}
//assert (newit != NULL);
newit->numofit = 0;
newit->head = NULL;
newit->tail = NULL;
newit->curr = NULL;
newit->cmpElm=cmpFp;
newit->newElm=newFp;
newit->freeElm=freeFp;
return newit;
// implemented function here and changed return value
}
int add(IteratorG it, void *vp){
Node *temp;
if ((temp = malloc(sizeof(Node))) == NULL) {
return 0;
}
Node *tempe;
if ((temp = malloc(sizeof(Node))) == NULL) {
return 0;
}
temp->value = it->newElm(vp);
//temp->next=NULL;
if(it->curr==NULL)
{
//temp->next=it->curr;
it->head=it->tail=temp;
it->curr=temp;
}
else
{
tempe=it->curr;
tempe->prev=temp;
temp->next=tempe;
it->curr=tempe;
it->curr=temp;
it->head=temp;
}
//it->tail=it->head=it->curr;
return 1;
}
int hasNext(IteratorG it){
if(it->curr->next==NULL)
{
return 0;
}
// check if theres next element/node
return 1;
}
int hasPrevious(IteratorG it){
if(it->curr->prev!=NULL)
{
return 1;
}
// check if theres previous element/node
return 0;
}
void *next(IteratorG it){
Node *tempo;
if(it->curr->next==NULL)
{
return NULL;
}
tempo=it->curr;
it->curr=it->curr->next;
// implemented function here
return tempo->value;
}
void *previous(IteratorG it){
Node *tempor;
tempor=it->curr;
if(tempor->prev==NULL)
{
return NULL;
}
tempor=it->curr->prev;
it->curr=it->curr->prev;
//tempor=it->curr;
// move to next node in list
return tempor->value;
}
int del(IteratorG it){
if(it->curr->prev!=NULL)
{
Node *temp_curr=it->curr;
Node *temp_prev=it->curr->prev->prev;
temp_curr->prev=temp_prev;
temp_prev->next=temp_curr;
return 1;
}// delete previous node from list
else
return 0;
}
int set(IteratorG it, void *vp){
if(it->curr->prev!=NULL)
{
it->curr->prev->value=vp;
return 1;
}
// change previous node value with new
return 0;
}
IteratorG advance(IteratorG it, int n){
int zero;
zero=0;
IteratorG lis;
lis = malloc(sizeof (struct IteratorGRep));
assert (lis != NULL);
lis->numofit = 0;
lis->head = NULL;
lis->tail = NULL;
lis->curr = NULL;
Node *tem;
if ((tem = malloc(sizeof(Node))) == NULL) {
return 0;
}
if(n<0 && distanceFromStart(it)!=0 )
{
for(tem=it->curr;n!=zero;it->curr=it->curr->prev)
{
add(lis,tem);
zero++;
}
return lis;
}
if(n>0 && distanceToEnd(it)!=0)
{
for(tem=it->curr;n!=zero;it->curr=it->curr->next)
{
add(lis,&(tem->value));
zero++;
}
return lis;
}
//To be implemented
//move forward by n times
return NULL;
}
void reverse(IteratorG it){
Node *curr = it->head;
Node *temp = NULL;
while(curr != NULL) {
temp = curr->next;
curr->next = curr->prev;
curr->prev = temp;
curr = temp;
}
temp = it->head;
it->head = it->tail;
it->tail = temp;// reverse elements of whole list
}
IteratorG find(IteratorG it, int (*fp) (void *vp) ){
// To be implemented
// Find elements of vp in list after current position and put in new list.return the list.
return NULL;
}
int distanceFromStart(IteratorG it){
Node *c=it->curr;
int count=0;
while(c->prev!=NULL)
{
c=c->prev;
count++;
}
return count;
// count number of elements from start of list to current position
}
int distanceToEnd(IteratorG it){
Node *cu=it->curr;
int count=0;
while(cu->next!=NULL)
{
cu=cu->next;
count++;
}
return count;
// count number of elements from end of list to current position
}
void reset(IteratorG it){
while(it->curr->prev!=NULL)
{
it->curr=it->curr->prev;
}
return;
// move current position to start of list
}
void freeIt(IteratorG it){
assert(it != NULL);
Node *curr, *prev;
curr = it->head;
while (curr != NULL) {
prev = curr;
curr = curr->next;
// free(prev->value);
free(prev);
}
free(it); // free items
}
This is the header file for the code:
#ifndef LISTITERATORG_H
#define LISTITERATORG_H
#include <stdio.h>
typedef struct IteratorGRep *IteratorG;
typedef int (*ElmCompareFp)(void const *e1, void const *e2);
typedef void *(*ElmNewFp)(void const *e1);
typedef void (*ElmFreeFp)(void *e1);
IteratorG newIterator(ElmCompareFp cmpFp, ElmNewFp newFp, ElmFreeFp freeFp);
int add(IteratorG it, void *vp);
int hasNext(IteratorG it);
int hasPrevious(IteratorG it);
void *next(IteratorG it);
void *previous(IteratorG it);
int del(IteratorG it);
int set(IteratorG it, void *vp);
IteratorG advance(IteratorG it, int n);
void reverse(IteratorG it);
IteratorG find(IteratorG it, int (*fp) (void *vp) );
int distanceFromStart(IteratorG it);
int distanceToEnd(IteratorG it);
void reset(IteratorG it);
void freeIt(IteratorG it);
#endif
One of the functions have yet to be implemented and is indicated in the code itself. But I guess that might not be the source of issue here.
EDIT:
heres the test case code. Theres no errors in the test case code just in the program above only :
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "iteratorG.h"
#include "positiveIntType.h"
#include "stringType.h"
#define MAXARRAY 5
/* Helper Functions Below */
/* Returns 1 if marks >= 50, 0 otherwise */
int passMarks(void *marks){
return (*((int *) marks) >= 50);
/* Easy to understand below ..
int *ip = (int *) marks;
if(*ip >= 50) { return 1; }
else { return 0; }
*/
}
/* Returns 1 if str starts with "jo" */
int prefixJo(void *str){
return (strncmp("jo", (char *) str, 2) == 0) ;
}
/* A function to print a string from a void pointer */
void prnStr(void *vp){
assert(vp != NULL);
printf(" %s", (char *) vp );
}
/* A function to print an integer from a void pointer */
void prnInt(void *vp){
assert(vp != NULL);
printf(" %d", *((int *) vp) );
}
/* Prints previous element using the given function 'fp'
examples: prnPrev(it1, prnInt); prnPrev(it2, prnStr);
*/
void prnPrev(IteratorG it, void (*fp) (void *p) ){
void *prevP = previous(it);
assert(prevP != NULL);
printf("> Previous value is: ");
fp(prevP);
printf("\n");
}
/* Prints next element using the given function 'fp'
examples: prnNext(it1, prnInt); prnNext(it2, prnStr);
*/
void prnNext(IteratorG it, void (*fp) (void *p) ){
void *nextP = next(it);
assert(nextP != NULL);
printf("> Next value is: ");
fp(nextP);
printf("\n");
}
/* Prints elements of 'it' from current to last position
using the given function 'fp'. The current position
of 'it' will change to the end of the list.
examples: prnIt(it1, prnInt); prnIt(it2, prnStr);
*/
void prnIt(IteratorG it, void (*fp) (void *p) ){
int count = 0;
while(hasNext(it)){
void *nextP = next(it);
count++;
if(count > 1) { printf(", "); }
fp(nextP);
}
printf("\n");
}
/* Few Tests Below */
void test1(){
printf("\n--==== Test-01 ====------\n");
IteratorG it1 = newIterator(positiveIntCompare, positiveIntNew, positiveIntFree);
int a[MAXARRAY] = { 25, 78, 6, 82 , 11};
for(int i=0; i<MAXARRAY; i++){
int result = add(it1 , &a[i]);
printf("> Inserting %d: %s \n", a[i], (result==1 ? "Success" : "Failed") );
}
freeIt(it1);
printf("--==== End of Test-01 ====------\n");
}
void test2(){
printf("\n--==== Test-02 ====------\n");
IteratorG it1 = newIterator(positiveIntCompare, positiveIntNew, positiveIntFree);
int a[MAXARRAY] = { 72, 14, 62, 8, 93};
for(int i=0; i<MAXARRAY; i++){
int result = add(it1 , &a[i]);
printf("> Inserting %d: %s \n", a[i], (result==1 ? "Success" : "Failed") );
}
prnNext(it1, prnInt);
prnNext(it1, prnInt);
prnPrev(it1, prnInt);
int newVal1 = 55;
int result1 = set(it1, &newVal1);
printf("> Set value: %d ; return val: %d \n", newVal1, result1 );
prnPrev(it1, prnInt);
freeIt(it1);
printf("--==== End of Test-02 ====------\n");
}
void test3(){
printf("\n--==== Test-03 ====------\n");
IteratorG it1 = newIterator(positiveIntCompare, positiveIntNew, positiveIntFree);
int a[MAXARRAY] = { 04, 54, 15, 12, 34};
for(int i=0; i<MAXARRAY; i++){
int result = add(it1 , &a[i]);
printf("> Inserting %d: %s \n", a[i], (result==1 ? "Success" : "Failed") );
}
reset(it1);
printf("> it1 (after reset): \n");
prnIt(it1, prnInt);
reset(it1);
IteratorG advIt1 = advance(it1, 4);
printf("> advance(it1, 4) returns: \n");
prnIt(advIt1, prnInt);
//IteratorG advIt2 = advance(it1, -3);
//printf("> advance(it1, -3) returns: \n");
//prnIt(advIt2, prnInt);
//printf("> In 'it1', ");
//prnPrev(it1, prnInt);
freeIt(it1);
//freeIt(advIt1);
//freeIt(advIt2);
printf("--==== End of Test-03 ====------\n");
}
int main(int argc, char *argv[])
{
test1();
test2();
test3();
return EXIT_SUCCESS;
}
Okay so i have this Queue implementation that works, but i'm having some memory leak that doesn't let a if else operations runs after that.
File queue_arr.h
#define MaxQ 100
typedef struct {
int array[MaxQ];
int front;
int back;
int size;
}*Queue;
Queue init();
int enqueue(Queue q, int v);
int dequeue(Queue q, int *v);
int front(Queue q, int *v);
int isEmpty(Queue q);
File queue_arr.c
#include "queue_arr.h"
#include <stdlib.h>
#include <stdio.h>
Queue init() {
Queue q = (Queue)malloc(sizeof(Queue));
q->front = 0;
q->back = 0;
q->size = 0;
return q;
}
int enqueue(Queue q, int v) {
if(q->size==MaxQ)
return 0;
q->array[q->back] = v;
q->back++;
if(q->back == MaxQ)
q->back = 0;
q->size++;
return 1;
}
int dequeue(Queue q, int *v) {
if(q->size == 0)
return 0;
*v = q->array[q->front];
q->front++;
if(q->front == MaxQ)
q->front =0;
q->size--;
return 1;
}
int front(Queue q, int *v) {
if(q->size==0)
return 0;
*v = q->array[q->front];
return 1;
}
int isEmpty(Queue q) {
if(q->size == 0)
return 1;
return 0;
}
int main(){
Queue teste = init();
int *aux;
*aux = -1;
printf("Value : %d\n",*aux );
enqueue(teste,5);
enqueue(teste,10);
enqueue(teste,15);
front(teste,aux);
printf("Next costumer: %d\n",*aux );
dequeue(teste,aux);
printf("Costumer %d left queue\n",*aux );
dequeue(teste,aux);
printf("Costumer %d left queue\n",*aux );
dequeue(teste,aux);
printf("Costume %d left queue\n",*aux );
int random = 10;
if(random == 10)
printf("asdasdasd\n");
}
The last if and else statement doest not work, i noticed cause i was trying to do a isEmpty if clause, and keep leading me to segmentation fault.
Without the last three lines, the code compiles and runs, with no errors. But with that i just keep getting a segmentation fault.
Does anybody knows the problem ?
Your code can't decide whether a Queue is a pointer to something or the something.
typedef struct {
int array[MaxQ];
int front;
int back;
int size;
}*Queue;
This says a Queue is a pointer to a bunch of things.
Queue q = (Queue)malloc(sizeof(Queue));
q->front = 0;
This allocates enough bytes to hold a Queue, which is just a pointer, and then attempts to use the thing it points to. But you never allocated space for anything but a pointer.
Queue q = (Queue)malloc(sizeof(Queue));
Congratulations, sizeof(Queue) is 4 (or 8) bytes since it's a pointer.
Your segmentaion fault because of this
int *aux;
*aux = -1;
you should
aux = malloc(sizeof(int));
before
*aux = -1;
but I don't think that is what you want, instead you should just do it
int aux = -1;
and when calling dequeue
dequeue(teste, &aux);
Also I would recomend you fix these other issues
You don't need to cast malloc
You should check that malloc didn't return NULL otherwise you will dereference a
NULL pointer which is undefined behavior.
Also, your malloc call is passing the wrong size. A possible fix is to use
Queue q = malloc(sizeof(*q));
But I would actually recommend to avoid hiding the fact that variables are pointers completely.
You do have a memory leak but that is not a cause for a segmentaion fault, you should just call free(teste) at the end of main().
Your main() doesn't return you should, also add return 0; at the end of main() after free()
I fixed your code, hope this helps
#include <stdlib.h>
#include <stdio.h>
#define MaxQ 100
typedef {
int array[MaxQ];
int front;
int back;
int size;
} *Queue;
Queue init() {
Queue q = malloc(sizeof(*q));
if (q == NULL)
return NULL;
q->front = 0;
q->back = 0;
q->size = 0;
return q;
}
int enqueue(Queue q, int v) {
if (q == NULL)
return 0;
if(q->size==MaxQ)
return 0;
q->array[q->back] = v;
q->back++;
if(q->back == MaxQ)
q->back = 0;
q->size++;
return 1;
}
int dequeue(Queue q, int *v) {
if (q == NULL)
return 0;
if(q->size == 0)
return 0;
*v = q->array[q->front];
q->front++;
if(q->front == MaxQ)
q->front =0;
q->size--;
return 1;
}
int front(Queue q, int *v) {
if (q == NULL)
return 0;
if(q->size==0)
return 0;
*v = q->array[q->front];
return 1;
}
int isEmpty(Queue q) {
if (q == NULL)
return 0;
if(q->size == 0)
return 1;
return 0;
}
int main(){
Queue teste = init();
if (teste == NULL)
return -1;
int aux;
aux = -1;
printf("Value : %d\n", aux);
enqueue(teste,5);
enqueue(teste,10);
enqueue(teste,15);
front(teste, &aux);
printf("Next costumer: %d\n", aux );
dequeue(teste, &aux);
printf("Costumer %d left queue\n", aux );
dequeue(teste, &aux);
printf("Costumer %d left queue\n", aux );
dequeue(teste, &aux);
printf("Costume %d left queue\n", aux );
int random = 10;
if(random == 10)
printf("asdasdasd\n");
free(teste);
return 0;
}