How do I create a dynamic array of struct pointers? - arrays

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.

Related

How to assign an array to a struct in C

Say I have a simple struct, such as this one:
struct myStruct {
uint8_t arr[10];
};
All I want to be able to do is to modify the contents of that array. However, it seems that I cannot assign the array directly (ie, I can't do something like pointerToThisStruct->arr = anArrayofSizeTen).
So here is my main method:
int main(int argc, char **argv) {
uint8_t test[10] = {0};
myStruct *struc;
struc->arr = test; //can't do this
memcpy(struc->arr, test, sizeof(test));
}
Now, I understand that direct copying over won't work, but why is memcpy also giving me a segfault? How exactly am I supposed to modify the struct array?
You need to declare an actual myStruct. Not a pointer to one. Declaring a pointer to one doesn't actually allocate any memory for the struct.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
struct myStruct {
uint8_t arr[10];
};
int main(int argc, char **argv) {
int i;
uint8_t test[10] = {0,1,2,3,4,5,6,7,8,9};
struct myStruct struc;
memcpy(struc.arr, test, sizeof(struc.arr));
printf("struc.arr[] = ");
for( i=0; i < sizeof(test); i++ )
{
printf("%d ", struc.arr[i]);
}
printf("\n");
return( 0 );
}
You are getting a segmentation fault because you didn't allocate your struct pointer.
int main(int argc, char **argv) {
uint8_t test[10] = {0};
struct myStruct *struct = malloc(sizeof(struct myStruct));
if (!struc)
return -1;
memcpy(struc->arr, test, sizeof(test));
free(struc);
return 0;
}
But, as #Chimera mentioned, you perfectly can not use a point and directly a heap-allocated structure, and access to its inner fields with the . operator

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.

accessing the array inside array of structures

I have a structure as follows
struct a
{
char* ap;
char* inputs[10];
int e;
};
then I have created an array of this structure like struct a list [100];
now i want to fille the array inputs[10] and for that I am using the syntax to access the first location :
ip=0;
inp=0;
list[ip].inputs[inp]
but I am gettin the error "error C2107: illegal index, indirection not allowed" on compiling the code
please suggest how to access the array location inside array of structure.
regards
priya
Here you use array of character pointer in your structure. So Initially you allocate memory for you structure by creation list of 100. I think you didn't create memory for you array of character pointer. You have to create memory for each of character pointer. So I suggest example code.
#include <stdio.h>
struct a
{
char* ap;
char* inputs[10];
int e;
};
int main()
{
int ip=0;
int inp=0;
struct a list[100];
list[ip].inputs[inp]= (char*)malloc(25);
scanf("%s",list[ip].inputs[inp]);//Or other copy function to fill string
printf("output %s",list[ip].inputs[inp]);
}
Working fine on my pc.. here is my code..
#include <stdio.h>
struct a
{
char* ap;
char* inputs[10];
int e;
};
int main()
{
int ip=0;
int inp=0;
struct a list[100];
list[ip].inputs[inp] = 'A';
printf("This: %c", list[ip].inputs[ip]);
return 0;
}
OUTPUT= This: A
let me know whether it helped or not..
The struct themselves do not have data. You need to create objects of the struct type and set the objects ...
struct a
{
char* ap;
char* inputs[10];
int e;
};
/* I like to separate the type definition from the object creation */
struct a list [3];
list [0].inputs[0] = "Choclate";
list [0].inputs[1] = "Almond";
list [0].inputs[2] = "Rasberry";
Hope it ll usefull. Also refer this article

C struct array and search: Attempting to a match a member and prnt the entire struct if a match is found.

here is the struct
int main() {
typedef struct {
char firstName[25];
char lastName[30];
char street[35];
char city[20];
char state[3];
int zip;
char phone[15];
int accountId;
}Customer ;
say i fill this out with x amount of data.
what is a simple way to search the array index of this struct based on one its members, and then print that "Customers" info. Specifically I am looking to search for customers by state.
Below is an example that I believe will be of some help. Of course, the Customer definition, record printing, and data population need to be expanded. Also note that customer[] is on the stack in this example, so its members aren't zeroed and hence should be set to intended values one way or another.
#include <string.h>
#include <stdio.h>
#define NUM_RECORDS 10
int main()
{
int i;
typedef struct {
char state[3];
} Customer;
Customer customer[NUM_RECORDS];
strcpy(customer[2].state, "CA");
for (i = 0; i < NUM_RECORDS; i++)
{
// if this customer record's state member is "CA"
if (!strcmp(customer[i].state, "CA"))
printf("state %d: %s\n", i, customer[i].state);
}
// Prints "state 2: CA"
return 0;
}

printing data from a struct

I have a nested array of structures in the following form:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char* e_name;
char* e_lastname;
}emp_name;
typedef struct
{
emp_name name;
int id;
}emp;
int main(int argc, char *argv[])
{
int i;
int cod=100;
emp job[3];
for (i=0;i<3;i++)
{
scanf("%s",&job[i].emp.e_lastname);
job[i].id=cod;
cod++;
}
for (i=0;i<3;i++)
{
printf("%s",job[i].emp.e_lastname);
printf("%d\n",job[i].id);
}
system("PAUSE");
return 0;
}
but the program hangs in the printing part, why is that?
Thanks
You have three problem:
First you want to access:
job[i].name.e_lastname
not
job[i].emp.e_lastname
Second You should have:
scanf("%s",&job[i].name.e_lastname);
instead of
scanf("%s",job[i].name.e_lastname);
You do not pass & since it is an array you are passing to the scanf function.
Third problem you should allocate memory to your char *e_lastname and char *e_name camps of the struct emp_name.
Note that:
scanf
int scanf ( const char * format, ... );
Reads data from stdin and stores them according to the parameter
format into the locations pointed by the additional arguments.
The additional arguments should point to already allocated objects
of the type specified by their corresponding format specifier within
the format string. (source)
So you want this:
int main(int argc, char *argv[])
{
int i;
int string_size = 10;
int cod=100;
emp job[3];
for (i=0;i<3;i++) // Allocate space for the string you will access.
{
job[i].name.e_name = malloc(sizeof(char)*string_size);
job[i].name.e_lastname = malloc(sizeof(char)*string_size);
}
for (i=0;i<3;i++)
{
scanf("%s",job[i].name.e_lastname);
job[i].id=cod;
cod++;
}
for (i=0;i<3;i++)
{
printf("%s",job[i].name.e_lastname);
printf("%d\n",job[i].id);
}
system("PAUSE");
return 0;
}
Consider the fact that using scanf is unsafe, because:
If you use the %s and %[ conversions improperly, then the number of
characters read is limited only by where the next whitespace character
appears. This almost cetainly means that invalid input could make your
program crash, because input too long would overflow whatever buffer
you have provided for it. No matter how long your buffer is, a user
could always supply input that is longer. A well-written program
reports invalid input with a comprehensible error message, not with a
crash. (source)
Nevertheless, their are some workaround that you can do to use scanf (check them here)
Instead of scanf you can use fgets. fgets allows you to limit the data that will be placed in your buffer.
You really need to be careful with pointers and what is allocated or not.
I have rewritten your code but with the wrong solution. check comments.
#include <stdio.h>
#include <stdlib.h>
typedef struct emp_name {
/*
* now there you had just char*. this decares
* a pointer to some memory but no memory is allocated.
* if you were going with that approach you should initialize
* the struct and assign those values to something you malloc'ed().
* This version suffers from fixed size and a possible buffer overflow if
* you chose scanf to write the data in the buffer.
*/
char e_name[512];
char e_lastname[512];
/*
* try to follow conventions. your previous struct declarations
* were anonymous. if it caught an error you wouldn't know in which
* struct it would be. good practices here: link1 (bottom)
*/
} emp_name_t;
typedef struct emp {
emp_name_t emp;
int id;
} emp_t;
int main(int argc, char *argv[]) {
int i;
int cod=100;
emp job[3];
for (i=0;i<3;i++) {
/*
* check out this excelent post for a secure alternative:
* link2 (bottom)
*/
scanf("%s",&job[i].emp.e_lastname);
job[i].id=cod;
cod++;
}
for (i=0;i<3;i++) {
printf("%s",job[i].emp.e_lastname);
printf("%d\n",job[i].id);
}
return 0;
}
link1: openbsd style(9)
link2: disadvantages of scanf
I see you have:
typedef struct
{
char* e_name;
char* e_lastname;
}emp_name;
typedef struct
{
emp_name name;
int id;
}emp;
emp job[3];
So what is .emp doing in the following line? Its not a member of any structure
job[i].emp.e_lastname

Resources