accessing the array inside array of structures - c

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

Related

failing freeing dynamic struct array in c

I'm having some problem with freeing dynamic struct array and I can't understand why.
first of all there is this struct:
typedef struct
{
char name[LEN];
char address[MAX];
} Airport;
And the constructor I made for this struct isn't using allocation for this struct building.
sec of all there is this struct:
typedef struct
{
Airport* airports;
int maxAPS;
int currentAPS;
} AirportManager;
//constructor
void addAirport(AirportManager* pAirportManager)
{
if (pAirportManager->maxAPS == pAirportManager->currentAPS)
{
pAirportManager->maxAPS++;
pAirportManager->airports = (Airport*)realloc(pAirportManager->airports, sizeof(Airport)*pAirportManager->maxAPS);
//pAirportManager->airports[pAirportManager->currentAPS] = *(Airport*)malloc(sizeof(Airport));
}....
and when I'm ending my program and want to free the AirportManager with the following code:
void freeAirportManager(AirportManager* pAirportManager)
{
for (int i = 0; i < pAirportManager->currentAPS; i++)
free(&pAirportManager->airports[i]);
free(pAirportManager->airports);
}
I've debuged this one and all the parameters are just fine but after one run in the loop the program exits, what should I change in the free function ?
do I need the marked line in the constructor ? I just added this on thinking it might help, but seems to not work as well... do I need to free only the array itself ?
for (int i = 0; i < pAirportManager->currentAPS; i++)
free(&pAirportManager->airports[i]);
You need only to free pAirportManager->airports. You do not have pointer to pointer here.
So instead of those two lines:
free(pAirportManager->airports);
I would use flexible array member instead of pointer.
typedef struct
{
char name[LEN];
char address[MAX];
} Airport;
typedef struct
{
size_t maxAPS;
size_t currentAPS;
Airport airports[];
} AirportManager;
For sizes use size_t type instead of int

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] );
}

Sorting arrays of strings/struct in C

I'm a newbie with C language and I need to make a function to sort an array of struct Student data types (after the element Student.ime alphabetically). I am not really sure where to put the pointers so I can return the new array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Student {
int id;
char ime[20];
char prezime[20];
char brindexa[20];
struct Datum datum_rodjenja;
};
struct Student sortiraj(struct Student niz[], int vel)
{
int i, j;
struct Student tempo;
tempo = niz[0];
for(j=0 ; j<vel ; j++)
{
for(i=j ; i<vel ; i++)
{
if(strcmp(tempo.ime,niz[i].ime)>0)
{
tempo = niz[i];
}
i++;
}
niz[j] = tempo;
j++;
}
return niz;
}
The array is stored in a .txt file but that is not the problem. One more thing, how do I call the function in the main(). I thought maybe like this?
niz=sortiraj(niz, vel);
Can someone give me any tips please. Thank you.
You seem to be sorting the array in-place, so you don't really need to return it at all. Also, use the standard library function qsort():
int cmp(const void *ap, const void *bp)
{
const struct Student *a = ap, *b = bp;
return strcmp(a->ime, b->ime);
}
struct Student students[] = { /* whatever */ };
qsort(
students,
sizeof(students) / sizeof(studends[0]),
sizeof(students[0]),
cmp
);
Also, please use English function and variable names.
Have you considered using the qsort() function? Example:
If you have an array of strings say strings, (Note: not an array of structs), with the number of strings being say, cnt then:
qsort(strings, cnt, sizeof(char*), sortstring);
With the function sortstring defined as:
static int sortstring( const void *str1, const void *str2 )
{
const char *rec1 = *(const char**)str1;
const char *rec2 = *(const char**)str2;
int val = strcmp(rec1, rec2);
return val;
}
//for a simple test, run this main with the code above:
int main(void)
{
char *strings[]={"this", "is", "a", "test", "of", "the", "qsort", "function", "to", "try"};
int strlen = sizeof(strings)/sizeof(char *);
qsort(strings, strlen, sizeof(char *), sortstring);
return 0;
}
//Note my environment required #include <ansi_c.h>
First of all, your function signature is not marked return type as an Array of Students. Second of all, I don't know which sorting algorithm you're trying to use, but your implementation isn't right.
If you correct your function signature, you shouldn't get any error by the way you're calling the:
struct Student* sortiraj(struct Student niz[], int vel)
tips about your sortiraj: Check either selection sort or bubble sort for your sort algorithm. And for further study, you can check some recursive algorithms like merge sort and quick sort which are more advance and you need more programming knowledge to implement them.
Change the return type of function sortiraj to void.
Create and fill the struct Student niz[] array in function main.
From function main, pass the array and its length (vel) to function sortiraj.
And of course, no need to return anything from function sortiraj (as implied in section 1).
Since you are passing in a pointer, namely niz, you are changing the memory that niz points to. This means that you don't have to return niz.
However if you want to return niz your function's return type must be the same type as niz. Currently you have a return type of just struct Student so you should be getting a compilation error.

struct as unknown argument

I know how to pass an unknown amount of arguments from unknown types to a function.
I mean something like this:
char* plugins_entry(const char* data, ...);
Now I am trying to pass a struct besides a few other arguments to that function. I have the same struct declared (or defined?) in both files (main.c and plugins.c). But when I try to "filter" the irc struct passed from the main.c out and parse the data in the irc struct from the plugins.c, I don't get anything usefull. When I call the function I get a segementation fault.
This is the important part from the main.c:
struct irc_data {
char nick[32];
char user[32];
char host[64];
char chan[32];
char message[512];
int is_ready;
};
....
int main(int argc, char** argv) {
....
struct irc_data *irc = malloc(sizeof(struct irc_data));
....
(*lib_plugin)("r",irc); // call the function in plugins.c
....
}
And here the hole plugins.c:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
struct irc_data{
char nick[32];
char user[32];
char host[64];
char chan[32];
char message[512];
int is_ready;
};
char* plugins_entry(const char* data, ...) {
int i;
struct irc_data *irc = malloc(sizeof(struct irc_data));
va_list args;
va_start(args, data);
for(i=0; data[i] != '\0'; ++i){
if(data[i] == 'r'){
irc = data[i];
}
}
va_end(args);
printf("\n\n------------------------\n");
printf("What we got here: %s\n",irc->nick);
printf("\n------------------------\n\n");
return "done";
}
So, I am pretty sure that I am doing something wrong with the pointers.
Could you please help me out here?
Thank you
~ Tectu
The line irc = data[i] doesn't make any sense. You need to call va_arg:
if(data[i] == 'r') {
irc = va_arg(args, struct irc *);
}
Also, the malloc in plugins_entry is useless, it will only leak memory.
You don't extract the pointer to the struct using va_args(). With that, you should be able to directly use your struct:
struct irc_data *irc = va_args(args, struct irc *);
Note that you don't need to use malloc in this function as long as you don't want to copy explicitly. As your struct is already located on the heap (it's malloc'ed in main.c), you can just use it directly by using the pointer.

dynamically expanding array of struct

I am (trying to) write a server-side daemon in c, and it accepts connections from clients. I need a struct that keeps information on each open connection, so I have created an array of my defined struct, and I have it dynamically re-sizing with realloc.
The problem I have is creating the struct within the array. I keep getting this error:
test.c:41: error: conversion to non-scalar type requested
What am I doing wrong?
I spend most of my time in PHP, and am a noob with c. I realize that I am making some simple, beginner mistakes (in other words, feel free to make fun of me). If I am doing something stupid, please let me know. I've put my quality time in with google, but have not figured it out. I have reproduced the issue on smaller scale, as below:
here is my test.h:
typedef struct test_ test;
and here is my test.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test.h"
//define the struct
struct test_ {
int id;
char *ip;
int user;
char *str;
};
//yes, the list needs to be global
test *test_list;
//
// add an item to the global list
//
int add(int id, char *ip, int size)
{
//
// increment size
if(id>size) {
size = id;
//try to expand the list
test *tmp = realloc(test_list,size);
if(tmp) {
//it worked; copy list back
test_list = tmp;
} else {
//out of memory
printf("could now expand list\n");
exit(1);
}
}
//
// HERE IS THE TROUBLE CODE::
test_list[id] = (struct test)malloc(sizeof(test)+(sizeof(int)*5)+strlen(ip)+1);
test_list[id].id = id;
test_list[id].ip = malloc(strlen(ip));
strcpy(test_list[id].ip,ip);
test_list[id].user = 0;
test_list[id].str = NULL;
}
//
// main
//
int main(void)
{
//initialize
int size = 1;
test_list = malloc(size*sizeof(test));
//add 10 dummy items
int i;
for(i=0; i<10; i++) {
size = add(i, "sample-ip-addr", size);
}
//that's it!
return 0;
}
Try changing
test *tmp = realloc(test_list,size);
to
test *tmp = realloc(test_list,size*sizeof(test));
then delete
test_list[id] = (struct test)malloc(sizeof(test)+(sizeof(int)*5)+strlen(ip)+1);
When you allocate for test_list, there's already space for each member of the struct allocated, so you don't need to do it again. You just have to allocate for any pointers within the struct
The return value from 'malloc' is the memory address you've allocated. You can't cast it to a struct. What would that even mean?
You want something like: test_list=realloc(test_list, num_alloc * sizeof(test_));

Resources