Today I'm trying to implement a queue, but one that works with structures within arrays (I've always hated the C 'Array of Structs' terminology, as I am not trying to make that). However, when I try and do a basic initialization, I run into the compiler error as follows.
"Request for member '**' in something not a structure or union. "
Here's my code, not much as of now.
//------------------------Preprocessor Instructions. ------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define MAX 128
#define BUFFER 120
//-------------------------Global Stuff -------------------------------------------------
int head=-1;
int tail=-1; //Starting head and tail at -1.
struct Entry{
int Data;
int Hops;
};
struct Entry Queue[MAX]; //Queue made up of structs.
int visited[MAX];
//------------------------Function Definitions. -----------------------------------------
int QueuePush(struct Entry *q, int num);
int QueuePop(struct Entry *q);
int IsEmpty(struct Entry *q);
//------------------------Main. ---------------------------------------------------------
int main(void)
{
int i;
while(i<MAX){
Queue.Data[i]=0;
Queue.Hops[i]=0;
i++;
}
for(i=0;i<=10;i++){
printf("Queue Data[%d] = %d \n", i, Queue[i].Data);
printf("Queue Hops = %d \n", Queue[i].Hops);
}
}
Am I making some scary, large error in the way I'm defining the array? Or is the issue syntactical? Thanks in advance.
You should write
Queue[i].Data = 0;
Queue[i].Hops = 0;
not
Queue.Data[i] = 0;
Queue.Hops[i] = 0;
In you initialization while loop, you have written Queue.Data[i] instead of Queue[i].Data.
And another thing:
int i;
while(i<MAX){
Queue.Data[i]=0;
Queue.Hops[i]=0;
i++;
}
Here i contains random number and this loop will not work, so you should write int i = 0; or use for instead of while.
Related
I'm making a program that returns a struct containing an array, but the elements in the array are completely wrong. I keep searching for an answer on this site, Google, and even Bing and nothing. The best I can find are answers like this:
Functions can't return arrays in C.
However, they can return structs. And structs can contain arrays...
from How to make an array return type from C function?
Now, how do I fix this without the use of pointers?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
struct Codes{
int as;
int a[];
};
struct Codes create(int as){
int a[as];
for(int j = 0;j<as;j++)
a[j]=j+1;
struct Codes c;
c.as = as;
c.a[c.as];
for(int i=0; i<as; i++)
c.a[i] = a[i];
for(int i=0; i<as; i+=1)
printf("%d \n", c.a[i]);
return c;
}
int main(int argc, char **argv) {
struct Codes cd;
int as = 4;
cd = create(as);
for(int i=0; i<4; i+=1)
printf("%d \n", cd.a[i]);
}
Actual output:
1
2
3
4
0
0
2
-13120
Expected output:
1
2
3
4
1
2
3
4
structs with flexible value are not meant to be manipulated by value, only by pointer.
You cannot return a struct with a flexible member by value, because C does not know how many items it needs to allocate to the return value, and how many bytes it needs to copy.
Allocate your struct in dynamic memory using malloc of sufficient size, copy your data into it, and return a pointer to the caller:
struct Codes *c = malloc(sizeof(struct Codes)+as*sizeof(int));
c->as = as;
for (int i = 0 ; i != as ; i++) {
c->a[i] = i+1;
}
return c;
Change your function to return a pointer; make sure the caller frees the result.
In your function, struct Codes create(int as), the struct Codes c; is allocated on the stuck, so the memory is no longer valid once the function returns...
...It is true that the core struct is copied in the return value... but the variable array length c.a isn't part of the struct (it's a memory "trailer" or "footer") and isn't copied along with the return value.
Either:
allocate the struct and pass it to a struct Codes create(struct Codes *dest, int as) function; OR
make the struct array fixed in size struct Codes{ int as; int a[4]; };
Good luck.
So i have a struct that has name and age. Look inside the displayRecords() under main, there I am trying to bubble sort array of structs by age. I am able to sort the age, but i am having trouble simultaneously sorting the sting called name[100] to correspond to the correct age.
When i try to set it equal to something, for example a[j+1].name= a[j].name it gives me the error: expression must be a modifiable variable.
I think i tried everything from using -> to even putting putting parentheses in various places.
*a[j+1].name= *a[j].name worked but it only sorted the first letter in the string.
Below is the problem at hand, look inside the displayRecords() function
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define pause system("pause")
#define cls system("cls")
#define SIZE 10
typedef struct{
char name[100];
int age;
}THING;
main(){
THING thing[SIZE];
defaultValue(thing);
displayRecords(thing);
}//End main
void displayRecords(THING a[]){
int i, j;
int temp;
char* temp2;
for(i=0; i<SIZE; i++)
{
for(j=0; j<SIZE-1; j++)
{
if(a[j].age>a[j+1].age)
{
temp = a[j+1].age;
temp2= a[j+1].name;
a[j+1].age = a[j].age;
a[j+1].name= a[j].name;
a[j].age = temp;
a[j].name= temp2;
}
}
}//end bubble sort
for(i=0;i<SIZE;i++){
printf("\n%s is %i\n",a[i].name,a[i].age);
}//end for
pause;
}//end display records
void defaultValue(THING a[]){
strcpy(a[0].name, "Dennis");
strcpy(a[1].name, "Willie");
strcpy(a[2].name, "Tammy");
strcpy(a[3].name, "Abbie");
strcpy(a[4].name, "Spike");
strcpy(a[5].name, "Willis");
strcpy(a[6].name, "Frankie");
strcpy(a[7].name, "Betty");
strcpy(a[8].name, "Donna");
strcpy(a[9].name, "Abe");
a[0].age=45;
a[1].age=22;
a[2].age=99;
a[3].age=75;
a[4].age=5;
a[5].age=4;
a[6].age=67;
a[7].age=36;
a[8].age=11;
a[9].age=21;
}//end defaultvalue
You can't assign to arrays, only initialize them on definition. You can however copy to them, like with strcpy.
i want to create queue with dynamic array, the problem is when i test the q.rear value in int main() (for inserting data later) it's not -1 anymore. Which part did i do wrong?
here's a piece of the code:
#include <stdio.h>
#include <conio2.h>
#include <stdlib.h>
typedef struct{
int *data;
int front,rear,max;
}tqueue;
tqueue create(int size)
{
tqueue q;
q.data=(int *)malloc(size*sizeof(int));
q.front=0;
q.rear=-1;
q.max=size;
return q;
}
int main()
{
tqueue q;
int size=4;
create(size);
printf("\n%d",q.rear);
getch();
return 0;
}
You didn't assign the result of create() to q. The following calls create() and discards the result, leaving q in its original state:
create(size);
To fix, replace the above line with:
q = create(size);
You have two different tqueues, both called q. One (the one you create in create) you initialize and one (the one you create in main) you don't.
You forgot to assign the return value:
q = create(size);
Ok so I'm sure there's a simple fix that I'm missing, but right now my code is causing a segment fault on the line "A[i]->key = 0;." The Record* Item part is a necessity for the program, so I need to make it work this way for an assignment I'm working on, however if I do change it so that Item becomes a non-pointer typedef of Record, then I can use A[i].key no problem. I just need a nudge in the right direction so that I can make standInput correctly assign values to an array of pointers to records. Thanks!
Item.h:
#include "stdio.h"
#include "stdlib.h"
typedef int keyType;
struct Record
{
keyType key;
int other;
};
typedef struct Record* Item;
void standInput(Item *A, int n)
{
int i, input;
for(i = 0; i <= n-1; i++)
{
A[i]->key = 0;
printf("%d ", A[i]->key);
}
}
Main:
#include "stdio.h"
#include "stdlib.h"
#include "Item.h"
int main()
{
int n;
Item *A;
printf("Enter a length for the array: ");
scanf("%d", &n);
A = (Item*)malloc(n * sizeof(Item));
standInput(A, n);
return 0;
}
The values in A are all uninitialized, but you're using them as struct Record pointers anyway. If you want to have A continue holding pointers (rather than the structs directly), then you need to allocate space for A and for each item pointed to by A.
Note that Item is already a pointer!
You have to allocate space for the struct, not for the pointer:
A = (Item)malloc(n * sizeof(struct Record));
Note: If the typedef for pointer confuses you, don't use it ;)
A[i]->key means that A[i] is a pointer, but you just allocated an array, so use A[i].key.
Note: you have to change the type of A accordingly.
2nd solution: if you want A[i] to be a pointer, you have to fist allocate space for the pointers (as you do now), then for each pointer (in a loop) allocate space for the struct.
Your structure name is Record not Item. So you should use sizeof(struct Record).
Do it this way:
int main()
{
int n, i;
Item *A;
printf("Enter a length for the array: ");
scanf("%d", &n);
A = (Item*)malloc(n * sizeof(Item));
for(i=0; i<n; i++){
A[i] = (Item)malloc(sizeof(struct Record));
}
standInput(A, n);
return 0;
}
I am going to use GLib's Hash table implementation in a C program and just for now
I am just experimenting with it. I wrote the following piece of code for testing:
#include <glib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int main(){
// Some codes and declerations here
GHashTable *g_hash_table;
uint32_t *a;
a=(uint32_t *)malloc(sizeof(uint32_t));
if(a==NULL){
printf("Not Enough Mem For a\n");
return 1;
}
*a=1123231;
uint32_t* key;
key=(uint32_t *)malloc(sizeof(uint32_t));
if(key==NULL){
printf("Not Enough Mem For key\n");
return 1;
}
*key=122312312;
int i;
g_hash_table=g_hash_table_new(g_int_hash, g_int_equal);
for(i=0;i<TABLE_SIZE;i++){
*key+=1;
*a+=1;
g_hash_table_insert(g_hash_table,(gpointer)key,(gpointer)a);
uint32_t *x=(uint32_t *)g_hash_table_lookup(g_hash_table,key);
printf("Counter:%d, %u\n",i,*x);
}
GHashTableIter iter;
g_hash_table_iter_init(&iter,g_hash_table);
int size=g_hash_table_size(g_hash_table);
printf("First size: %d\n",size);
uint32_t *val;
uint32_t *key_;
int counter=0;
// My problem is in the following loop it
// always returns the same and the last key value pair
while(g_hash_table_iter_next(&iter,(gpointer*)(void*)&key_,(gpointer*)(void*)&val)){
counter++;
printf("%u %u\n",(uint32_t)*key_,(uint32_t)*val);
printf("Counter: %d\n",counter);
}
//Some more code here
return 0;
}
Somehow my test code iterates correctly but in the loop it always returns the last key and last value pairs and it is always the same. What is the problem here? The above code may not run with its as it is format. I just copied and pasted some parts to give a clear idea about what I am trying to do.
I think your insertion code is broken. You're only allocating memory once, but then doing many inserts, incrementing the value stored in the single allocated location between each.
The hash table stores your pointer, so it will end up associating each key with the same pointer.
Also, you should probably use g_malloc() with glib, for consistency.
And I always recommend using sizeof on objects rather than on their types; that way you don't repeat yourself in quite as dangerous a way. So, instead of
guint32 *a;
a = g_malloc(sizeof (guint32));
use
a = g_malloc(sizeof *a);
This way you "lock down" the dependency, so that you always allocate enough room to store whatever a points at, even if you later change the type.
Further, you should take a hard look at every cast you do. Casting any non-constant pointer to gpointer is a sign of a hesitant programmer. With glib, gpointer is just a synonym for void *, so that cast is never needed. It just adds cruft to your code, making it harder to read.
There is an error in key, a declarations. You always put the same pointer in the hash table. Try:
#include <glib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define TABLE_SIZE 12
int main() {
// Some codes and declarations here
GHashTable *g_hash_table;
int i;
g_hash_table = g_hash_table_new(g_int_hash, g_int_equal);
for (i=0; i<TABLE_SIZE; i++)
{
uint32_t* key = (uint32_t *)malloc(sizeof(uint32_t));
uint32_t* a = (uint32_t *)malloc(sizeof(uint32_t));
*key = i;
*a = i+10;
g_hash_table_insert(g_hash_table, (gpointer)key, (gpointer)a);
uint32_t *x = (uint32_t *)g_hash_table_lookup(g_hash_table,key);
printf("key: %d --> %u\n", *key ,*x);
}
GHashTableIter iter;
int size=g_hash_table_size(g_hash_table);
printf("First size: %d\n", size);
uint32_t *val;
uint32_t *key_;
// My problem is in the following loop
// it always returns the same and the last key value pair
g_hash_table_iter_init (&iter, g_hash_table);
while (g_hash_table_iter_next (&iter, (gpointer) &key_, (gpointer) &val))
{
printf("key %u ---> %u\n", (uint32_t)*key_, (uint32_t)*val);
}
// TODO: free keys
return 0;
}