dynamically allocate arrays of pointers to structures in C - c

I have this structure here:
typedef struct _open {
int x;
struct _open *next;
} *NODE;
And on my main function I declared this pointer:
NODE open = initOpen(size);
Here's the initOpen function:
NODE initOpen(int size) {
return (NODE)malloc(sizeof(struct _open)*size);
}
I this correct? can I access my array in the main function like: open[0] to open[9] ?

First of all, the way you are doing dynamically allocated array is wrong.
I'm not sure if you actually want the thing you wrote, which is linked list, or the thing you said, which is dynamically allocated array.
Below is how you should do dynamically allocated array. Hope it helps.
By doing so, you can add as many ints into the array as you want, before you run out of memory. And you can access the array using array notation but with a pointer first: darray->array[0]
Your linked list, however, can not be accessed with this syntax.
#include <stdio.h>
#include <stdlib.h>
#define INITSIZE 8
typedef struct dyarr{
int num;
int max;
int *array;
}arr;
arr* makeArr();
void add( arr*, int );
int main( int argc, char const *argv[] ){
int t;
arr* darray = makeArr();
while( scanf( "%d", &t ) != EOF ){
add( darray, t );
}
int i;
for( i = 0; i<darray->num; i++ ){
printf( "%d\n", darray->array[i] );
}
getchar();
return 0;
}
arr* makeArr(){
arr* A = malloc( sizeof( arr ) );
A->max = MAXSIZE;
A->num = 0;
A->array = malloc( sizeof( int )*A->max );
return A;
}
void add( arr* a, int i ){
if( a->num == a->max ){
a->max *= 2;
a->array = realloc( a->array, a->max );
}
a->array[a->num++] = i;
}

First of all, you should respect some conventions:
typedef struct node {
int x;
struct node *next;
} *nodePtr;
Second, what is the usage of the parameter size ?
According to me the right way to allocate a new nodePtr is:
nodePtr initNodePtr() {
return (nodePtr)malloc(sizeof(struct node));
}
Also dont forget to release memory after usage:
nodePtr node = initNodePtr();
...
...
free(node); //should be wrapped in a function to respect design.
To Create an array of structure, you should do the following:
typedef struct {
int x;
node* next;
} node;
int main() {
node* nodeArray = (node*)malloc(sizeof(node)*50); // 50 = size of your array
...
// do whatever you want
...
free(nodeArray);
}
Not tested, let me know if errors.

Related

Error in stack with linked list implementation

I'm trying to implement stack using linked list implementation. Its giving me "Segmentation Error". Please help me finding the error. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct NODE {
char word;
struct NODE *next;
};
struct STACK {
struct NODE *head;
int size;
};
void pushStack(struct STACK *stack, char s);
void makeStack(struct STACK *stack, char *s);
void printStack(struct STACK *stack);
int main(){
char *s;
fgets(s,100,stdin);
struct STACK stack;
stack.head = NULL;
makeStack(&stack,s);
printStack(&stack);
return 0;
}
void pushStack(struct STACK *stack, char s){
struct NODE temp;
temp.word = s;
temp.next = stack->head;
stack->head = &temp;
}
void makeStack(struct STACK *stack, char *s){
char temp[MAX];
strcpy(temp,s);
for(int i=0; i<MAX; i++){
if(temp[i]=='\0') break;
pushStack(stack,temp[i]);
}
}
void printStack(struct STACK *stack){
struct NODE *trav = stack->head;
while (trav != NULL){
printf("%c", trav->word);
trav = trav->next;
}
}
MAX=100 is the limit I'm taking for string input. I haven't also added increasing the size because I'm just ignoring the increment of size for now. Before I could perfect the implementation
In main the s pointer is not initialized and it points nowhere.
int main(){
char *s; // <<< this is wrong, you want 'char s[100]' instead
fgets(s,100,stdin);
...
However the safest option is this:
int main(){
char s[100]; // declare array of 100 chars
fgets(s, sizeof(s), stdin); // sizeof(s) is the actual size of s (100 here)
...
This is wrong too: you store the pointer to the local variable temp, but that variables ceases to exist once you return from the pushStask function.
void pushStack(struct STACK* stack, char s) {
struct NODE temp;
temp.word = s;
temp.next = stack->head;
stack->head = &temp;
}
Instead you need to create a new struct NODE like this:
void pushStack(struct STACK* stack, char s) {
struct NODE* temp = malloc(sizeof *temp);
temp->word = s;
temp->next = stack->head;
stack->head = temp;
}
Instead of malloc(sizeof *temp) you could write sizeof(struct NODE), it's the same, but it's less fool proof because you could mistakenly write sizeof(struct STACK) which would compile fine, but the size of the allocated memory would be wrong.
Another problem: you don't assign the size field of the struct STACK, this is not a problem now, but it might become a problem later.
There are several drawbacks in your implementation of a stack.
The first one is that you are using a pointer with an indeterminate value to read a string
char *s;
fgets(s,100,stdin);
So the call of fgets invokes undefined behavior.
Moreover there is used a magic number 100.
You need to allocate a character array and use it to read a string.
#define MAX 100
//...
char s[MAX];
fgets( s, MAX, stdin );
Pay attention to that the name word for an object of the type char is confusing
struct NODE {
char word;
struct NODE *next;
};
You could define the structure like for example
struct NODE {
char c;
struct NODE *next;
};
or
struct NODE {
char item;
struct NODE *next;
};
Instead of separating the declaration and the initialization as you did
struct STACK stack;
stack.head = NULL;
forgetting to initialize the data member size (that by the way should have an unsigned integer type as for example size_t) you could just write for example
struct STACK stack = { NULL, 0 };
or
struct STACK stack = { .head = NULL, .size = 0 };
In the declaration of the function makeStack the second parameter should have the qualifier const because the passed string is not being changed within the function. And as a memory allocation in general can fail the function should report whether all characters of the string were pushed successfully. So the function declaration should look like
int makeStack( struct STACK *stack, const char *s );
It does not make a sense to declare a local array temp within the function
void makeStack(struct STACK *stack, char *s){
char temp[MAX];
//...
using the index variable i is redundant. Also the function fgets can append the new line character '\n' to the input string that you should not push on stack.
The function can be defined the following way
int makeStack( struct STACK *stack, const char *s )
{
int success = 1;
for ( ; *s && success; ++s )
{
if ( *s != '\n' )
{
success = pushStack( stack, *s );
}
}
return success;
}
Another approach is to remove the new line character from the input string before passing it to the function makeStack.
For example
s[ strcspn( s, "\n" ) ] = '\0';
makeStack( &stack, s );
If it is the user that is responsible whether to push the new line character on stack or not then the function makeStack can be simplified
int makeStack( struct STACK *stack, const char *s )
{
int success = 1;
for ( ; *s && success; ++s )
{
success = pushStack( stack, *s );
}
return success;
}
Correspondingly the function pushStack also should be redefined.
For starters it shall dynamically allocate a new node. Otherwise you will try to add nodes that are local to the function and will not be alive after exiting the function that again results in undefined behavior.
The function pushStack can be defined the following way.
int pushStack( struct STACK *stack, char c )
{
struct NODE *temp = malloc( sizeof( struct NODE ) );
int success = temp != NULL;
if ( success )
{
temp->word = c;
temp->next = stack->head;
stack->head = temp;
++stack->size;
}
return success;
}
The parameter of the function printStack should have the qualifier const because the stack itself within the function is not being changed.
The function can be defined at least the following way
void printStack( const struct STACK *stack )
{
for ( const struct NODE *trav = stack->head; trav != NULL; trav = trav->next )
{
printf( "%c", trav->word );
}
}

How would I return a pointer to an allocated data structure in C?

I have created a struct:
typedef struct _POOL
{
int size;
void* memory;
}Pool;
and have then allocated space in the system memory for that structure but would like to return a pointer to the beginning of the allocated memory. I tried just returning the variable but got an error.
int main(void)
{
Pool* allocatePool(int n);
{
Pool *n = malloc(sizeof *n);
return n;
}
}
It seems you mean something like the following
#include <stdlib.h>
typedef struct _POOL
{
int size;
void* memory;
}Pool;
Pool * allocatePool( int n )
{
Pool *p = malloc( sizeof( Pool ) );
if ( p != NULL )
{
p->size = 0;
p->memory = malloc( sizeof( n ) );
if ( p->memory != NULL ) p->size = n;
}
return p;
}
int main(void)
{
int n = 10;
Pool *p = allocatePool( int n );
//...
if ( p != NULL ) free( p->memory );
free( p );
}
The function malloc is not declared because you missed to include the respective header stdlib.h. Thus, the compiler assumes an implicit declaration with a return type of int.
#include <stdio.h>
#include <stdlib.h>
int main()
{
typedef struct _POOL
{
int size;
void* memory;
} Pool;
Pool *p=(Pool*) malloc(sizeof(Pool));
return 0;
}
Here p is a pointer to the (first byte of the) allocated memory.

got "error: undeclared here (not in a function)" with void * variable array

Code:
struct bunchofdata
{
int i;
void *dllist[i];
int spltq[i];
pthread_t tlist[i];
};
Errormsg:
error: ā€˜iā€™ undeclared here (not in a function)
void *dllist[i];
^
I can't understand why this doesn't work.
In addition to pikkewyn's answer, another way to implement this is to use Flexible Array Member
This makes it easier to manage than allocating members separately.
#include <stdio.h>
#include <stdlib.h>
typedef int pthread_t;
struct data
{
void *dl;
int spltq;
pthread_t thread;
};
struct bunchofdata
{
int i;
struct data data_list[];
};
struct bunchofdata * data_factory(int size)
{
struct bunchofdata * ret = malloc(sizeof(struct bunchofdata)
+size*sizeof(struct data));
/* fill in the members here*/
ret->i=size;
return ret;
}
int main(void) {
struct bunchofdata *data10=data_factory(10);
data10->data_list[9].spltq=0;
printf("data10->data_list[9].spltq=%d",data10->data_list[9].spltq);
free(data10)
return 0;
}
You can use sth like this, although since each field of your structure is array it might be nicer to have array of such structs:
#include <malloc.h>
#include <pthread.h>
struct bunchofdata
{
int i;
void** dllist;
int* spltq;
pthread_t* tlist;
};
struct anotherbunchofdata
{
int i;
void* dll;
int spltq;
pthread_t tlist;
};
void init_bunchofdata( int size, struct bunchofdata* bd )
{
bd->i = size;
bd->dllist = malloc( size * sizeof( void* ) );
bd->spltq = malloc( size * sizeof( int ) );
bd->tlist = malloc( size * sizeof( pthread_t ) );
}
void free_bunchofdata( struct bunchofdata* bd )
{
free( bd->dllist );
free( bd->spltq );
free( bd->tlist );
}
int main()
{
struct bunchofdata bd;
init_bunchofdata( 5, &bd );
free_bunchofdata( &bd );
return 0;
}

segmentation fault 11, while pointer variables

I am trying to take input from console and add it to hash table.
But I'm getting Segmentation fault 11.
So, I debugged the program using gdb-apple.
It is showing that I'm trying access memory I cannot, using the pointer variable.
I think it is something obvious, but I'm missing it
This is what the gdb is displaying
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000008
0x0000000100000986 in CreateHashTable (size=200) at hashing.c:29
29 h->Table[i]->next = NULL;
Here is the code
Header File:
#define LOAD_FACTOR 20
#define INITIAL_SIZE 200
struct HashTable *CreateHashTable(int size);
int HashSearch(struct HashTable *h,int data);
int HashInsert(struct HashTable *h,int data);
int HashDelete(struct HashTable *h, int data);
void Rehash(struct HashTable *h);
int Hash(int data, int size);
struct ListNode
{
int key;
int data;
struct ListNode *next;
};
struct HashTableNode
{
int bcount;
struct ListNode *next;
};
struct HashTable
{
int tsize;
int count;
struct HashTableNode **Table;
};
Implementation file:
#include "hashing.h"
#include<stdio.h>
#include<stdlib.h>
struct HashTable *CreateHashTable(int size)
{
struct HashTable *h;
h = (struct HashTable *) malloc ( sizeof(struct HashTable) );
if(h == NULL)
{
printf("Memory Error");
return NULL;
}
h->tsize = (int) size/LOAD_FACTOR;
printf("h->tsize = %d",h->tsize);
h->count = 0;
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
if( h->Table == NULL )
{
printf("Memory Error");
return NULL;
}
int i;
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
return h;
}
I would paste the rest of file, or Driver file, but I don't see it relevant.
Please tell me why I'm getting the segmentation fault 11
You allocated memory for array of pointers but you didn't allocate memory for members of this array.
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i] = malloc(...); //put correct arguments here and check allocation
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
Your problem is here:
struct HashTableNode **Table;
You want an array of nodes (not a 2d array), change to:
struct HashTableNode *Table;
also change
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
to
h->Table = malloc(sizeof(struct HashTableNode) * h->tsize);
I think I want an array of pointers to nodes, don't I?
As pointed out by #WhozCraig, there is no reason for the additional level of indirection.
Example A (Pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *a; /* pointer */
int i, n = 10;
a = malloc(n * sizeof(int)); /* space for 10 ints */
for (i = 0; i < n; i++) {
a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", a[i]);
}
free(a);
return 0;
}
Example B (Pointer to pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int **a; /* pointer to pointer*/
int i, n = 10;
a = malloc(n * sizeof(int *)); /* space for 10 pointer to ints */
for (i = 0; i < n; i++) {
a[i] = malloc(sizeof(int)); /* space for 1 int */
*a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", *a[i]);
free(a[i]);
}
free(a);
return 0;
}
As you can see both do the same thing, but the first one requires less memory and the code is cleaner.
One way to make it easy to remember is:
int * can hold an array
int ** can hold a table (NROWS * NCOLS)
int *** can hold an array of tables

Assignment makes pointer from Integer without a Cast in Structure

I'm making a program that dynamically creates a list of integers.
int ins_dlist(int data, struct dlist **p){
struct dlist *q;
if((*p)->sz == (*p)->maxsz){
q = realloc(*p, DLISTSZ((*p)->maxsz + INCRSZ));
if(q == NULL)
return (-1);
q->maxsz += INCRSZ;
*p = q;
}
//(*p)->item[(*p)->sz++] = data; <-Gives me pointer from integer without cast
*((*p)->item + (*p)->sz++) = data;
return(0);
}
My problem is on *((*p)->item + (*p)->sz++) = data; I tried declaring it in different ways but I still can't get access to the sz variable in my struct.
Heres my struct declaration, its inside a file named dlist.h:
#include <stdlib.h>
struct dlist{
int sz;
int maxsz;
int *item[1];
};
#define INITSZ 5
#define INCRSZ 5
#define DLISTSZ(n) ((size_t)(sizeof(struct dlist)) + ((n-1)*sizeof(int)))
struct dlist *init_dlist(int num);
int ins_dlist(int data, struct dlist **p);
You probably wanted to define dllist as:
struct dlist{
int sz;
int maxsz;
int item[1];
};

Resources