Can someone please explain the code below. I am new to C and trying to figure it out. why do we have queueNodeT at the end?
typedef char queueElementT;
typedef struct queueNodeTag {
queueElementT element;
struct queueNodeTag *next;
} queueNodeT;
queueNodeT is the name of the type that the typedef statement is trying to create.
An alternate way to specify this is:
struct queueNodeTag {
...
};
typedef struct queueNodeTag queueNodeT;
In C (vs. C++), "struct queueNodeTag" just defines a struct named "queueNodeTag". In C++ [should you get there], this would also define a type named "queueNodeTag"
When creating a pointer variable to the struct, it's slightly shorter to use:
queueNodeT *my_pointer;
than:
struct queueNodeTag *my_pointer;
The trailing "T" is just a coding convention to denote that it's a type name and not a variable. You can use others. Mine is:
struct mystructname {
...
};
typedef struct mystructname mystructname_t;
typedef mystructname_t *mystructname_p;
Using mystructname_p, you can change:
struct mystructname *my_pointer;
mystructname_t *my_pointer;
into:
mystructname_p my_pointer;
The "_t" is fairly common. The "_p" thing is my convention, but, I believe other conventions define pointers to types as "p<Mytype>", such as "pMystructName". I much prefer using a suffix for this [and "snake case" notation rather than the "camel hump" notation in your example].
Let's break it down part by part.
This line simply tells you that queueElementT is defined as char here. Meaning you can write either queueElementT or char, both will work.
typedef char queueElementT;
Now here is the actual struct. It contain two variables, the element it is holding, in this case a char. It then also tells which element is next in the queue.
typedef struct queueNodeTag {
queueElementT element;
struct queueNodeTag *next;
} queueNodeT;
More of that can be read in this answer.
A demonstration:
int count (queueNodeTag q) {
int i = 0;
if (q == null) {
return 0;
}
if (q.next == null) {
return 1;
}
while (q.next != null) {
q = q.next;
i++;
}
return i;
}
Three cases to handle.
q is null, the queue is empty. Return 0.
q.next is null, the queue only contains one element. Return 1.
Repeat until q.next is separated from null, increment i as we go. A better name for i might be elements or something similar.
This code is untested as I currently do not have a C compiler at hand. Someone who has one available can perhaps verify that no mistake has been done?
Related
I'm trying to figure out how to parse S-expressions in C on my own, in order to store data and code for my own rudimentary Lisp (written as a learning exercise, not for production).
Before explaining my code and my reasoning, I should explain that all I know about S-expressions is the introductory section of the Wikipedia article on it, and the occasional glance at Common Lisp code, so the naming of my structs and variables may be a bit off.
My language of implementation is C, and before I defined any functions I created the following structs:
typedef enum {
string,
letter,
integer,
} atom_type;
typedef struct {
void* blob;
atom_type type;
} atom;
typedef struct expr {
atom* current;
struct expr* next;
} expr;
Each atom is stored in a struct atom, which contains a enum instance (? I'm not sure of the correct jargon for this) and a void pointer pointing to the data to be stored. Each S-expression "node" consists of a pointer to an atom and a pointer to the next S-expression node.
I've written a rudimentary function that accepts a string and parses it into an atom, like the following:
atom* parse_term(char* str) {
size_t len = strlen(str);
atom* current = malloc(sizeof(atom));
if(str[0] == '\'') {
current->blob = (char*) &str[1];
current->type = letter;
} else if(str[0] == '\"') {
char temp[256];
int pos = 1;
while(str[pos] != '\"') {
temp[pos] = str[pos];
pos++;
}
current->blob = malloc(256 * sizeof(char));
current->blob = (char*) &temp;
current->type = string;
} else if(isdigit(str[0])){
char temp[256];
int pos = 0;
while(str[pos] != ' ') {
temp[pos] = str[pos];
pos++;
}
int tmp = atoi(temp);
current->blob = (int*) &tmp;
current->type = integer;
}
return current;
}
The function seems to be working correctly; at least, when I print out the data type it shows it correctly. But apart from this I can't figure out how to print out the actual 'blob': I've tried using the %p formatting code, as well as a switch statement:
void print_atom(atom* current) {
switch(current->type) {
case string:
printf("atom%s\ttype:%d", current->blob, current->type);
case letter:
printf("atom%c\ttype:%d", current->blob, current->type);
case integer:
printf("atom%c\ttype:%d", current->blob, current->type);
}
}
But this doesn't work. In the case of a string, it returns garbled text and in the case of everything else, it just doesn't print anything where the atom's information is supposed to be.
I imagine this is a product of my use of a void* within a struct; how could I remedy this? I think I did cast properly (though I could very well be wrong, please tell me), the only other option I could concieve of is storing a hardcoded variable for every supported data type in the 'atom' struct, but this seems wasteful of resources.
Don't use void*. Use a union. That's what unions are for.
In this example, I use an "anonymous union", which means that I can just refer to its fields as though they were directly inside the Atom struct. (I changed the spelling of names according to my prejudices, so that types are Capitalised and constants are ALLCAPS. I also separated the typedef and struct declarations for Atom, in case Atom turns out to be self-referential.
typedef enum {
STRING,
LETTER,
INTEGER
} AtomType;
typedef struct Atom Atom;
struct Atom {
union {
char* str;
char let;
int num;
};
AtomType type;
};
void print_atom(Atom* current) {
switch(current->type) {
case STRING:
printf("atom %s\ttype:%d", current->str, current->type);
case LETTER:
printf("atom %c\ttype:%d", current->let, current->tyoe);
case INTEGER:
printf("atom %d\ttype:%d", current->num, current->type);
}
}
As someone says in a comment, that's not actually how Lisp objects look. The usual implementation is combine cons cells and atoms, something like this (instead of AtomType). You'll also need to add CELL to your enum.
typedef struct Cell Cell;
struct Cell {
union {
char* str;
char let;
int num;
struct {
Cell* hd; // Historic name: car
Cell* tl; // Historic name: cdr
};
};
CellType type;
};
Here there's an anonymous struct inside an anonymous union. Some people say this is confusing. Others (me, anyway) say it's less syntactic noise. Use your own judgement.
The use of Cell* inside the definition of Cell is the motivation for typedef struct Cell Cell.
You can play not-entirely-portable-but-usually-ok games to reduce the memory consumption of Cell, and most real implementations do. I didn't, because this is a learning experience.
Also note that real Lisps (and many toy ones) effectively avoid most parsing tasks; the language includes character macros which effectively do what parsing is needed (which isn't much); for the most part, they can be implemented in Lisp itself (although you need some way to bootstrap).
I am trying to understand an assignment I have before I have to take a final. I am trying to understand what exactly I am declaring.
So in a given file the typedef struct's are declared as so:
(Struct Declaration)
/** The following two structs must be defined in your <gamename>.c file **/
typedef struct game_position_t *game_position;
/* move struct must code enough information to reverse the move, given the resulting position */
typedef struct move_t *move;
I have then built the structs out as so (yes this has to be separated just because it is interfaced programming):
(Struct Definition)
/** The following two structs must be defined in your <gamename>.c file **/
struct game_position_t {
int mathy;
int numrows;
int *sizes;
};
/* move struct must code enough information to reverse the move, given the resulting position */
struct move_t {
int rownum;
int move_size;
};
Then an example of a functions and declaration of game_position for example is:
(Example Function)
/* return the starting position, NULL if error */
game_position starting_position(int me_first, int argc, char **argv) {
if (argc < 3) {
printf("\n\nToo few arguments, see help below\n\n");
game_help(argv[0]);
return NULL;
}
int mathy;
if (strcmp(argv[2],"search")==0)
mathy = 0;
else if (strcmp(argv[2],"mathy")==0)
mathy = 1;
else {
printf("\n\nSecond argument must be \"search\" or \"mathy\", see help below\n\n");
game_help(argv[0]);
return NULL;
}
int play_default = (argc==3);
if (play_default) printf("\n\nOK, we will play the default game of 7 5 3 1\n\n");
int defaultgame[4] = {7,5,3,1};
game_position result = malloc(sizeof(struct game_position_t)*1);
result->mathy = mathy;
if (result) {
result->numrows = (play_default ? 4 : argc-3);
result->sizes = malloc(sizeof(int)*(result->numrows));
int row;
for (row=0; row<(result->numrows); row++)
(result->sizes)[row] = (play_default ? defaultgame[row] : strlen(argv[row+2]));
}
return result;
}
So my main misunderstanding is when using a struct declaration in this manner, specifically putting the * before the name like this, typedef struct move_t *move;. Is that previous line saying move it a struct pointer or dereferencing move? Continuing from that. When defining them I just use the struct name such as struct move_t. I don't fully understand how they are linking together and in what matter. Then inside the function I just declare game_position, but still need to use a derefencer, 'p->`, to access it fields. So if someone could explain to me when these struct variables are points to structs and when they are the actual struct.
An example of my misunderstanding is that in the Example Function after result was declared. I first thought to use the . operator to access and set it's fields. I then changed it due to compiler errors, but now I want to understand my misunderstanding. And why did I I have to malloc game_position_t and not game_position?
typedef defines a type, so typedef struct move_t *move defines a new type named move, which is a pointer type, pointing to struct move_t. So after this if you define a variable with move ptr, ptr will have a pointer type so that you should use the syntax of accessing members through a pointer. When allocating memory for it, of course you have to specify the exact size of the structure other than the size of a pointer, that's sizeof(struct move_t)
I'm really new to C programming and I'm still trying to understand the concept of using pointers and using typedef structs.
I have this code snippet below that I need to use in a program:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
}* pStudentRecord;
I'm not exactly sure what this does - to me it seems similar as using interfaces in Objective-C, but I don't think that's the case.
And then I have this line
pStudentRecord* g_ppRecords;
I basically need to add several pStudentRecord to g_ppRecords based on a number. I understand how to create and allocate memory for an object of type pStudentRecord, but I'm not sure how to actually add multiple objects to g_ppRecords.
defines a pointer to the struct described within the curly bracers, here is a simpler example
typedef struct {
int x;
int y;
}Point,* pPoint;
int main(void) {
Point point = {4,5};
pPoint point_ptr = &point;
printf("%d - %d\n",point.x,point_ptr->x);
pPoint second_point_ptr = malloc(sizeof(Point));
second_point_ptr->x = 5;
free(second_point_ptr);
}
The first declares an unnamed struct, and a type pStudentRecord that is a pointer to it. The second declares g_ppRecords to be a pointer to a pStudentRecord. In other words, a pointer to a pointer to a struct.
It's probably easier to think of the second as an "array of pointers". As such, g_ppRecords[0] may point to a pStudentRecord and g_ppRecords[1] to another one. (Which, in turn, point to a record struct.)
In order to add to it, you will need to know how it stores the pointers, that is, how one might tell how many pointers are stored in it. There either is a size somewhere, which for size N, means at least N * sizeof(pStudentRecord*) of memory is allocated, and g_ppRecords[0] through g_ppRecords[N-1] hold the N items. Or, it's NULL terminated, which for size N, means at least (N+1) * sizeof(pStudentRecord*) of memory is allocated and g_ppRecords[0] through g_ppRecords[N-1] hold the N items, and g_ppRecords[N] holds NULL, marking the end of the string.
After this, it should be straightforward to create or add to a g_ppRecords.
A struct is a compound data type, meaning that it's a variable which contains other variables. You're familiar with Objective C, so you might think of it as being a tiny bit like a 'data only' class; that is, a class with no methods. It's a way to store related information together that you can pass around as a single unit.
Typedef is a way for you to name your own data types as synonyms for the built-in types in C. It makes code more readable and allows the compiler to catch more errors (you're effectively teaching the compiler more about your program's intent.) The classic example is
typedef int BOOL;
(There's no built-in BOOL type in older ANSI C.)
This means you can now do things like:
BOOL state = 1;
and declare functions that take BOOL parameters, then have the compiler make sure you're passing BOOLs even though they're really just ints:
void flipSwitch(BOOL isOn); /* function declaration */
...
int value = 0;
BOOL boolValue = 1;
flipSwitch(value); /* Compiler will error here */
flipSwitch(boolValue); /* But this is OK */
So your typedef above is creating a synonym for a student record struct, so you can pass around student records without having to call them struct StudentRecord every time. It makes for cleaner and more readable code. Except that there's more to it here, in your example. What I've just described is:
typedef struct {
char * firstName;
char * lastName;
int id;
float mark;
} StudentRecord;
You can now do things like:
StudentRecord aStudent = { "Angus\n", "Young\n", 1, 4.0 };
or
void writeToParents(StudentRecord student) {
...
}
But you've got a * after the typedef. That's because you want to typedef a data type which holds a pointer to a StudentRecord, not typedef the StudentRecord itself. Eh? Read on...
You need this pointer to StudentRecord because if you want to pass StudentRecords around and be able to modify their member variables, you need to pass around pointers to them, not the variables themselves. typedefs are great for this because, again, the compiler can catch subtle errors. Above we made writeToParents which just reads the contents of the StudentRecord. Say we want to change their grade; we can't set up a function with a simple StudentRecord parameter because we can't change the members directly. So, we need a pointer:
void changeGrade(StudentRecord *student, float newGrade) {
student->mark = newGrade;
}
Easy to see that you might miss the *, so instead, typedef a pointer type for StudentRecord and the compiler will help:
typedef struct { /* as above */ } *PStudentRecord;
Now:
void changeGrade(PStudentRecord student, float newGrade) {
student->mark = newGrade;
}
It's more common to declare both at the same time:
typedef struct {
/* Members */
} StudentRecord, *PStudentRecord;
This gives you both the plain struct typedef and a pointer typedef too.
What's a pointer, then? A variable which holds the address in memory of another variable. Sounds simple; it is, on the face of it, but it gets very subtle and involved very quickly. Try this tutorial
This defines the name of a pointer to the structure but not a name for the structure itself.
Try changing to:
typedef struct
{
char* firstName;
char* lastName;
int id;
float mark;
} StudentRecord;
StudentRecord foo;
StudentRecord *pfoo = &foo;
I am getting an error:
error: request for member ‘clsf_ptr’ in something not a structure or union
From this C Program:
#include<stdio.h>
#define M 3
struct class_stud
{
char name[16];
char subject[16];
int roll_num;
}
struct node
{
int n;
struct branch *p[M];
struct class_stud cls[M-1];
}*root=NULL;
main()
{
int clsf_cnt;
struct class_stud clsf, *clsf_ptr;
clsf_ptr = &clsf;
clsf_cnt = 0;
root = malloc(sizeof (struct node));
printf("enter source address \n");
scanf("%s",&root.clsf_ptr[clsf_cnt]->name);
printf("%s",root.clsf_ptr[clsf_cnt]->name);
printf("enter key\n");
scanf("%d",&root.clsf_ptr[clsf_cnt]->key);
printf("%d",root.clsf_ptr[clsf_cnt] -> key);
clsf_cnt++;
}
What does the error mean?
There are a number of problems in this code. Let's walk through it line by line:
#include<stdio.h>
#define M 3
struct class_stud
{
char name[16];
char subject[16];
int roll_num;
}
First problem; you need a closing ; after the struct definition above. Also, it's interesting that you don't define a preprocessor macro for the lengths of the name and subject arrays, but that's a minor issue at this point.
struct node
{
int n;
struct branch *p[M];
struct class_stud cls[M-1];
}*root=NULL;
Where is the definition for struct branch? What is p supposed to represent in the structure definition? Why do you have one fewer elements in cls than p?
main()
As of C99, you cannot get away with an implicit type for main; it must be explicitly typed to return int. And, since you're not messing with any command-line arguments, it's best to explicitly set the parameter list to void, like so:
int main(void)
{
int clsf_cnt;
struct class_stud clsf, *clsf_ptr;
clsf_ptr = &clsf;
What purpose does the above operation serve?
clsf_cnt = 0;
root = malloc(sizeof (struct node));
That's fine, but a preferred way of writing this would be
root = malloc(sizeof *root);
That way you're sure to allocate the right amount of memory based on root's type.
printf("enter source address \n");
scanf("%s",&root.clsf_ptr[clsf_cnt]->name);
Ack. Multiple problems in this one line.
First of all, clsf_ptr is not a member of struct node. You likely meant to access cls. Secondly, since root is a pointer to struct, you need to use the -> operator to access its members (or explicitly dereference root and then use .). Third, cls[clsf_cnt] is not a pointer type, so you would use the . operator to access name. Finally, since name is an array type, it will implicitly be converted to a pointer type before being passed to scanf, so the & isn't necessary.
In order to avoid buffer overflow, you should either put a maximum field width in the %s conversion specifier, or use fgets() instead of scanf().
Sticking with scanf(), that line should be written as
scanf("%15s", root->cls[clsf_cnt].name);
I'm using 15 instead of 16 in the conversion specifier so that we leave one character for the 0 terminator.
Using fgets(), that line would be written
fgets(root->cls[clsf_cnt].name, sizeof root->cls[clsf_cnt].name, stdin);
printf("%s",root.clsf_ptr[clsf_cnt]->name);
Again, you're trying to access something that isn't a member of root, and you have your access operators backwards:
printf ("%s", root->cls[clsf_cnt].name);
printf("enter key\n");
scanf("%d",&root.clsf_ptr[clsf_cnt]->key);
printf("%d",root.clsf_ptr[clsf_cnt] -> key);
struct class_stud has no member named key; perhaps you meant roll_num?
scanf("%d", &root->cls[clsf_cnt].roll_num);
printf("%d", root->cls[clsf_cnt].roll_num);
clsf_cnt++;
}
It looks like you've posted something that isn't complete; make sure you're showing us the same code you're trying to build.
Any instance of root.clsf_ptr you have in your code should be replaced with root->clsf_ptr, which indicates that root is a pointer to a struct.
You also need to make sure the member clsf_ptr is located in the node struct.
Here is some general source code cleanup that may be helpful:
#include <stdio.h>
#define M 3
typedef struct
{
char name [16];
char subject [16];
int roll_num;
} Class_stud;
typedef struct
{
int n;
Branch* p[M];
Class_stud cls[M-1];
} Node;
int main()
{
Node* root;
int clsf_cnt;
Class_stud clsf;
Class_stud* clsf_ptr;
clsf_ptr = &clsf;
clsf_cnt = 0;
root = malloc (sizeof(Node));
if(root == NULL)
{
/* error handling here */
}
}
The following code should work for you. I'm assuming key should be a member in class_stud (and by your formatting options in scanf, a signed integer):
#include<stdio.h>
#define M 3
typedef struct
{
char name[16];
char subject[16];
int roll_num;
int key;
} class_stud;
typedef struct
{
int n;
struct branch *p[M];
struct class_stud cls[M-1];
} node;
int main(void)
{
int clsf_cnt = 0;
node *root;
root = malloc(sizeof(node));
if (root == NULL) {
/* handle error */
}
printf("enter source address \n");
scanf("%s",&root->cls[clsf_cnt]->name);
printf("%s",root->cls[clsf_cnt]->name);
printf("enter key\n");
scanf("%d",&root->cls[clsf_cnt]->key);
printf("%d",root->cls[clsf_cnt]->key);
clsf_cnt++;
}
You had the following problems:
Incorrectly accessing class_stud. It's a part of root, so you want root -> class_stud[member]->value.
key was omitted
Both were changed to typedefined structures as shown in Lundin's answer, however you need not make them types (just using struct is fine).
We just declare root to be a pointer to node, rather than declaring struct node, and then a pointer and then making the assignment.
We aren't creating a structure as a pointer, we're creating a pointer to a structure
Main should return the type int, if you don't want arguments, tell the compiler that you expect argc to be void.
Stuff I didn't do:
Initialize the allocated structure with memset() or via calloc()
Handle malloc() failing
Compile my example (I don't know what struct branch is)
I think malloc syntax is wrong. once check that. Memory is not allocated.Thats why it shows an error.
For my upcoming university C project, I'm requested to have modular code as C allows it. Basically, I'll have .c file and a corresponding .h file for some data structure, like a linked list, binary tree, hash table, whatever...
Using a linked list as an example, I have this:
typedef struct sLinkedList {
int value;
struct sLinkedList *next;
} List;
But this forces value to be of type int and the user using this linked list library would be forced to directly change the source code of the library. I want to avoid that, I want to avoid the need to change the library, to make the code as modular as possible.
My project may need to use a linked list for a list of integers, or maybe a list of some structure. But I'm not going to duplicate the library files/code and change the code accordingly.
How can I solve this?
Unfortunately, there is no simple way to solve this. The most common, pure C approach to this type of situation is to use a void*, and to copy the value into memory allocated by you into the pointer. This makes usage tricky, though, and is very error prone.
Another alternative no one has mentioned yet can be found in the Linux kernel's list.h generic linked list implementation. The principle is this:
/* generic definition */
struct list {
strict list *next, *prev;
};
// some more code
/* specific version */
struct intlist {
struct list list;
int i;
};
If you make struct intlist* pointers, they can safely be cast (in C) to struct list* pointers, thus allowing you to write genericized functions that operate on struct list* and have them work regardless of datatype.
The list.h implementation uses some macro trickery to support arbitrary placement of the struct list inside your specific list, but I prefer to rely on the struct-cast-to-first-member trick myself. It makes the calling code much easier to read. Granted, it disables "multiple inheritance" (assuming you consider this to be some kind of inheritance) but next(mylist) looks nicer than next(mylist, list). Plus, if you can avoid delving into offsetof hackery, you're probably going to end up in better shape.
Since this is a university project, we can't just give you the answer. Instead, I'd invite you to meditate on two C features: the void pointer (which you've likely encountered before), and the token pasting operator (which you may not have).
You can avoid this by defining value as void* value;. You can assign a pointer to any type of data this way, but the calling code is required to cast and dereference the pointer to the correct type. One way to keep track of this would be to add a short char array to the struct to note the type name.
This problem is precisely the reason why templates were developed for C++. The approach I've used once or twice in C is to have the value field be a void*, and cast the values thereto on insertion and cast them back on retrieval. This is far from type-safe, of course. For extra modularity, I might write insert_int(), get_mystruct() etc. functions for each type you use this for, and do the casting there.
You can use Void* instead of int. This allows the data to be of any type. But the user should be aware of the type of data.
For that, optionally you can have another member which represents Type. which is of enum {INT,CHAR,float...}
Unlike C++ where one can use template, void * is the de-facto C solution.
Also, you can put the elements of the linked list in a separate struct, e.g:
typedef struct sLinkedListElem {
int value; /* or "void * value" */
} ListElem;
typedef struct sLinkedList {
ListElem data;
struct sLinkedList *next;
} List;
so that the elements can be changed without affecting the link-ing code.
Here is an example of linked list utilities in C:
struct Single_List_Node
{
struct Single_List * p_next;
void * p_data;
};
struct Double_List_Node
{
struct Double_List * p_next;
struct Double_List * p_prev; // pointer to previous node
void * p_data;
};
struct Single_List_Data_Type
{
size_t size; // Number of elements in list
struct Single_List_Node * p_first_node;
struct Single_List_Node * p_last_node; // To make appending faster.
};
Some generic functions:
void Single_List_Create(struct Single_List_Data_Type * p_list)
{
if (p_list)
{
p_list->size = 0;
p_list->first_node = 0;
p_list->last_node = p_list->first_node;
}
return;
}
void Single_List_Append(struct Single_List_Data_Type * p_list,
void * p_data)
{
if (p_list)
{
struct Single_List_Node * p_new_node = malloc(sizeof(struct Single_List_Node));
if (p_new_node)
{
p_new_node->p_data = p_data;
p_new_node->p_next = 0;
if (p_list->last_node)
{
p_list->last_node->p_next = p_new_node;
}
else
{
if (p_list->first_node == 0)
{
p_list->first_node = p_new_node;
p_list->last_node = p_new_node;
}
else
{
struct Single_List_Node * p_last_node = 0;
p_last_node = p_list->first_node;
while (p_last_node->p_next)
{
p_last_node = p_last_node->p_next;
}
p_list->last_node->p_next = p_new_node;
p_list->last_node = p_new_node;
}
}
++(p_list->size);
}
}
return;
}
You can put all these functions into a single source file and the function declarations into a header file. This will allow you to use the functions with other programs and not have to recompile all the time. The void * for the pointer to data will allow you to use the list with many different data types.
(The above code comes as-is and has not been tested with any compiler. The responsibility of bug fixing is up to the user of the examples.)