How do i make this into a struct? - c

OK so I have erased everything trying to make this into a struct, because i messed it up bad.
I need this code of arrays to become a struct.
FILE *pFile;
int choice = 0;
char buf[40];
int id[sizeof(buf)];
char name[sizeof(buf)][20];
char state[sizeof(buf)][5];
char dis_code[sizeof(buf)];
float balance[sizeof(buf)];
char due_date[sizeof(buf)][40];
This is what I got do so far but when i try to use it it goes nuts. I still don't know how to load the file into it.
struct fileinfo
{
int id[10];
char name[20];
char state[5];
char dis_code[5];
float balance[10];
char due_date[40];
} info[sizeof(buf)];
Am i missing something or do i have the right idea. The problem is when i run this the same why i would the regular arrays I run into errors.

I'm not sure if this is your only issue, but you have changed the type of several of the fields.
int id[sizeof(buf)]; // id[i] is an int
char dis_code[sizeof(buf)]; // dis_code[i] is a char
float balance[sizeof(buf)]; // balance[i] is a float
struct fileinfo
{
int id[10]; // info[i].id is an _array of 10 ints_
char dis_code[5]; // info[i].dis_code is an _array of 5 chars_
float balance[10]; // info[i].balance is an _array of 10 floats_
} info[sizeof(buf)];
An array of a type and single instance of that type will behave quite differently.
I would suggest making the fields of the struct the same type as your original array elements, i.e.:
struct fileinfo
{
int id;
char dis_code;
float balance;
}

Since you declared char buf[40] ==> sizeof(buf) = 40. You are changing the 2 dimensional array into a single dimensional. The structure should be like
struct fileinfo
{
int id[40];
char name[40][20];
char state[40][5];
char dis_code[40];
float balance[40];
char due_date[40][40];
}

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.

Sending Pointers of Structs to a Function in C

I don't love this, but I have a struct with nearly 45 members inside; all are characters or character arrays. That said, I am going to need to optimize the way I initialize each struct. Ordinarily, I would pass the entire object into my init_struct() function, but I feel like that is not the best way to do this.
How would I create and use a pointer to the struct to accomplish this?
Old Method would look something like this:
void init_struct(struct general){
...initialize members...
}
int main(){
struct general[10];
for(int i = 0 ; i < 10 ; ++i){
init_struct(general[i];
}
}
Since this struct is so large, as I said nearly 45 members inside it, I think a point to the struct would go a long way in optimizing this process. How would I accomplish that?
Just in case you need, here is the typedef for my struct
typedef struct
{
//Basically, everything we want to read from HUDL should be here...
int play_num;
char down;
char dist[3];
char ydln[4];
char gnls[3];
char hash[3];
char home[20];
char away[20];
char odk[2];
char qtr[2];
char series[3];
char result[20];
char penalty[20];
char act_cb[20]; //How do they act post-snap
char act_dl[20];
char act_lb[20];
char act_ol[20];
char act_qb[20];
char act_rb[20];
char act_saf[20];
char aln_cb[20]; //How do they align pre-snap
char aln_dl[20];
char aln_lb[20];
char aln_ol[20];
char aln_qb[20];
char aln_rb[20];
char aln_saf[20];
char aln_wr[20];
char blitz[20];
char box_cnt[3];
char saf_count[20];
char coverage[20];
char cvr_basic[20];
char def_front[20];
char mtn_def[20];
char num_rush[3];
char off_form[20];
char form_var[20];
char motion[20];
char off_pro[20];
char off_play[20];
char play_var[20];
char personnel[20];
char play_type[20];
char time[2];
char score_diff[4];
char field_zone[2];
char dd_type[2];
char form_strength[2];
} HUDL; // MAXIMUM of 63 Members
There's a couple of things wrong on your code.
First of, your function definition is wrong because you omit the parameter name. Your function definition should look like this:
void init_struct(struct general mygeneralstruct){}
Alternatively, you could use an alias for your struct using typedef, like so:
typedef struct {
int a;
} general;
In which case, your function declaration could look like this:
void init_struct(general mygeneralstruct){}
You have the same problem when you declare your array of structures. You omit the name of your variable. Instead of
struct general[10];
it should be
struct general mygeneralstruct[10]
or
general mygeneralstruct[10](typedef)
Finally, you can't change your array of structures by passing each structure's value to the function. You need to pass each structure's address instead.
Your function declaration should then be(using typedef):
void init_struct(general* mygeneralstruct){}
and the code in the loop:
init_struct(&mygeneralstruct[i]);
To pass a pointer to your array element, you just prefix the parameter with &, make sure you declare the function correctly:
void init_struct(HUDL* pGeneral){
if ( pGeneral != NULL ) {
//This will ensure the entire structure contains '0'
memset(pGeneral, 0, sizeof(HUDL));
...initialize members...
}
}
int main(){
HUDL general[10];
for( int i=0; i<(sizeof(general) / sizeof(general[0])); i++ ) {
init_struct(&general[i]);
}
}
I'm not sure why you haven't used the typedef 'HUDL' makes life a lost easier and code easier to read.
A slightly cleaner and better approach would be to have a constructor and destructor function to allocate memory dynamically to structure and free it after use.
static void HUDL_destroy(HUDL* ptr)
{
if(ptr)
{
//...any other clean up that needs to be done goes here..
free(ptr);
}
}
static HUDL* HUDL_create()
{
HUDL* ptr = malloc(sizeof(HUDL));
if(!ptr)
return NULL;
//do initialization bits...
init_struct(ptr);
return ptr;
}
int main()
{
//allocate and initialise structure
HUDL *general = HUDL_create();
//do stuff...
//free structure after use
HUDL_destroy(general);
}
You might need an array of pointers in your case. So modify your main() accordingly.
int main()
{
//we need an array of structure pointers
HUDL* general[SIZE];
//allocate and initialize structure
for(int i=0; i<SIZE; i++)
general[i] = HUDL_create();
//do stuff...
//free structure after use
for(i=0; i<SIZE; i++)
HUDL_destroy( general[i] );
}

Looping through C struct w/o union

My intention: To loop through -- without using unions -- 30 members of a structure, all of type character array, storing in each the result of a call to itoa. In the following code, I name the structure members a-z,A-D. In the calling function, I initialize a string of those characters, called 'letters', then I try to loop through the structure members by referring to them with my increment variable as the index into letters. Then, I try to dump the contents of each member of the structure. **edit: I realize that the members wouldn't contain anything, given what code you can see. The problem seems to be with referring to struct members like this.
struct listArrays {
char a[10];
char b[10];
char c[10];
char d[10];
char e[10];
char f[10];
char g[10];
char h[10];
char i[10];
char j[10];
char k[10];
char l[10];
char m[10];
char n[10];
char o[10];
char p[10];
char q[10];
char r[10];
char s[10];
char t[10];
char u[10];
char v[10];
char w[10];
char x[10];
char y[10];
char z[10];
char A[10];
char B[10];
char C[10];
char D[10];
};
struct listArrays Ternaries;
int testTernary(){
char letters[30] = "ABCDabcdefghijklmnopqrstuvwxyz";
int i;
for(i = 0; i < 30; ++i){
dumpArray((Ternaries.(letters[i])), 10);
}
return 0;
}
The error I get is "expected identifier before '(' token."
Problems I have ruled out:
-The dumpArray function works fine.
-Looping through the letters works fine, outside the context of the
referral to struct members
Identifiers (names) only exist in the program text. Once compiled and linked, they no longer exist. So you can't "index" the struct for the letter. What you can do is:
struct listArrays {
char letters[30][10];
};
Now you can access these "letters":
dumpArray((Ternaries.letters[i]), 10);

Create a struct with more than 1 dynamically sized array in c?

Is it possible to create a struct containing two dynamically size arrays in c?
I have something like this:
#define MAX_DATA 512
struct Address {
int id;
int set;
char name[MAX_DATA];
char email[MAX_DATA];
};
I'd like MAX_DATA to be defined at run time.
I have seen the struct hack:
How to include a dynamic array INSIDE a struct in C?
But I think this only works for one field per struct?
This code is from http://c.learncodethehardway.org/book/ex17.html
The extra credit section near the bottom of that page contains the bit about changing the sizes to be dynamic.
I once did this:
struct Thing {
int Number;
char *MoreBytes;
char Bytes[]
}
Thing *MakeThing(int nBytes, int nMoreBytes)
{
Thing *th = malloc(sizeof(Thing) + nBytes + nMoreBytes);
// Error checking is for grrrlz.
th->Number = 42;
th->MoreBytes = th->Bytes + nBytes;
return th;
}
Thus the array th->Bytes actually holds both "arrays", and the pointer th->MoreBytes tells us
where one array ends and another begins.
It works (at least for GCC 4.7.2) if you put your struct Address definition in a function, like this:
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
int len = atoi(argv[1]);
struct Address {
int id;
char name[len];
int set;
char email[len];
};
printf("sizeof(struct Address) = %zu\n", sizeof(struct Address));
exit(EXIT_SUCCESS);
}
Testing:
$ ./a.out 10
sizeof(struct Address) = 32
$ ./a.out 20
sizeof(struct Address) = 48
struct Address
{
int id;
int set;
char *name;
char *email;
};
Now in the main() function, Use some variable, lets say len to store length of the array, and dynamically allocate required memory using malloc().
int len;
struct Address Add;
printf("Enter the lenght of the array you want?");
scanf("%d",&len);
Add.name=(char *)malloc(len);
Add.email=(char *)malloc(len);
otherwise you can add len as the member of the struct Address
struct Address
{
int id;
int set;
int len;
char *name;
char *email;
};
Now in main()
struct Address Add;
printf("Enter the lenght of the array you want?");
scanf("%d",&Add.len);
Add.name=(char *)malloc(Add.len);
Add.email=(char *)malloc(Add.len);
You can do this using the struct hack, now known as a flexible array. It just requires you to pack both arrays into the flexible part of the struct.
Suppose that you want the arrays to be of length N and M respectively. Then allocate a flexible array as if you were allocating a single array of length N+M. Then use indices 0..N-1 for the first array, and indices N..N+M-1 for the second array.

how to write the character value from structure into the serial interface and convert into integer value?

struct MemoryTag1;
typedef struct MemoryTag1{
char a[8]= {'+','0','2','6','.','5','EA','\r'}; // setpoint temperature value
char b[8]= {'-','0','2','4','.','5','EB','\r'};
char c[6]= {'+','0','2','0','EC','\r'};
}Memory1;
// This is a message structure which I want to transfer over the serial interface (RS232) and later convert into integer value. please guide me in this.
Your syntax is a bit off - try this:
// declare Memory1 struct type to hold data
typedef struct MemoryTag1 {
char a[9]; // setpoint temperature value
char b[9];
char c[7];
} Memory1;
// allocate and initialise a Memory1 struct
Memory1 m = { {'+','0','2','6','.','5','E','A','\r'},
{'-','0','2','4','.','5','E','B','\r'},
{'+','0','2','0','E','C','\r'} };
Really, to be honest, I'd prefer more information. But it doesn't really matter. It only affects the method of output. If you were running this on an arduino, for instance, you could output to the serial ports as easily as:
Serial.begin(9600);
Serial.write('a');
etc, etc
As others have mentioned, there are situations in which you'd be better off using null-terminated strings. If however, you had a particular reason to do so, then I suppose you could;
#include <stdio.h>
typedef struct memoryTag1_t
{
char a[9]; // setpoint temperature value
char b[9];
char c[7];
} *pMemoryTag1_t;
typedef struct memoryTag2_t
{
char a[10]; // setpoint temperature value
char b[10];
char c[8];
} *pMemoryTag2_t;
void displayField1(char *field, int len)
{
for (int i=0; i<len; i++)
{
if (i!=0) printf(",");
printf("%c", field[i]);
}printf("\n");
}
void displayField2(char *field)
{
bool firstDone = false;
while (*field)
{
if (firstDone)
printf(",");
else
firstDone = true;
printf("%c", *field++);
}
printf("\n");
}
int main()
{
memoryTag1_t myMem1 =
{
{'+','0','2','6','.','5','E','A','\r'},
{'-','0','2','4','.','5','E','B','\r'},
{'+','0','2','0','E','C','\r'}
};
memoryTag2_t myMem2 =
{
"+026.5EA\r",
"-024.5EB\r",
"+020EC\r"
};
displayField1(myMem1.a, sizeof(myMem1.a));
displayField1(myMem1.b, sizeof(myMem1.b));
displayField1(myMem1.c, sizeof(myMem1.c));
displayField2(myMem2.a);
displayField2(myMem2.b);
displayField2(myMem2.c);
}
Output:
(Don't forget there's a \r printed 'after' the last comma in each line)
+,0,2,6,.,5,E,A,
-,0,2,4,.,5,E,B,
+,0,2,0,E,C,
+,0,2,6,.,5,E,A,
-,0,2,4,.,5,E,B,
+,0,2,0,E,C,
you can not declare struct in C in this way:
it should be
typedef struct MemoryTag1{
char a[9];
char b[9];
char c[7];
}Memory1;
you can set value in the declaration of an object of this structure:
Memory1 test = {
{'+','0','2','6','.','5','E','A','\r'},
{'-','0','2','4','.','5','E','B','\r'},
{'+','0','2','0','E','C','\r'}
};
If you use this bloc in each initiation of a Memory1 object so you can use macro to make it easier:
#define INIT_MEMORYTAG1 {\
{'+','0','2','6','.','5','E','A','\r'},\
{'-','0','2','4','.','5','E','B','\r'},\
{'+','0','2','0','EC','\r'}\
}
and then in your declaration of a Memory1 object:
Memory1 test = INIT_MEMORYTAG1;
BTW: You can not put 'EA', 'EB', 'EC' like a 1 charachter you have to separate them to:
'E','A', 'E','B', 'E','C' and so you have to update your char array sizes in the struct definition
That is really not C syntax.
You can't have initializers in declarations of types, that doesn't have any meaning.
You need to do it like this, to build the message:
typedef struct {
char a[10];
char b[10];
char c[8];
} Memory1;
int main(void)
{
Memory1 m1;
strcpy(m1.a, "+026.5EA\r");
strcpy(m1.b, "-024.5EB\r");
strcpy(m1.c, "+020EC\r");
return 0;
}
Note that the above will build proper C strings in the fields of the message, i.e. there will be 0-characters acting as terminators. The sizes were too small, so I changed that.
It's trivial to ignore the terminator characters if you need to send this over some format that doesn't allow them; send each field separately.
Converting one of the fields back into integers could be done using sscanf(), for instance.

Resources