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];
};
Related
I'm getting the dereferencing pointer to incomplete type error when I try to run the following code. I've checked several other questions about this error and from what I can tell it's not due to a missing or extra struct keyword and I believe the pointer type is correct but I could be mistaken.
There might be other issues with the code as I'm just learning C, I'm happy to try and figure them out for myself I just can't seem to track down the issue with the incomplete type error.
Development/C/AI/test/src/test.c: In function ‘compare’:
Development/C/AI/test/src/test.c:10:19: error: dereferencing pointer to incomplete type ‘lrgraph_node {aka struct lrgraph_node}’
if ( strcmp(other->dataType, current->dataType == 0) ) {
test.c
#include "lrGraph.h"
#include <string.h>
int data = 1;
char *dataType = "int";
lrgraph_edge *connected[] = {};
unsigned numEdges = 0;
int compare( lrgraph_node *other, lrgraph_node *current ) {
if ( strcmp(other->dataType, current->dataType == 0) ) {
return (int)other->data - (int)current->data;
}
return -1;
}
int main() {
lrgraph_node *nodeA = lrgraph_createNode((void*)&data, dataType, &compare, connected, numEdges);
lrgraph_printVersion();
}
lrGraph.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lrGraph.h"
struct lrgraph_edge {
float weight;
lrgraph_node *nodeA;
lrgraph_node *nodeB;
};
struct lrgraph_node {
//data can be of any type
void *data;
//string to see if this node can be compared to another node based on data type
char *dataType;
int numEdges;
//comparator function which compares another node to this node
int (*compare)(lrgraph_node *other, lrgraph_node *current);
//array of connected edges
lrgraph_edge *connected[];
};
void lrgraph_printVersion() {
fprintf(stdout, "\nlrgraph version 0.01b\n");
}
lrgraph_node* lrgraph_createNode(void *data, char *dataType, int (*compare)(lrgraph_node* other, lrgraph_node* current), lrgraph_edge *connected[], unsigned numEdges) {
//allocate enough memory for the struct plus each pointer in the array of edges - https://stackoverflow.com/questions/32311269/can-we-have-a-struct-element-of-type-variable-length-array
lrgraph_node *node = malloc(sizeof(lrgraph_node) + numEdges * sizeof(lrgraph_edge));
if (NULL != node) {
node->data = data;
node->dataType = strdup(dataType);
node->compare = compare;
node->numEdges = numEdges;
//initialize each edge in the array
for( unsigned i=0; i < numEdges; i++) {
node->connected[i] = connected[i];
}
}
return node;
}
lrGraph.h
#ifndef LRGRAPH_H
#define LRGRAPH_H
typedef struct lrgraph_node lrgraph_node;
typedef struct lrgraph_edge lrgraph_edge;
lrgraph_node* lrgraph_createNode(void *data, char *dataType, int (*compare)(lrgraph_node *other, lrgraph_node *current), lrgraph_edge *connected[], unsigned numEdges);
void lrgraph_printVersion();
#endif /*LRGRAPH_H*/
"Incomplete type" means the compiler sees you're trying to use a struct type but there is no definition for that struct.
This is fine if you're only using pointers to structs (and is in fact how abstract data types are implemented in C), but if you want to dereference such a pointer, a struct definition must be visible.
In test.c only the contents of lrGraph.h are visible (i.e. typedef struct lrgraph_node lrgraph_node;), but the actual struct lrgraph_node { ... }; definition exists only in lrGraph.c.
Possible solution: Move the struct lrgraph_node { ... } definition into the header. (Alternatively, put the definition of compare into lrGraph.c).
struct node
{
int a;
node * link;
}
i have an array A with each element of type 'pointer to node' and hence each element of A can have variable size.Example
A[0]=NULL
A[1]=2->3->4
A[2]=3->4
and so on..
so to dynamically allocate an array if I use
u = (struct node*) malloc( m * sizeof(struct node*) )
then
u+i = NULL
(i is any integer) gives error as Lvalue required.
If I use array pointer as
struct node(*p)[];
and then use
(*p)+i = NULL
it gives error as L value required.
*(p+i) = NULL
gives error as
invalid use of array with unspecified bounds
What is the solution?
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
struct node{
int a;
node * link;
};
void print(node *np){
while(np){
printf("%d->", np->a);
np = np->link;
}
printf("NULL\n");
}
int main(){
struct node four = {4, NULL};
struct node three = {3, &four};
struct node two = {2, &three};
struct node **u;
int m = 3;
u = malloc(m * sizeof(struct node*));
u[0] = NULL;
u[1] = &two;
u[2] = &three;
for(int i=0;i<m;++i)
print(u[i]);
free(u);
return 0;
}
I think what you want is:
(*p) += i;
(*p) = NULL;
or
p[i] = NULL;
Here is a working example:
#include <stdio.h>
#include <string.h>
typedef struct s_node {
int x;
struct s_node *next;
} node ;
main()
{
node n[5];
n[2].x = 42;
printf("%d\n", n[2].x);
node *p = n;
printf("%d\n", p[2]);
p += 2;
printf("%d\n", p->x);
}
Output:
42
42
42
Consider to take a look at a tutorial for pointer arithmetic. Just google for it or click the provided link.
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.
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.
Essentially I want qPtr[0] to hold sPtr[0]
struct myQueue{
struct sample* node;
int front;
int size;
int numElements;
};
struct sample{
int field1[5];
char field2[10];
}
int main(){
struct myQueue* qPtr = malloc(10 * sizeof(struct myQueue);
struct sample* samplePtr = malloc(10 * sizeof(struct sample); //assume this array has been initialized
enqueue(qPtr, samplePtr[0]); //this does not work
}
//returns 1 if enqueue was successful
int enqueue(struct myQueue* qPtr, struct sample* sPtr){
qPtr->node[(qPtr->front + qPtr->numElements) % qPtr->size] = sPtr; //code pertains to circular array implementation of queues
return 1;
}
I've been at it for about 2 hours now and would appreciate some clarification on what I'm doing wrong conceptually. thank you!
samplePtr[0] gives the object itself, not a pointer to the object. Try sending &samplePtr[0] or samplePtr itself. enque function, second parameter expects a type of struct sample* and not struct sample.
How about:
enqueue(qPtr, &samplePtr[0]);
The second parameter to enqueue() takes a pointer to a struct sample.
Your code has 2 fundamental problems.
you're passing a struct sample object to enqueue() instead of a pointer to a struct sample. this should be caught by the compiler.
you're setting up an array of queue structures instead of having a single queue structure object that manages an array of pointers to the objects that are on the queue. This is a design problem.
Your code should probably look more like:
struct myQueue{
struct sample* node;
int front;
int size;
int numElements;
};
struct sample{
int field1[5];
char field2[10];
}
struct myQueue q = {0};
int enqueue(struct myQueue* qPtr, struct sample* sPtr);
int main(){
// get memory to hold a collection of pointers to struct sample:
q.node = calloc(10, sizeof(struct sample*));
q.size = 10;
// allocate a sample
struct sample* samplePtr = malloc(sizeof(*samplePtr));
// put the sample on the queue
enqueue(qPtr, samplePtr);
}
//returns 1 if enqueue was successful
int enqueue(struct myQueue* qPtr, struct sample* sPtr){
qPtr->node[(qPtr->front + qPtr->numElements) % qPtr->size] = sPtr; //code pertains to circular array implementation of queues
return 1;
}