linked list && structures - c

I would like to know if design of my program is correct, as well as to understand if my commented area is doing what it supposed to be doing. I get these compile errors that are associated probably with commented segments of my code, and I would lie to receive some help. THANKS!
part1.c:15:6: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'insert'
part1.c: In function 'main':
part1.c:43:14: error: incompatible types when assigning to type 'struct point' from type 'int'
part1.c:49:44: error: invalid type argument of '->' (have 'struct point')
part1.c:49:59: error: invalid type argument of '->' (have 'struct point')
part1.c:55:5: error: incompatible type for argument 1 of 'free'
/usr/include/stdlib.h:488:13: note: expected 'void *' but argument is of type 'struct point'
char *chars[3]= {"a","b","c"};
int nums[3]= {5,8,9};
struct point {char *letter;
int number;
struct point *next;};
struct point* insert(struct point list[],char *rqdLetters, int rqdNums)
{
struct point *new;
new = (struct point*)malloc(sizeof(struct point));
if(new == NULL)
fprintf(stderr,"error!");
new->letter = rqdLetters;
new->number = rqdNums;
new->next = head;
head = new;
//not sure if i'm returning the a pointer to the start of new list
return head;
}
int main(int argc, char **argv)
{
//not sure if i need to declare these here or in the insert
struct point list[3];
struct point *head = NULL;
struct point *next;
struct point *new;
int i;
for (i = 0; i < 3; i++)
{
//return result put back into the pointer to the start of the list
head[i] = insert(list[i], chars[i], nums[i]);
}
int j;
for(j = 0; j < 3; j++)
{
printf("letter %s and number %d\n", list[j]->letter, list[j]->number);
}
int z;
for(z = 0; z < 3; z++)
{
free(list[z]);
}
return 0;
}

At a glance, there are several issues with your code. Firstly, you're not declaring your variables correctly.
new = list;
should be:
struct point* new;
Your function signature also looks a little suspect. If you're returning a pointer to your data structure, it should be something like:
struct point* insert(...) { ... }
At a more general level, I does seem like your idea of a linked list may be a little off. To represent a list, you should only need to hold on to the head and tail of the list, instead of keep an array of your points.
It usually helps if you create a data structure to hold these pointers. You can then pass this structure around to functions that operate on the list e.g. the insert() function.
As a quick example (untested):
struct node {
struct node *next;
char letter;
int number;
}
struct list {
struct node *head;
struct node *tail;
}
/* create a new list */
struct list* list_new(void) {
struct list *L = malloc(sizeof(struct list));
L->head = NULL;
L->tail = NULL;
}
/* add a new node to the list */
void list_insert(struct list *list, char in_letter, int in_number) {
struct node *node = malloc(sizeof(struct node));
node->letter = in_letter;
node->number = in_number;
node->next = NULL;
if (list->head == NULL) { /* empty list */
list->head = node;
list->tail = node;
} else { /* append to list */
list->tail->next = node;
list->tail = node;
}
}
You can then use it as such:
int i;
char chars[3]= {"a","b","c"};
int nums[3]= {5,8,9};
struct list *mylist = list_new();
for (i = 0; i < 3; i++)
{
list_insert(mylist, chars[i], nums[i]);
}
In response to:
... and i am not sure if i am supposed to declare it inside insert or main, i did in the main however
This depends on where you intend to use the variables and the intended lifespan of these variables. As stated in the comments above, you might want to polish up on your understanding of scoping rules.

Related

Code is printing pointer address (I think) instead of value?

I have a list defined as
typedef struct node {
Voo *voo;
ListaReservas nodeReservas; /* Ignore this */
struct node *next;
} *Node;
I created some functions to help me add or remove nodes from the list like:
/* creates a node */
Node criaNode(Voo v) {
Node new = (Node)malloc(sizeof(struct node));
new->voo = &v;
/* I had new->voo = v; but vscode told me it was wrong so i changed it to &v */
new->next = NULL;
return new;
}
Voo is defined as:
typedef struct {
int dia;
int mes;
int ano;
} Data;
typedef struct {
int horas;
int minutos;
} Tempo;
typedef struct {
char codigo[LEN_CODIGO + 1];
char partidaID[LEN_ID + 1];
char chegadaID[LEN_ID + 1];
Data datapartida;
Tempo horapartida;
Tempo duracao;
Data datachegada;
Tempo horachegada;
int capacidade;
} Voo;
Now I wanted to iterate through the list and print its values as such
Voo *v;
for (n = headVoos; n != NULL; n = n->next) {
v = n->voo;
printf("%s %s %s %.2d-%.2d-%d %.2d:%.2d\n",
v->codigo, v->partidaID, v->chegadaID,
v->datapartida.dia, v->datapartida.mes, v->datapartida.ano,
v->horapartida.horas, v->horapartida.minutos);
}
The program is not printing correctly. For example where it should appear
AA1 AAA AAD 16-03-2022 14:50
its appearing instead
� 146187376-32765--1940381952 40355300:50
What's causing this and how can I avoid it in the future?
EDIT
After replacing in the struct node the Voo *voo definition by Voo voo, I am now getting an error in one of the auxiliary functions:
/* deletes node */
Node eliminaNode(Node head, Voo v)
{
Node n, prev;
for (n = head, prev = NULL; n != NULL; prev = n, n = n->next)
{
if (n->voo == v) /* expression must have arithmetic or pointer error */
{
if (n == head)
head = n->next;
else
prev->next = n->next;
free(n->next);
free(n);
break;
}
}
return head;
}
In criaNode you're taking the address of the parameter v and returning it from the function via a pointer to dynamic memory. That address is no longer valid after the function returns. Subsequently dereferencing that invalid address then triggers undefined behavior.
It probably makes more sense for struct node to contain a Voo directly instead of a pointer to one. So change the member to a non-pointer:
Voo voo;
And assign the parameter directly:
new->voo = v;
There are multiple problems here:
there seems to be a confusion between structures and pointers to structures. In C, you must understand the difference between manipulating objects (allocating as local objects or from the head, passing as arguments or returning as values) and pointers to objects, which are a more idiomatic as arguments to functions and allow functions to modify the object they point to.
the confusion is amplified by a very error prone construction: hiding pointers behind typedefs. Do not do that, define object types for the actual structure, using the same or a different name as the struct tag, and make all pointers explicit with the * syntax.
you pass an actual Voo object as an argument and allocate a list node using the address of this argument. This is incorrect because the argument will be discarded as soon as the function returns, makeing the list point to invalid memory and explaining the weird output you observe.
Node eliminaNode(Node head, Voo v) should take a pointer to the head node and return a success indicator. It should take a Voo * argument and it should not free(n->next) because the next node is still in use after the removal.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#define LEN_CODIGO 30
#define LEN_ID 30
typedef struct Data {
int dia;
int mes;
int ano;
} Data;
typedef struct Tempo {
int horas;
int minutos;
} Tempo;
typedef struct Voo {
char codigo[LEN_CODIGO+ 1];
char partidaID[LEN_ID + 1];
char chegadaID[LEN_ID + 1];
Data datapartida;
Tempo horapartida;
Tempo duracao;
Data datachegada;
Tempo horachegada;
int capacidade;
} Voo;
typedef struct Node {
struct Voo *voo;
//ListaReservas nodeReservas; /* Ignore this */
struct Node *next;
} Node;
/* creates a node */
Node *criaNode(Voo *v) {
/* allocation with calloc is safer as the object will be initialized to 0 */
Node *nodep = calloc(1, sizeof(*new));
if (nodep) {
nodep->voo = v;
nodep->next = NULL;
}
return nodep;
}
/* deletes node */
int eliminaNode(Node **head, Voo *v) {
for (Node *n = *head, *prev = NULL; n != NULL; prev = n, n = n->next) {
if (n->voo == v) {
if (n == *head)
*head = n->next;
else
prev->next = n->next;
free(n);
return 1; /* article was found and freed */
}
}
return 0; /* article was not found */
}
void printList(const Node *head) {
for (const Node *n = head; n != NULL; n = n->next) {
const Voo *v = n->voo;
printf("%s %s %s %.2d-%.2d-%.2d %.2d:%.2d\n",
v->codigo, v->partidaID, v->chegadaID,
v->datapartida.dia, v->datapartida.mes, v->datapartida.ano,
v->horapartida.horas, v->horapartida.minutos);
}
}

Incompatible pointer type warning whit in self referencied structs, trying to implement a hash table

I'm trying to implement a hash table with pointers to a double-linked list that stores the information in C language. The problem is that i keep getting warnings from the compiler that I don't understand why. The warnings are all "warning: assignment from incompatible pointer type "
Here are my structs:
typedef struct stru_contacto_list{
char *nome;
char *email;
char *telefone;
struct stru_contacto_list *prev, *next;
}contacto_list;
typedef struct stru_contacto{
contacto_list *info;
struct stru_contact *next_hash;
}contacto_hash;
typedef struct{
contacto_hash **val;
}hash_tableC;
Here is some code for you to understand better what is hapening:
Initializing the hash table
void initContactos(hash_tableC *c){
int i;
c->val =
(contacto_hash**)malloc(sizeof(contacto_hash)*DEFAULTSIZE);
for(i = 0; i < DEFAULTSIZE; i++){
c->val[i] = NULL;
}
}
Here's some code from where I get the warnings, here im am trying to add a 'contact_hash' to the hash table by putting it in the head of the linked list associated to the index in the hash_table.
void addContact(){
int index, flag;
contacto_hash *novo =
(contacto_hash*)malloc(sizeof(contacto_hash));
contacto_list *novoL =
(contacto_list*)malloc(sizeof(contacto_list));
flag = addContactToList(novoL);
if (flag){
free(novo);
return;
}
novo->info = novoL;
novo->next_hash = NULL;
index = hashing(novoL->nome);
if (contactos->val[index] != NULL)
novo->next_hash = contactos->val[index]; /* THE WARNING*/
contactos->val[index] = novo;
}
Some other small piece of code where I get the same "warning : assignment from incompatible pointer type " :
contacto_hash* find(char *nome, int indice){
/*Returns the previous contact_hash i want to find*/
contacto_hash *atual, *prev;
if (contactos->val[indice] == NULL)
return NULL;
atual = contactos->val[indice];
prev = atual;
while (atual != NULL) {
if (strcmp(atual->info->nome, nome) == 0){
return prev;
}
prev = atual;
atual = atual->next_hash; /* THE WARNING */
}
return NULL;
}
The warning from the compiler is "warning: assignment from incompatible pointer type"

dereferencing error in linked list - not typedef error

I can't find my dereferencing error to save my life. As far as I can see I've got all my declarations where they need to be and can't see where I have defined a bad structure.
EDIT: the paste is missing a ton of the code, but it includes all of the code that uses the pointers. everything else is checking to make sure the file is the right file, right location, error handling, etc.
typedef struct list{
int pid;
char *name;
struct list* link;
}LIST;
void begin(FILE *file, char *argv[])
{
struct LIST *root, *p, *tail;
struct utmp x[BUFF];
root = NULL;
char *name;
int c;
int i;
struct utmp hold;
int pid;
tail = malloc(sizeof(LIST));
int logins = 0;
int logouts = 0;
for (i=0;i<=BUFF;i++)
{
c = fread(x, sizeof(struct utmp), BUFF, file);
if (strcmp(x[i].ut_user, argv[1]) == 0)
{
if (x[i].ut_type == 7)
{
hold = x[i];
logins++;
pid = x[i].ut_pid;
name = hold.ut_user;
p = create(pid, name); //<--Line 129
if (root == NULL)
{
root = tail = p;
}
else
{
tail->link = p; //<---Line 136
tail = p;
}
printf("%d\n", p->pid); //<---Line 139
}
}
if (x[i].ut_pid == pid && x[i].ut_type == 8)
{
pid = 0;
logouts++;
}
}
LIST *create(int pid, char *name)
{
LIST *p;
p = malloc(sizeof(LIST));
p->pid = pid;
p->link = NULL;
p->name = name;
return p;
}
The error:
main.c: In function ‘begin’:
main.c:129:10: warning: assignment from incompatible pointer type [enabled by default]
main.c:136:9: error: dereferencing pointer to incomplete type
main.c:139:24: error: dereferencing pointer to incomplete type
Your issue is with confusing how to use structs and typedefs. Your definition
typedef struct list{
...
}LIST;
creates 2 data types the structure struct list and its typedef equivalent LIST. Then when you declare your variables, you use struct LIST, which isn't defined. This is generating all 3 of your errors. The compiler is assuming that you are defining this struct somewhere else. The reason that people use typedef is to make the later use of struct unnecessary.

incompatible pointer type error C

So I'm trying to implement a cache in C. I have included a very slimmed down version of my code.
I keep getting this error:
prog.c: In function ‘addtolist’:
prog.c:29: warning: assignment from incompatible pointer type
prog.c:40: warning: assignment from incompatible pointer type
prog.c: In function ‘main’:
prog.c:72: warning: assignment from incompatible pointer type
from this code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct node_
{
char * word;
int filenumber;
struct node * next;
};
typedef struct node_ * node;
node createnode()
{
node head;
head = malloc(sizeof(struct node_));
head->word = NULL;
head->next = NULL;
return head;
}
unsigned int addtolist(node head, char * word, unsigned int limit, int fileno)
{
unsigned int templimit = limit;
node temp;
node temphead = head;
while(temphead->next != NULL)
{
temphead = temphead->next;
}
temp = malloc(sizeof(struct node_));
temp->word =(char*) malloc(strlen(word)+ 1);
strcpy(temp->word, word);
temp->next = NULL;
temp->filenumber = fileno;
templimit = templimit - (strlen(word) + 1) - sizeof(struct node_)- sizeof(int);
printf("templimit is size %u\n", templimit);
if (templimit < limit && templimit > 0)
{
temphead->next = temp;
limit = limit - strlen(word) - 1 - sizeof(struct node_)- sizeof(int);
return limit;
}
else
{
free(temp->word);
free(temp);
return 0;
}
}
int main()
{
node newlist = createnode();
int i = 0;
unsigned int limit = 65;
unsigned int temp = limit;
while(temp > 0 && temp <= limit)
{
temp = addtolist(newlist, "Hello", temp, i);
i++;
printf("new limit is - \t%u\nfilenumber is - \t%d\n", temp,i);
}
node ptr = newlist;
while(ptr->next != NULL)
{
printf("node %d contains the word %s\n", ptr->filenumber, ptr->word);
ptr = ptr->next;
}
return 1;
}
I honestly can't figure out what I'm doing wrong... My logic was that, since I was typedef'ing my struct as a pointer, after I created the struct in memory, I would be able to easily step through the ensuing list. Where was the flaw in my logic?
EDIT the initial problem was fixed (I forgot an underscore in my type declaration for struct node_ next;.
Now I'm having another problem: when I try to step through the list at the bottom of my code to print out the words contained in the list, I'm basically not able to step through the list. I keep outputting:
templimit is size 43
new limit is - 43
filenumber is - 1
templimit is size 21
new limit is - 21
filenumber is - 2
templimit is size 4294967295
new limit is - 0
filenumber is - 3
node 0 contains the word (null)
node 0 contains the word Hello
For some reason, it seems that my program isn't storing my changes to my list in memory after the first iteration. Any ideas on what I'm doing wrong?
Once again, any help would be appreciated, and thanks.
Inside your structure definition you have struct node without the underscore.
you'd better have a forward declaration
typedef struct node node;
and then declare your structure
struct node {
...
node *next;
};
no need to have this underscore stuff and hiding the * in a typedef. That only makes you mix things up easily.
String literals "like this" have type const char*, not char*, because they're immutable.
Fix your declarations to have const char* and the warnings will go away.
I think the struct member 'next' has to be declared as a (node_ *) type. As written it is currently (node_ **)

Passing argument from incompatible pointer type warning

I've been trying to figure out pointers in C most of today, even asked a question earlier, but now I'm stuck on something else. I've got the following code:
typedef struct listnode *Node;
typedef struct listnode {
void *data;
Node next;
Node previous;
} Listnode;
typedef struct listhead *LIST;
typedef struct listhead {
int size;
Node first;
Node last;
Node current;
} Listhead;
#define MAXLISTS 50
static Listhead headpool[MAXLISTS];
static Listhead *headpoolp = headpool;
#define MAXNODES 1000
static Listnode nodepool[MAXNODES];
static Listnode *nodepoolp = nodepool;
LIST *ListCreate()
{
if(headpool + MAXLISTS - headpoolp >= 1)
{
headpoolp->size = 0;
headpoolp->first = NULL;
headpoolp->last = NULL;
headpoolp->current = NULL;
headpoolp++;
return &headpoolp-1; /* reference to old pointer */
}else
return NULL;
}
int ListCount(LIST list)
{
return list->size;
}
Now in a new file I have:
#include <stdio.h>
#include "the above file"
main()
{
/* Make a new LIST */
LIST *newlist;
newlist = ListCreate();
int i = ListCount(newlist);
printf("%d\n", i);
}
When I compile, I get the following warning (the printf statement prints what it should):
file.c:9: warning: passing argument 1 of ‘ListCount’ from incompatible pointer type
Should I be worried about this warning? The code seems to do what I want it to, but I'm obviously very confused about pointers in C. After browsing questions on this site, I found that if I make the argument to ListCount (void *) newlist, I don't get the warning, and I don't understand why, nor what (void *) really does...
Any help would be appreciated, thanks.
You're getting confused because of multiple typedefs. LIST is a type representing a pointer to struct listhead. So, you want your ListCreate function to return a LIST, not a LIST *:
LIST ListCreate(void)
The above says: ListCreate() function will return a pointer to a new list's head if it can.
Then you need to change the return statement in the function definition from return &headpoolp-1; to return headpoolp-1;. This is because you want to return the last available head pointer, and you have just incremented headpoolp. So now you want to subtract 1 from it and return that.
Finally, your main() needs to be update to reflect the above changes:
int main(void)
{
/* Make a new LIST */
LIST newlist; /* a pointer */
newlist = ListCreate();
int i = ListCount(newlist);
printf("%d\n", i);
return 0;
}

Resources