Problems with abstract data type code in C [duplicate] - c

This question already has answers here:
How do you compare structs for equality in C?
(11 answers)
Closed 4 days ago.
I have this types defined:
#define NAME_LENGTH_LIMIT 25
#define LNULL (-1)
#define MAX 1000
typedef char tParticipantName[NAME_LENGTH_LIMIT];
typedef int tNumVotes;
typedef bool tEUParticipant;
typedef struct tItemL {
tParticipantName participantName;
tNumVotes numVotes;
tEUParticipant EUParticipant;
} tItemL;
typedef int tPosL;
typedef struct tList {
tItemL data[MAX];
tPosL lastPos;
} tList;
This code below is creating problems, because it needs to read a character but when I insert one I recived this error-> error: invalid operands to binary == (have 'tItemL' and 'tItemL').
tPosL findItem(tItemL d, tList L) {
tPosL t;
if (L.lastPos == LNULL) {
return LNULL;
} else {
t = first(L); //p=0;
while (t != LNULL && (L.data[t] == d)) { //error in this line
t = next(t, L);
}
if (L.data[t] == d) return t;//error in this line
else return LNULL;
}
}
I don't know how to solve the problem

if (L.data[t] == d)
Here L.data[t] and d evaluates to structs.
You can't compare two structs for equality with the == operator.
You need to compare each member separately.

You should pass the pointer to this big struct, not the struct itself as every time you copy the whole thing when you call the function.
Do hide standard types behind typedefs.
Do not hide arrays behind typedefs
typedef struct tItemL {
char participantName[NAME_LENGTH_LIMIT];
int numVotes;
bool EUParticipant;
} tItemL;
typedef int tPosL;
typedef struct tList {
tItemL data[MAX];
tPosL lastPos;
} tList;
int compare(const tItemL *i1, const tItemL *i2)
{
return strcmp(i1 -> participantName, i2 -> participantName) &&
i1 -> numVotes == i2 -> numVotes &&
i1 -> EUParticipant && i1 -> EUParticipant;
}
int findItem(tItemL *d, tList *L) {
int t = -1;
if (L -> lastPos == LNULL) {
return LNULL;
} else {
t = first(L); //p=0;
while (t != LNULL && compare(&L -> data[t], d)) { //error in this line
t = next(t, L);
}
if (compare(&L -> data[t], d)) return t;//error in this line
else return LNULL;
}
}
You need to change other functions to take pointers not struct

Related

why does my isFull function is always return 1?

I made a function to check if my circular queue is full, but it always return 1 (aka "true");
this is my Queue setup:
#define MAX_LENGTH 150
typedef double ElementType;
typedef int bool;
typedef struct
{
ElementType Elements[MAX_LENGTH];
int front;
int rear;
} Queue;
and this is my function:
int isFull(Queue Q)
{
if (Q.front == Q.rear++)
return 1;
if ((Q.rear == MAX_LENGTH) && (Q.front == 0))
return 1;
return 0;
}
This function always return 1 mean the queue is full even though i have not put anything in the queue yet.
how do I fix this?
Thanks.
Edit:
I edited Q.rear++ to Q.rear+1
Here is how I initialize the Queue.
void resetQueue(Queue *Q)
{
Q->front = -1;
Q->rear = -1;
};
I found out that the problem is right at:
if (Q.front == Q.rear+1)
return 1;
part.
Now I just can put 2 Elements in the queue, if I put the third Elements, it will become full.
As part of your problem, please learn the difference between prefix ++ and postfix ++ (i.e. between ++Q.rear and Q.rear++).
Since you initialize both front and rear to the same value, the comparison Q.front == Q.rear++ will be true, because the increment happens after the value of Q.rear is used.
The code
if (Q.front == Q.rear++)
{
// ...
}
is really more equivalent to
int old_value_of_rear = Q.rear;
Q.rear = Q.rear + 1;
if (Q.front == old_value_of_rear)
{
// ...
}
If you want to compare Q.front with Q.rear + 1, use that exact addition:
if (Q.front == Q.rear + 1)

Getting an segmentation fault (core dumped) error in Ubuntu

I am trying to build a program which will function as an assembler, it will be getting file name as command line arguments and translate them to machine code.
The program compiles just fine and runs OK with 1 file name, but when I try to run with several, the error appears after the first iteration.
I think there might be something withe the Clear() function (which flushes out all the data allocated in the previous iteration), but not sure why. Note that this is partial, but as I said, the program will run unless several files are used.
struct symbolStruct { // a structure which is used to absorb info about a tag, its place in memory and related flags
char *name;
int place;
unsigned int isEntry : 1;
unsigned int isData : 1;
unsigned int isExternal : 1;
struct symbolStruct *next;
};
typedef struct { // a structure which is used to absorb info about the operand structure of an instruction line
unsigned int numOfOperands : 2;
unsigned int addrMethSou : 2;
unsigned int addrMethDest : 2;
unsigned int operation : 4;
unsigned int extraWords : 2;
char *firstOperand;
char *secondOperand;
} OperandType;
typedef struct {
unsigned int row : WORD_SIZE;
} int15;
struct MachineCode { // a structure which is used to absorb machine code lines, and their location in the assembly file
unsigned int row : WORD_SIZE;
unsigned int line;
OperandType *structure;
struct MachineCode *next;
};
struct DataCode { // a structure which is used to absorb data and string elements (signed numbers and ascii characters)
unsigned int row : WORD_SIZE;
struct DataCode *next;
};
struct Operation { /* the main operation structure, contains pointers to all used lists, the ic and dc counters, the
current line number which is dealt with and the error flag. */
unsigned int ic;
unsigned int dc;
struct symbolStruct *externHead; // a pointer to a linked list of extern tags used in the assembly file, and their locations
struct symbolStruct *symbolHead; // a pointer to a linked list of all tags
struct DataCode *dataHead; // a pointer to a linked list of all data/string elements
struct MachineCode *machineHead; // a pointer to a linked list of all machine code rows
int linenumber;
unsigned int errorflag : 1; // raised in case of an error which triggered a warning
};
#include "header.h"
void FirstRun(struct Operation*, char *);
void DataUpdate(struct symbolStruct*,int);
void SecondRun(struct Operation *, char *);
void Clear(struct Operation *);
int main(int argc, char *argv[]) {
int i;
struct Operation programCore = {0,0,NULL,NULL,NULL,NULL,0,0};
for(i=1;i<argc;i++) {
char *fn = argv[i];
FirstRun(&programCore,fn);
DataUpdate(programCore.symbolHead,programCore.ic+INSTRUCTION_OFFSET);
SecondRun(&programCore,fn);
Clear(&programCore);
programCore.symbolHead = programCore.externHead = programCore.dataHead = programCore.machineHead = NULL;
}
if(argc < 2) {
fprintf(stderr,"No files selected.\n");
}
return 0;
}
/*Used to empty the linked lists and allocated memory after the program has finished one iteration. */
void Clear(struct Operation *programCore) {
/*f(pointer name) is there to hold a pointer to the allocated memory which is about to be flushed. */
struct MachineCode *machineHead = programCore->machineHead, *fMachineHead;
struct DataCode *dataHead = programCore->dataHead, *fDataHead;
struct symbolStruct *externHead = programCore->externHead, *fExternHead;
struct symbolStruct *symbolHead = programCore->symbolHead, *fSymbolHead;
while(machineHead != NULL) {
fMachineHead = machineHead;
machineHead = machineHead->next;
if(fMachineHead->structure != NULL) {
if(fMachineHead->structure->numOfOperands == 2)
free(fMachineHead->structure->secondOperand);
if(fMachineHead->structure->numOfOperands > 0)
free(fMachineHead->structure->firstOperand);
free(fMachineHead->structure);
}
free(fMachineHead);
}
while(dataHead != NULL) {
fDataHead = dataHead;
dataHead = dataHead->next;
free(fDataHead);
}
while(externHead != NULL) {
fExternHead = externHead;
externHead = externHead->next;
free(fExternHead->name);
free(fExternHead);
}
while(symbolHead != NULL) {
fSymbolHead = symbolHead;
symbolHead = symbolHead->next;
free(fSymbolHead->name);
free(fSymbolHead);
}
programCore->ic = programCore->dc = programCore->linenumber = programCore->errorflag = 0;
}
You do not free and nullifying the linked lists in the context struct (programCore). I suspect you are then using pointers to freed memory blocks.
This line only copies the pointer:
struct MachineCode *machineHead = programCore->machineHead;
The while() loop is not clearing programCore->machineHead
To fix it, run directly on the head:
while(programCore->machineHead != NULL)
{
...
}
Well, by getting rid of
if(fMachineHead->structure->numOfOperands == 2)
free(fMachineHead->structure->secondOperand);
if(fMachineHead->structure->numOfOperands > 0)
free(fMachineHead->structure->firstOperand);
I have managed to solve the error, but now I am getting a new one -
main.c:242:13: error: request for member ‘symbolHead’ in something not a structure or union
main.c:242:38: error: request for member ‘externHead’ in something not a structure or union
main.c:243:13: error: request for member ‘dataHead’ in something not a structure or union
main.c:244:13: error: request for member ‘machineHead’ in something not a structure or union
Referring to the next line -
programCore.symbolHead = programCore.externHead = programCore.dataHead = programCore.machineHead = NULL;
Is there a problem with the way I wrote that? (Obviously yes, but I just don't see it).
Changed the clear() function again and it seems to be working fine now.
/*Used to empty the linked lists and allocated memory after the program has finished one iteration. */
void Clear(struct Operation *programCore) {
/*f(pointer name) is there to hold a pointer to the allocated memory which is about to be flushed. */
struct MachineCode *machineRowPointer = programCore->machineHead, *fMachineRow;
struct DataCode *dataRowPointer = programCore->dataHead, *fDataRow;
struct symbolStruct *externSymbolPointer = programCore->externHead, *fExtern;
struct symbolStruct *symbolPointer = programCore->symbolHead, *fSymbol;
if(machineRowPointer != NULL) {
while(machineRowPointer != NULL) {
if(machineRowPointer->structure != NULL)
free(machineRowPointer->structure);
fMachineRow = machineRowPointer;
machineRowPointer = machineRowPointer->next;
free(fMachineRow);
}
programCore->machineHead = NULL;
}
if(dataRowPointer != NULL) {
while(dataRowPointer != NULL) {
fDataRow = dataRowPointer;
dataRowPointer = dataRowPointer->next;
free(fDataRow);
}
programCore->dataHead = NULL;
}
if(externSymbolPointer != NULL) {
while(externSymbolPointer != NULL) {
fExtern = externSymbolPointer;
externSymbolPointer = externSymbolPointer->next;
free(fExtern->name);
free(fExtern);
}
programCore->externHead = NULL;
}
if(symbolPointer != NULL) {
while(symbolPointer != NULL) {
fSymbol = symbolPointer;
symbolPointer = symbolPointer->next;
free(fSymbol->name);
free(fSymbol);
}
programCore->symbolHead = NULL;
}
programCore->ic = programCore->dc = programCore->linenumber = programCore->errorflag = 0;
}

Error dereferencing pointer to incomplete type and I can't figure out why

I've went thru all the material here and I just can't seem to spot my error.
I've created some structs to be used and when trying to manipulate them I get this error. Any advice would be appriciated!
These are the structs as defined in KDArray.c
struct sp_kdarray_t
{
SPPoint* points;
int** sorted;
int rows;
int size;
};
struct sp_kdarrays_t
{
SPKDArray kdLeft;
int leftSize;
int rightSize;
SPKDArray kdRight;
};
And in KDArray.h we have:
typedef struct sp_kdarray_t* SPKDArray;
typedef struct sp_kdarrays_t* SPKDArrays;
Now when I try to manipulate them ( recursively building a tree ) in the following function:
KDTreeNode recursiveTreeBuild(SPKDArray kdArr, int size, SP_TREE_SPLIT_METHOD spKDTreeSplitMethod, int splittingDimension)
{
int split;
KDTreeNode result;
result = (KDTreeNode)malloc(sizeof(KDTreeNode));
if (result == NULL)
{
spLoggerPrintError("Memory Allocation ERROR", __FILE__, __func__, __LINE__);
return NULL;
}
if (size == 1)
{
result -> dim = -1;
result -> val = -1;
result -> left = NULL;
result -> right = NULL;
result -> data = spKDArrayCopyPoint(kdArr, 0);
if (result -> data == NULL)
{
spLoggerPrintError("Memory Allocation ERROR", __FILE__, __func__, __LINE__);
return NULL;
}
}
else
{
SPKDArrays subtrees;
subtrees = spKDArraySplit(kdArr, splittingDimension);
if (subtrees == NULL)
return NULL;
result -> dim = splittingDimension;
result -> val = spKDArrayGetMedianValueByDimension(kdArr, splittingDimension);
result -> data = NULL;
switch (spKDTreeSplitMethod)
{
case MAX_SPREAD:
split = spKDArrayGetHighestSpread(kdArr);
if (split < 0)
return NULL;
break;
case RANDOM:
srand(time(NULL));
split = rand() % spKDArrayGetDimensions(kdArr);
break;
case INCREMENTAL:
split = splittingDimension + 1;
break;
}
result -> left = recursiveTreeBuild(subtrees -> kdLeft, subtrees -> leftSize, spKDTreeSplitMethod, split);
result -> right = recursiveTreeBuild(subtrees -> kdRight, subtrees -> rightSize, spKDTreeSplitMethod, split);
}
return result;
}
I get the "dereferencing error" on :
result -> left = recursiveTreeBuild(subtrees -> kdLeft, subtrees -> leftSize, spKDTreeSplitMethod, split);
result -> right = recursiveTreeBuild(subtrees -> kdRight, subtrees -> rightSize, spKDTreeSplitMethod, split);
Thanks in advance!
Your error happens because the compiler cannot find the definition of the struct. The definition is there, but it is probably in the wrong file or in the wrong position in the file. You don't give details on the layout of your project so I cannot be sure of the details...
For example, the following code will trigger the same error:
typedef struct foo_t* Foo;
void something1(Foo p)
{
p->whatever; // error: incomplete type!
}
struct foo_t // type definition
{
int whatever;
};
void something2(Foo p)
{
p->whatever; // ok: the type is complete
}
So you should move the definition of the structs to before the function, or maybe to the header file itself.
Or if you want the structs to work as opaque types, so you don't want to publicly define them, the usual way is to write a public header with the declarations and a private header with the definitions.

How to dynamically initialize array in "object oriented" C?

In the code below, how and where do I dynamically initialize an array that is in the Class struct? For example, if I made it double *var instead, where does the malloc statement go?
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
struct Class;
struct Class *new_class();
void class_function(struct Class*,double);
#endif
myclass.c
#include "myclass.h"
#include <stdlib.h>
struct Class {
double var;
};
struct Class *new_class()
{
return (struct Class *)malloc(sizeof(struct Class));
}
void class_function(struct Class *inst, double num)
{
inst->var = num;
}
main.c
#include "myclass.h"
int main()
{
struct Class *c1 = new_class();
class_function(c1,0.15);
return 0;
}
I have tried modifying the new_class function to something like
struct Class *new_class(int len)
{
Class c1 = (struct Class *)malloc(sizeof(struct Class));
c1.var = (double)malloc(len*sizeof(double));
return c1;
}
with no luck. Do I need to create a separate function for allocation? What is the best way to accomplish this? Thanks.
This should work, first change the struct definition to
struct Class
{
double *var;
size_t len;
};
and then
struct Class *new_class(int len)
{
struct Class *c1;
c1 = malloc(sizeof(struct Class));
if (c1 == NULL)
return NULL;
c1->var = malloc(len * sizeof(double));
if (c1->var == NULL)
{
free(c1);
return NULL;
}
c1->len = len;
return c1;
}
your class_function() should be check if the pointer is NULL, believe me, you will thank me in this future for this
void set_class_value(struct Class *inst, int index, double num)
{
if ((inst == NULL) || (inst->var == NULL) || (index < 0) || (index >= inst->len))
return;
inst->var[index] = num;
}
you can also have
double get_class_value(struct Class *inst, int index)
{
if ((inst == NULL) || (inst->var == NULL) || (index < 0) || (index >= inst->len))
return 0.0; /* or any value that would indicate failure */
return inst->var[index];
}
you must have a function to release resources when you finish
void free_class(struct Class *klass)
{
if (klass == NULL)
return;
free(klass->var);
free(klass);
}
And now main()
int main()
{
struct Class *c1;
c1 = new_class(5);
if (c1 == NULL)
{
perror("Memory exhausted\n");
return -1;
}
set_class_value(c1, 0, 0.15);
printf("%f\n", get_class_value(c1, 0));
free_class(c1);
return 0;
}
this I think should help, though not much explanation, I think the code speaks by itself.
Note that I added a len field to the struct, because otherwise it wouldn't make sense to have a struct to store an array of double, so by knowing the size of the number of elements in the array you can prevent problems, you should also learn about opaque types and how to hide the structure definition from the structure users, so you force a safe usage.

why is this quick sort not sorting

I have a hash table of structures. I wanted to sort the contents of the buckets using quick sort algorithm and here is the code i tried. The result hash table bucket content is not sorted at all.
#define BUCKETS 6000
#define BK_ENTRIES 1024
void q_sort(int,int,int);
typedef struct fpinfo
{
char fing_print[33];
}fpinfo;
q_sort method
void q_sort(int left, int right,int bk)
{
if(left>=right)
return ;
char l_hold[33], r_hold[33];
int pivot=left;
l_hold=hash_table[bk][left].fp;
r_hold=hash_table[bk][right].fp;
hash_table[bk][pivot].fp=hash_table[bk][left].fp;
while (left < right)
{
while ((strcmp(hash_table[bk][right].fp,hash_table[bk][pivot].fp)>=0) && (left < right))
right--;
if (left != right)
{
hash_table[bk][left].fp=hash_table[bk][right].fp;
left++;
}
while ((strcmp(hash_table[bk][left].fp,hash_table[bk][pivot].fp)<=0) && (left < right))
right--;
if (left != right)
{
hash_table[bk][right].fp= hash_table[bk][left].fp;
left++;
}
}
hash_table[bk][left].fp=hash_table[bk][pivot].fp;
hash_table[bk][pivot].fp=hash_table[bk][left].fp;
hash_table[bk][left].fp=l_hold;
hash_table[bk][right].fp=r_hold;
if ((strcmp(hash_table[bk][left].fp,hash_table[bk][pivot].fp)<=0))
q_sort(left, pivot-1,bk);
if ((strcmp(hash_table[bk][right].fp,hash_table[bk][pivot].fp)>0))
q_sort(pivot+1, right,bk);
}
Here is how i called it in main
fread(hash_table,sizeof(hash_table),1,htfile);
for(int j=0;j<BUCKETS;++j)
{
q_sort(0,BK_ENTRIES-1,j);
}
You might say the code is too long but i couldn't make it any shorter .
EDIT:
Here is the declaration of hash_table
struct fpinfo hash_table[BUCKETS][BK_ENTRIES];
I have solved my problem with the c library function qsort(). But in case any of you want to still look into this problem I have updated it as your suggestions.
I have got a solution. I just used the qsort() standard C function. I have included all of the source code so that all beginners like me can understand it better.
EDITED AS wildplasser's SUGGESTED:
#include<iostream>
#include<stdio.h>
#define BUCKETS 6000
#define BK_ENTRIES 1024
int compare (const void * a, const void * b);
typedef struct fpinfo
{
unsigned long long offset;
unsigned long length;
char fp[33];
}fpinfo;
struct fpinfo hash_table[BUCKETS][BK_ENTRIES];
void main()
{
struct fpinfo e;
char fname[100];
printf("Enter source file name\n");
scanf(fname);
FILE *htfile,*f2;
htfile=fopen(fname,"r+b");
if (htfile != NULL)
{
fread(hash_table,sizeof(hash_table),1,htfile);
for(int j=0;j<BUCKETS;++j)
{
qsort(hash_table[j],BK_ENTRIES,sizeof(e),compare);
}
}
else
{
printf("Couldn't open source file");
exit(1);
}
f2=fopen("dest.txt","w+b");
if (f2 != NULL)
{
fwrite(hash_table,sizeof(hash_table),1,f2);
}
else
{
printf("Couldn't open destination file");
exit(1);
}
fclose(htfile);
fclose(f2);
}
int compare (const void * a, const void * b)
{
struct fpinfo *fpa=(struct fpinfo*)a;
struct fpinfo *fpb=(struct fpinfo*)b;
return strcmp(( char*)fpa->fp,( char*)fpb->fp);
}

Resources