Pointers and structs - c

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dictionary.h"
#define HASH_SIZE 100
// prototype
int hash(char *word);
// counter
int counter;
// node
typedef struct
{
char *word;
node *next;
} node;
// hash table
node *hashtable[HASH_SIZE];
bool
load(const char *dictionary)
{
// open the dictionary
FILE *dict = fopen(dictionary, "r");
if(dict == NULL)
{
printf("Could not open %s.\n", dictionary);
return false;
}
// set all values in the hash table to null
for(int i = 0; i < HASH_SIZE; i++)
{
hashtable[i] = NULL;
}
// set the counter to 0
counter = 0;
// iterate through the words in the dictionary
while (!feof(dict))
{
// get word into a string
char gotcha[LENGTH];
fscanf(dict, "%s", gotcha);
// declare a node and allocate memory
node n;
n.word = malloc( strlen(gotcha)*sizeof(char) );
// save the word into the node
strcpy(n.word, gotcha);
// hash the word, baby!
int hash_value = hash(n.word);
// start saving addresses to the hashtable
n.next = hashtable[hash_value];
hashtable[hash_value] = &n;
//test
int len = strlen(n.word);
printf("%s\n", n.word);
printf("%i\n", len);
// that's one more!
counter++;
}
fclose(dict);
return true;
}
I am receiving the following two errors on these two lines of code:
n.next = hashtable[hash_value];
hashtable[hash_value] = &n;
dictionary.c:89:16: error: assignment from incompatible pointer type [-Werror]
dictionary.c:90:31: error: assignment from incompatible pointer type [-Werror]
How do I save pointer values in these two places? I am new to this, so please bear that in mind. :)

In your structure, the type node is not yet defined. Change it to use the structure tag:
typedef struct node
{
char *word;
struct node *next;
} node;

This:
typedef struct
{
char *word;
node *next;
} node;
is a syntax error. The node *next; occurs before the end of the typedef that creates node as a type. If your compiler for some reason accepted this, it probably thinks there are 2 different types called "node" now, which explains why one of them isn't compaible with the other. You should give up on that typedef silliness (structs generally shouldn't be typedef'ed) and just use
struct node
{
char *word;
struct node *next;
};

Define typedef names of structs before defining the structs. This allows mutually referring structs without concern for order and doesn't require inconsistent definitions, sometimes with the struct keyword and sometimes without it. Note that in C++ you can do away with the typedef line entirely:
typedef struct node node;
struct node
{
char* word;
node* next;
};

Related

Structure with pointer for string

I have a char pointer in the structure to store names.When I inserted the values and printed the last value of name is getting printed for all nodes.
typedef struct tests{
int id;
char *p;
struct tests *next;
}test;'
'void add(test **root,int id,char *name){
test *newnode=(test* )malloc(sizeof(test));
newnode->id=id;
newnode->p=name;
newnode->next=NULL;
test *curr;
curr=(*root);
if((*root)==NULL){
(*root)=newnode;
}
else{
while(curr->next!=NULL){
curr=curr->next;
}
curr->next=newnode;
}
}
Most likely what you intend to achieve is something along these lines:
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
typedef struct test_s {
int id;
char *p;
struct test_s *next;
} test_t;
test_t** add(test_t **root, int id, char const *name){
size_t len = strlen(name);
test_t *newnode=(test_t*)malloc(sizeof(test_t)+len+1); // 1 goes for \0 terminator
newnode->id=id;
strcpy(newnode->p=(void*)(newnode+1), name);
newnode->next=NULL;
test_t **tail = root;
while (*tail) {
tail = &(*tail)->next;
}
*tail = newnode;
return &(newnode->next);
}
Problem with your code is, you never copied your string assigning just a single pointer instead.
Take a look at pointers mechanics once again, additionally I would advise you to check string.h reference.

how to make structs point to different strings?

I have a struct and in that a struct i have a character pointer but and i am creating different instances of this struct but when i am changing the pointer in one struct the other is also changing.
#include <stdio.h>
#include <stdlib.h>
typedef struct human{
int age;
char name[100];
} Human;
int main(){
FILE *s = fopen("h.txt","r");
if(s==NULL){
printf("file not available");
}
for(int i=0 ;i<5;i++){
Human h;
fscanf(s,"%d",&h.age);
fscanf(s,"%s",h.name);
insertintolinkedlist(h);
// this method is going to insert the human into the linked list
}
return 0;
}
what is happening that all humans in the linked list have different ages but same name!
You need to allocate memory to hold the name.
char* name is just a pointer - it has no memory for saving the name.
You change it to
char name[100];
Remember to check that the names you put into Human.name isn't longer than 100 characters.
To use a linked list you can do something like:
typedef struct human{
int age;
char name[100];
struct human* next;
} Human;
int main()
{
Human* head = NULL;
Human* tail = NULL;
for(.....)
{
Human* h = malloc(sizeof(Human));
if (head == NULL) head = h;
if (tail != NULL)
{
tail->next = h;
}
tail = h;
h->next = NULL;
h->age = ....;
strncpy(h->age, "..name..", 100);
}
// ..... other code
// Remember to free all allocated memory
}

Dereferencing Pointer to incomplete type Linked List - C

I've been trying to figure this out for a while now, but cannot find a solution. I am building a linked list and when I try to pass the list as a pointer to anything I get an error: Dereferencing Pointer to incomplete type.
Here is my struct declaration
typedef struct listStruct{
char *name;
int size;
boolean inRestStatus;
list *next;
}list;
and one of the many functions that do not work.
void addToList(list *l, char * name, int size){
list *tmp;
while(l->next != NULL){
l = l->next;
}
tmp = malloc(sizeof(list));
tmp->name = name;
tmp->size = size;
tmp->inRestStatus = NO;
tmp->next = NULL;
l->next = tmp;
}
and the header
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct listStruct list;
I have tried changing the struct declaration to
typedef struct listStruct list{
...
};
and received the error: request for member in something not structure or union.
If anyone has any ideas that'd be awesome.
Edit
The struct definition is/was in a main function in a seperate file than the function, I have since moved the definition to the header file.
It seems that you declared only typedef name in the header
typedef struct listStruct list;
Thus the module where function
void addToList(list *l, char * name, int size);
is defined does not know the definition of the structure.
You have to include the structure definition in the header as for example
typedef struct listStruct{
char *name;
int size;
boolean inRestStatus;
struct listStruct *next;
}list;
that it would be accessible in the module where the function is defined.
Take into account that this method
void addToList(list *l, char * name, int size){
list *tmp;
while(l->next != NULL){
l = l->next;
}
tmp = malloc(sizeof(list));
tmp->name = name;
tmp->size = size;
tmp->inRestStatus = NO;
tmp->next = NULL;
l->next = tmp;
}
is also wrong. For example l can be equal to NULL can't it?
Also simple copying pointers
tmp->name = name;
looks questionably. Should you allocate memory to store a copy of a string pointed to by argument name?
Apparently, you placed your struct declaration into some implementation file, and a wrong implementation file at that.
The typedef declaration that you have in your header
typedef struct listStruct list;
declares an incomplete type. You have to place this
typedef struct listStruct{
char *name;
int size;
boolean inRestStatus;
list *next;
} list;
into the header or at least into the same implementation file that uses the data fields of your struct. Where is it now? You have to describe your file structure in full detail.

error: invalid type argument of '->' (have 'struct node')

Why cant i access the pointer "Cells" like an array ? i have allocated the appropriate memory why wont it act like an array here? it works like an array for a pointer of basic data types.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define MAX 10
struct node
{
int e;
struct node *next;
};
typedef struct node *List;
typedef struct node *Position;
struct Hashtable
{
int Tablesize;
List Cells;
};
typedef struct Hashtable *HashT;
HashT Initialize(int SIZE,HashT H)
{
int i;
H=(HashT)malloc(sizeof(struct Hashtable));
if(H!=NULL)
{
H->Tablesize=SIZE;
printf("\n\t%d",H->Tablesize);
H->Cells=(List)malloc(sizeof(struct node)* H->Tablesize);
should it not act like an array from here on?
if(H->Cells!=NULL)
{
for(i=0;i<H->Tablesize;i++)
the following lines are the ones that throw the error
{ H->Cells[i]->next=NULL;
H->Cells[i]->e=i;
printf("\n %d",H->Cells[i]->e);
}
}
}
else printf("\nError!Out of Space");
}
int main()
{
HashT H;
H=Initialize(10,H);
return 0;
}
The error I get is as in the title-error: invalid type argument of '->' (have 'struct node').
A correct version of your code is given below. It is always advisable not to use pointers while using typedef.
The only problem with your code apart from that was your access method.
H->cells[i]->next will throw an error.
Also H->cells->[i]e was invalid syntax.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define MAX 10
struct node
{
int e;
struct node *next;
};
typedef struct node List;
typedef struct node Position;
struct Hashtable
{
int Tablesize;
List *Cells;
};
typedef struct Hashtable HashT;
HashT Initialize(int SIZE,HashT *H)
{
int i;
H=(HashT*)malloc(sizeof(struct Hashtable));
if(H!=NULL)
{
H->Tablesize=SIZE;
printf("\n\t%d",H->Tablesize);
H->Cells=(List*)malloc(sizeof(List)*H->Tablesize);
//should it not act like an array from here on?
if(H->Cells!=NULL)
{
for(i=0;i<H->Tablesize;i++)
//the following lines are the ones that throw the error
{
H->Cells[i].next=NULL;
H->Cells[i].e=i;
printf("\n %d",H->Cells[i].e);
}
}
}
else printf("\nError!Out of Space");
return *H;
}
int main()
{
HashT H;
H=Initialize(10,&H); //return is not required as already we are passing by address
return 0;
}
The
H->Cells[i]->next
should be
H->Cells[i].next
(Similarly for e.)
This is a version of your program without the typedefs. Which one is more readable?
#include <stdio.h>
#include <stdlib.h>
struct node {
struct node *next;
int e;
};
struct Hashtable {
unsigned Tablesize;
struct node *Cells;
};
struct Hashtable *Initialize(unsigned size)
{
unsigned iii;
struct Hashtable *hp;
hp = malloc (sizeof *hp);
if(!hp) {
fprintf(stderr, "Error!Out of Space\n");
return NULL;
}
hp->Cells = malloc(size * sizeof *hp->Cells );
if(!hp->Cells) {
hp->Tablesize = 0;
return hp;
}
hp->Tablesize = size;
fprintf(stderr, "\t%u\n", hp->Tablesize);
for(iii=0; iii < hp->Tablesize; iii++) {
hp->Cells[iii].next = NULL;
hp->Cells[iii].e = iii;
fprintf( stderr, " %u\n", hp->Cells[iii].e);
}
return hp;
}
int main()
{
struct Hashtable *hashtab;
hashtab = Initialize(10);
return 0;
}
The changes:
removed the typedefs; since they are confusing
removed the casts from malloc() not needed and potentially dangerous.
changed the sizes to unsigned. A size can never be negative
diagnostic output should go to stderr.
a few of levels of indentation can be avoided by doing the error-case first, and returning early from the function on error.

Dynamic array of linked lists in C

Basically I have to store words in linked list with each character having its own node. I get really confused with nested structures. How do I go to the next node? I know i'm doing this completely wrong which is why I'm asking.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
char letter;
}NODE;
typedef struct handle
{
NODE **arr;
}HANDLE;
HANDLE * create();
void insert(handle **, char, int);
int main(int argc, char **argv)
{
FILE *myFile;
HANDLE *table = (HANDLE *)malloc(sizeof(HANDLE));
NODE *linked = (NODE *)malloc(sizeof(NODE));
int counter = 0;
linked = NULL;
table->arr[0] = linked;
char c;
myFile = fopen(argv[argc], "r");
while((c = fgetc(myFile)) != EOF)
{
if(c != '\n')
insert(&table, c, counter);
else
{
counter++;
continue;
}
}
}
void insert(HANDLE **table, char c, int x)
{
(*table)->arr[x]->letter = c; //confused on what to do after this or if this
//is even correct...
}
You have a linked list of words with each word being a linked list of characters. Am I right? If so, it is better to use the names for what they are:
typedef struct char_list
{
char letter;
struct char_list * next;
} word_t;
typedef struct word_list
{
word_t * word;
struct word_list_t * next;
} word_list_t;
Now, you can populate the lists as per need.
For a linked-list, you typically have a link to the next node in the node structure itself.
typedef struct node
{
char letter;
struct node *next;
}NODE;
Then from any given node NODE *n, the next node is n->next (if not NULL).
insert should scan the list until it finds an n->next that is NULL, and allocate a new node at the end (make sure to set its next to NULL).
You may want to have a function to initialize a new list given the table index, and a separate function to initialize a new node.

Resources