Include variables in seperate file in C? - c

I created a structure item:
typedef struct item
{
char name[20];
char desc[100];
int lp;
int shield;
int weapon;
} item;
I need 36 of them so I create an array item treasure[6][6];
For each item I insert the data as so:
strcpy(treasure[0][0].name, "name");
strcpy(treasure[0][0].desc, "none");
treasure[0][0].lp = 0;
treasure[0][0].shield = 0;
treasure[0][0].weapon = 200;
I do this 36 times and takes a lot of space in editor, my question: Can I put this in a separate .c/.h file maybe? I've been trying to but can't make it work.
Thanks for any help!

I suggest that use a file, like init.h with the following content
#include <string.h>
typedef struct item {
char name[20];
char desc[100];
int lp;
int shield;
int weapon;
} item;
item treasure[1][1] = {
{{.name = "name", .desc = "none", .lp = 0, .shield = 0, .weapon = 200}}};
In that way you must be able to initialize the struct of you matrix 6, 6 in another file, then you must be able to access it from the main program calling it like this:
#include "init.h"
#include <stdio.h>
int main() {
printf("%s\n", treasure[0][0].name);
return 0;
}
I hope this work for you, there a another ways to initialize structs, but this one is what I use more often. You can find more information here
https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html

If you want to learn how to do proper C program design from the start, then this is how.
The correct way to do this is to create an item.h and a item.c file. Together they form a "code module" (or class, if you will).
Your header file item.h should contain the typedef and header guards. You should write an initialization function too.
// item.h
#ifndef ITEM_H
#define ITEM_H
#include <string.h>
typedef struct {
char name[20];
char desc[100];
int lp;
int shield;
int weapon;
} item_t;
void item_init (item_t* item,
const char name[20],
const char desc[100],
int lp,
int shield,
int weapon);
#endif
You can then implement the init function in init.c:
// item.c
#include "item.h"
void item_init (item_t* item,
const char name[20],
const char desc[100],
int lp,
int shield,
int weapon)
{
strcpy(item->name, name);
strcpy(item->desc, desc);
item->lp = lp;
item->shield = shield;
item->weapon = weapon;
}
These two files, init.h and init.c are only concerned about the behavior of all item_t variables. You can expand them with more functions as you go. They do not and should not contain any actual data.
Now if you want to keep the data separate, you could create a separate pair of files for it like this:
// item_data.h
#include "item.h"
#define ITEMS_N 36
item_t* item_data_get (int item_n);
This is just a "getter" function that lets you access the data. The actual data is encapsulated in the .c file:
// item_data.c
#include "item_data.h"
static item_t items [ITEM_N] =
{
[0] = {.name="name", .desc="none", .lp=0, .shield=0, .weapon=200},
[1] = ... // fill up data here
};
item_t* item_data_get (int item_n)
{
return items[n];
}
If you later on want to change the data of a given item, you can do so by calling item_init(item_data_get(n), ...);

Related

How do I create a dynamic array of struct pointers?

I need to read in some data from a csv file, and store each component into a struct.
The csv file has the following headers: name, last name, phone number, age
The csv file has an unknown number of records, and I want to create a dynamic array of pointers to structs to store this data.
I started with this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv){
typedef struct{
char** name;
char** last_name;
int * number;
int* age}person_t;
person_t **storage;
}
But now I am absolutely stuck and have no idea how to proceed. Please help!
You probably want something like this:
typedef struct{
char name[20]; // can store names of maximum length 19
char last_name[20]; // can store last names of maximum length 19
int number;
int age
} person_t;
int main(int argc, char **argv){
person_t **storage;
...
// allocate an array of nbOfElements pointers to person_t
storage = malloc(nbOfElements * sizeof(person_t*));
for (int i = 0; i < nbOfElements; i++)
{
...
... read one CSV line
...
// allocate memory for one person_t and store the pointer
storage[i] = malloc(sizeof(person_t));
// fill the structure
strcpy(storage[i]->name, ...);
strcpy(storage[i]->last_name, ...);
storage[i]->number = ...
storage[i]->age = ...;
}
}
This is not complete code, just an outline of what you could do. Also there are no error checks for malloc for brevity.

Circular header dependency

I am stuck on (what i think is) a circular dependency problem in VS2017 coding in c.
I tried looking up the problem, and found a lot of similar problems on stackoverflow, but I can't seem to get my problem solved with those questions.
My code:
main.c
#include <stdio.h>
#include "travelers.h"
#include "trip.h"
int main(void) {
int nTravelers = 0;
int nTrips = 0;
Traveler *travelersArray = (Traveler*)calloc(nTravelers, sizeof(Traveler));
Trip *tripsArray = (Trip*)calloc(nTrips, sizeof(Trip));
return 0;
}
travelers.h
typedef struct {
unsigned int id;
char *name;
char *adress;
char *residence;
} Traveler;
trip.h
typedef struct {
unsigned int id;
char *touringCar;
char *destination;
char *date;
Traveler *travelers;
unsigned int amount;
} Trip;
the travelers.c and trip.c files are only contain #include "travelers.h"/#include "trip.h"
The error occurs only in trip.h at Traveler *travelers;:
I don't know how to resolve this.
This looks like the same problem, but I couldnt translate it to my code.
Any help is apriciated.
No cycles here.
If trip.c includes trip.h is shall also include travelers.h as its definitions (Trip) depends on the latter (Traveller).
Knowing this, one could include travelers.h into trip.h. Still, this complicates things, so it is a good idea to 1st of all add to every header so call header-guards, protecting against duplicate definitions on pre-processor level.
Doing so made the headers look like this:
travelers.h
#ifndef TRAVELERS_H
#define TRAVELERS_H
typedef struct {
unsigned int id;
char *name;
char *adress;
char *residence;
} Traveler;
#endif // #ifndef TRAVELERS_H
trip.h
#ifndef TRIP_H
#define TRIP_H
#include "travelers.h" // makes including it unnecessary where trip.h is included
typedef struct {
unsigned int id;
char *touringCar;
char *destination;
char *date;
Traveler *travelers;
unsigned int amount;
} Trip;
#endif // #ifndef TRIP_H
As a remark, the error is caused by the typedef. C accepts opaque structs provided you do not need their implementation details:
a.h:
struct A {
int aVal;
const char * astr;
};
a.c:
#include "a.h"
const char *getAStr(struct A*a) {
return a->astr;
}
b.h
const char *getName(struct B*);
struct B {
int bVal;
struct A *a;
};
b.c
#include "b.h"
const char *getAStr(struct A*);
const char * getName(struct B* b) {
return getAStr(b->a);
}
main.c
#include <stdio.h>
#include "a.h"
#include "b.h"
int main() {
struct A a = { 1, "foo" };
struct B b = { 2, &a };
printf("%d - %d : %s\n", b.bVal, b.a->aVal, getName(&b));
return 0;
}
compiles and links without even a warning while in b.c nothing is known on struct A except that it is a struct.

invalid use of undefined type when using typedef struct

alsa_test.h header file includes the following code:
struct alsa_device;
typedef struct alsa_device alsa_device;
alsa_device *create_alsa_array(size_t n);
alsa_test.c file includes:
struct alsa_device
{
int card;
int dev;
char info[80];
};
typedef struct alsa_device alsa_device;
alsa_device *create_alsa_array(size_t n) {
alsa_device *new = malloc(n * sizeof *new);
return new;
};
and my main.c file has the following:
#include "alsa_test.h"
int main (int argc, char *argv[]) {
alsa_device *devices;
create_alsa_array(devices,50);
devices[0]->card=1;
}
and I get the following error
error: invalid use of undefined type 'struct alsa_device'
any ideas why ?
Your problem is in main(), here
devices[0]->card=1;
At this time devices is a pointer to a struct with no definition.
If you want to keep the structure undefined, define a function in alsa_test.c that takes a pointer to it and a integer (remember to add a prototype in your header file)
void setcard(struct alsa_device *dst, size_t index, int card) {
dst[index].card = card;
}
and call it from main()
setcard(devices, 0, 1); // set card of device 0 to 1
setcard(devices, 1, 42); // set card of device 1 to 42
You have 2 choices:
You wan't to expose types internal structure: you need then to define the struct in the interface (i.e. the alsa_test.h file).
You don't want to expose types internal structure: add functions in the interface to access structures fields
add in alsa_test.h
void set_alsa_card(struct alsa_device * alsa_dev_list, int dev_id, int card);
and in alsa_test.c
void set_alsa_card(struct alsa_device * alsa_dev, int dev_id, int card)
{
(alsa_dev + dev_id)->card = card;
}
main.c :
#include "alsa_test.h"
int main (int argc, char *argv[]) {
alsa_device *devices;
devices = create_alsa_array(50);
set_alsa_card(devices, 0, 1);
}

Forward declaration C

I have 2 header files api.h and impl.h
api.h is visible to outside files and will be included in other ".c" files. So api.h includes impl.h
api.h defines 2 structures
typedef struct
{
uint32_t att;
union
{
struct
{
void* buffer;
size_t length;
} x;
struct
{
int a, b;
} v;
} content;
}dummy;
and impl.h has some other structures and function def which uses this structure.
I tried forward declaration but it doesn't help me .
Please help .
Actually, your dummy is not a structure, but a typedef to an unnamed structure. Try naming the structure, you can then forward-declare it:
typedef struct sdummy dummy; // forward declaration
void foo(dummy *);
struct sdummy { ... }; // definition
Either reorder your code in api.h so the type declaration precedes the #include "impl.h" or give your (currently anonymous) structure itself a name like dummy, dummy_, dummy_s so you can add a forward declaration
typedef struct dummy_ dummy;
to impl.h.
If you want to hide the details of your struct then you have to define it in some .c file, let's say impl.c, so that it has internal linkage to that compilation unit. To use it you have to expose create, destroy, getter and setter functions. So a basic setup would look like this:
api.h with forward declaration for your struct
// forward declaration
typedef struct dummy* dummy_t;
// create / destroy / setter / getter (omitted)
dummy_t alloc_dummy();
void free_dummy(dummy_t);
void set_number(dummy_t, int);
void set_string(dummy_t, char*);
void print_dummy(dummy_t);
Then comes impl.c
#include "api.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct dummy {
int n;
char* s;
};
dummy_t alloc_dummy()
{
return malloc(sizeof(struct dummy));
}
void free_dummy(dummy_t dummy)
{
if(dummy) {
free(dummy->s);
free(dummy);
}
}
void set_number(dummy_t dummy, int n)
{
if(dummy) {
dummy->n = n;
}
}
void set_string(dummy_t dummy, char* s)
{
if(dummy && s) {
dummy->s = strdup(s);
}
}
void print_dummy(dummy_t dummy)
{
if(dummy) {
printf("%d, %s\n", dummy->n, dummy->s);
}
}
And finally the usage in some other C files, here main.c
#include "api.h"
int main(int argc, char** argv)
{
// struct dummy d; // error! type is unknown
// instead use the create function
dummy_t d = alloc_dummy();
// d->n = 1; // error! dereference of unknown type
// instead use the setter function
set_number(d, 1);
set_string(d, "Hello, world!");
print_dummy(d);
free_dummy(d);
return 0;
}
Ouput
1, Hello, world!

Instantiations for structs in C?

So I'm trying to learn C right now, and I have some basic struct questions I'd like to clear up:
Basically, everything centers around this snippet of code:
#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME_LEN 127
const char* getName(const Student* s);
void setName(Student* s, const char* name);
unsigned long getStudentID(const Student* s);
void setStudentID(Student* s, unsigned long sid);
int main(void) {
Student sarah;
const char* my_name = "Sarah Spond";
setName(&sarah, my_name);
printf("Name is set to %s\n", sarah.name);
}
typedef struct {
char name[MAX_NAME_LEN + 1];
unsigned long sid;
} Student;
/* return the name of student s */
const char* getName (const Student* s) { // the parameter 's' is a pointer to a Student struct
return s->name; // returns the 'name' member of a Student struct
}
/* set the name of student s
If name is too long, cut off characters after the maximum number of characters allowed.
*/
void setName(Student* s, const char* name) { // 's' is a pointer to a Student struct | 'name' is a pointer to the first element of a char array (repres. a string)
int iStringLength = strlen(name);
for (i = 0; i < iStringLength && i < MAX_NAME_LEN; i++) {
s->name[i] = name[i];
}
}
/* return the SID of student s */
unsigned long getStudentID(const Student* s) { // 's' is a pointer to a Student struct
return s->sid;
}
/* set the SID of student s */
void setStudentID(Student* s, unsigned long sid) { // 's' is a pointer to a Student struct | 'sid' is a 'long' representing the desired SID
s->sid = sid;
}
However, when I try and compile the program, I get a bunch of errors saying that there's an "unknown type name Student". What am I doing wrong?
Thanks!
Move the type definition for Student - the typedef .. right after #define MAX_NAME_LEN 127, i.e. before it's being referenced.
You need to move the declaration of the Student struct above the first time it is referenced by other code - otherwise those functions will not know what it is.
Struct declarations need to be defined before you use them , so you need to move your Student
As cnicutar said, move the typedef - the reason for this is that the type must be known before it's used. Alternatively, you can forward declare the type.
> Move the typedef .. right after #define MAX_NAME_LEN 127, i.e. before
> it's being used.
OR, if you want to keep your definition after, and if you are ready to use a pointer to Student, you can:
#include <stdio.h>
#include <stdlib.h>
#define MAX_NAME_LEN 127
// forward declare Student ici
struct Student;
//...
// in main, use a pointer to student
int main(void) {
Student *sarah; // Changed to pointer
const char* my_name = "Sarah Spond";
setName(sarah, my_name); // Pass the pointer instead of reference
printf("Name is set to %s\n", sarah->name); // Use the pointer
//....
delete sarah; // delete object when done
}
// Change struct decl to the following // can't explain the diff yet
struct Student {
char name[MAX_NAME_LEN + 1];
unsigned long sid;
};
A basic structure of a C program is:
//======DOCUMENT SECTION=========
//File:test.c
//Author:
//Description:
//...
//================================
//====INCLUDE SECTION=============
#include "lib1"
#include <lib2>
//================================
//========DEFINITIONS SECTION=====
#define TRUE 1
#define FALSE 0
//================================
//========STRUCTURES SECTION======
struct P{
};
//================================
//========TYPEDEFS SECTION========
typedef *P P;
//================================
//========FUNCTION HEADERS========
void foo1(...);
int foo2(...,...,...);
//================================
//=========GLOBAL VARIABLES=======
int GLOBAL_INT;
float GLOBAL_FLOAT;
//================================
//=====MAIN FUNCTION DEFINITION===
void main(void)
{
...
...
...
}
//=================================
//======FUNCTIONS DEFINITION======
void foo1(...)
{
}
int foo2(...,...,...)
{
}
//================================
A main function is where a C program starts. A main function also typically has access to the command arguments given to the program when it was executed.
Usually you have got:
int main(void);
int main();
int main(int argc, char **argv);
int main(int argc, char *argv[]);

Resources