How to parse a structure array as a parameter? - c

How should I parse an array of structures as parameter to a function?
For example, I have the following structure definition:
struct Town
{
char *TownName;
char **GiftList;
int *GiftCount;
int GiftTypes;
};
and a declaration of an array of such structures, in my main:
struct Town TownList[100];
struct Town AuxiliaryStructure;
I have written a custom sorting function for this array, in which I want to make use of each structure's fields, but I do not know how to provide the array TownList[100] to the sort function.

To pass an array of anything to a function, you can just pass a pointer to the first element plus an array length:
struct mystruct {
char* something;
/* ... */
}
struct mystruct myarray[100];
void do_something(struct mystruct* array, int length)
{
int i;
for (i=0; i<length; ++i)
{
array[i].something = ...
}
}
int main(void)
{
do_something(myarray, 100);
return 0;
}

Based on what you wrote, you would reference it in the caller and pass the result. For example:
void sort(char* str){
...
}
int main(){
for(int i=0; i<100; ++i){
sort(array[i].something);
}
}
Alternately you may want to pass the full array and handle it in another function, which would be like this:
void sort(struct mystruct * array){
...
}
int main(){
for(int i=0; i<100; ++i){
sort(array);
}
}
If, on the other hand, you meant that you want to sort the outer array of structures by the contents of something, then you would either have to pass the array as above and implement your own sort, or use a sorting function that takes a function pointer so you can write a comparator. The latter is available in the standard C library, and could be used something like this.
#include <stdlib.h>
int compare_mystruct_by_something(const void *a, const void *b){
return strcmp(((struct mystruct*)a)->something, ((struct mystruct *)b)->something);
}
int main(){
qsort(array, 100, sizeof(struct mystruct), compare_mystruct_by_something);
}

Related

How to pass a pointer to the array of structure in another fuction

I am trying to pass pointer to an array of structures to another function
#include<stdio.h>
#include<string.h>
typedef struct CovidData{
char region[7];
char towns[12];
char race[12];
int yearlyIncome;
int members;
int testedMembers;
int testedPositive;
} CovidData;
void RandomDataGenerator(CovidData *data[] ,int count)
{
for(int i=0;i<count;i++){
memcpy(data[i]->region,"david",sizeof("david"));
memcpy(data[i]->towns,"david",sizeof("david"));
memcpy(data[i]->race,"david",sizeof("david"));
data[i]->yearlyIncome=1000;
data[i]->members=99;
data[i]->testedMembers=88;
data[i]->testedPositive=656;
}
}
int main() {
struct CovidData data[100];
RandomDataGenerator(&data,2);
for(int i=0;i<5;i++){
printf("%s",data[i].region);
}
}
But it throws an error while compiling in terminal with gcc
incompatible pointer types passing 'CovidData (*)[100]' to
parameter of type 'CovidData
CovidData *data[] is grouped as CovidData *(data[]), so it declares an array of pointers to CovidData. For a pointer to an array, you would use CovidData (*data)[].
However, we rarely pass a pointer to an array. Usually, it is sufficient and convenient merely to pass a pointer to the first element. Thus, you would declare the parameter as CovidData *data and pass it as RandomDataGenerator(data, 2).
If you did declare the parameter as a pointer to an array, you would not use it with data[i]->region. You would need *data to get the array before applying the subscript, and again you would need parentheses for correct grouping: (*data)[i]->region.
Change your function to void RandomDataGenerator(CovidData *data ,int count); and pass only the pointer to the first array element, like this RandomDataGenerator(data,2);
#include<stdio.h>
#include<string.h>
typedef struct CovidData{
char region[7];
char towns[12];
char race[12];
int yearlyIncome;
int members;
int testedMembers;
int testedPositive;
} CovidData;
void RandomDataGenerator(CovidData *data ,int count)
{
for(int i=0;i<count;i++){
memcpy(data[i].region,"david",sizeof("david"));
memcpy(data[i].towns,"david",sizeof("david"));
memcpy(data[i].race,"david",sizeof("david"));
(data+i)->yearlyIncome=1000;
data[i].members=99;
data[i].testedMembers=88;
data[i].testedPositive=656;
}
}
int main() {
struct CovidData data[100];
RandomDataGenerator(data,2);
for(int i=0;i<5;i++){
printf("%s\n",data[i].region);
}
}

Array of structures: printing all members of each structure

I'm trying to print out all the members of each structure from a list. I was provided the print functions below to print out an element from a generic list.
Here is the structure definition of my list, which is in a generic list ADT c file:
struct list_type {
void *data;
int size;
int capacity;
int elementSize;
int (*comparePtr) (void *d1, void *d2);
};
So in a generic list ADT c file, I have this print function:
// client needs to send a pointer to a function capable of printing an element
void printl(ListType listptr, void (*printItem) (void *d)) {
int i;
for(i = 0; i < listptr->size; i++) {
// since we cannot use data[i], we need to calculate the address
// of the element to be sent to the client's print function
// since data is of type void, the formula is:
// the beginning address of the array + (offset x element size)
printItem(listptr->data + i * (listptr->elementSize) );
printf(" ");
}
printf("\n");
}
I call my printl function like so:
printl(clientList, printItem);
In my driver file, there's a function to print out an element from the list:
void printItem (int* p) {
printf("%d", *p);
//`my attempt at printing the members of an individual structure from the list
// printf("%s", ((Client *)&p)[0]);
}
Here is my Client structure definition:
struct client_tag {
char id[5];
char name[30];
char email[30];
char phoneNum[15];
};
When I run the program, I get a bunch of weird characters. How do I fix this?
Assuming you left out the line
typedef struct client_tag Client;
and assuming the strings of Client are guaranteed to be null terminated, this is the idea:
void printItem (const Client* p) {
printf("%s\n", p->id);
}

Accessing a struct without the struct being global

I've got a struct called members which contains a bunch of char arrays and integers. The struct has been declared in Header.h and defined it by "struct members pt" in source.c, inside main. From here a for-loop is being runned 5 times and adding variables to the character arrays and ints in pt[x].
Now I need to be able to access this from a function called void search(int a); (Should probably not be a void since I want it to return a value. But I'll fix that later)
What void search is supposed to do is basicly
int willReturn[10];
int b = 0;
for(int x = 0; x<a; x++)
{
if(pt[x].hasPayed == 0)
{
willReturn[b] = x;
b++;
}
}
There might be something wrong about that code, but the thing that I need to know is how I can access pt[x].hasPayed.
Any ideas?
I do not want to use any global variables.
Thank you in advance.
Below sample code might help you.
header.h
struct members {
int hasPayed;
};
main.c
#include <stdio.h>
#include <string.h>
#include "main.h"
typedef struct members MEMBERS;
void print_member(MEMBERS *pt) {
int i;
for(i =0 ; i< 10; i++)
{
printf(" %d\n",pt[i].hasPayed);
}
}
void main () {
MEMBERS pt[10];
int i;
for(i =0 ; i< 10; i++)
{
pt[i].hasPayed= i;
}
print_member(pt);
}
Instead of print_member code your search logic.
Pass a pointer to pt as a paraamter to search. e.g void search(int a, struct members *pt).
Another way if you don't want to pass pointers. Place pt in a function as a static variable.
struct members** ____get_pt(){
static struct members pt[ /* size */ ];
/*
or for dynamical size,
static struct members* pt;
*/
return &pt;
}
// Define a macro for convenience, above where you want to use 'pt'.
#define PT (*____get_pt())
Then you can use PT[x].hasPayed everywhere, without global variables.
However, this could do not improve your code ...

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.

Is there a tool that can refactor this C code correctly?

Lets say I have the following code (the array* function are what we use for resizable arrays and they operate on pointers-to-arrays that are null initialized):
typedef struct MyStruct
{
int i;
} MyStruct;
MyStruct* GetNewMyStruct(int i)
{
MyStruct* s = malloc(sizeof(MyStruct));
s->i = i;
return s;
}
int SomeFunction(int number, MyStruct *elem)
{
MyStruct **structs = NULL;
int i;
for (i = 0; i < number; i++)
arrayPush(&structs, GetNewMyStruct(i));
arrayPush(&structs, elem);
return arraySize(&structs);
}
I decide that SomeFunction is too large and I want refactor it. Currently where I work we use VisualAssist X, which has some refactoring capabilities, but when I use it on this it does not work correctly. If I attempt to use it to refactor out the loop, this is what I get:
void MyMethod( int number, MyStruct ** structs )
{
int i;
for (i = 0; i < number; i++)
arrayPush(&structs, GetNewMyStruct(i));
}
int SomeFunction(int number, MyStruct *elem)
{
MyStruct **structs = NULL;
MyMethod(number, structs);
arrrayPush(&structs, elem);
return arraySize(&structs);
}
This is not correct. MyMethod should take a MyStruct ***, not a MyStruct **. This is because the code I'm refactoring takes the address of structs. The result is that the refactored version will always return 1 (since only one object has been pushed into my array) rather than number+1. Are there other tools out there that do this type of refactoring correctly?
Eclipse CDT does this correctly (at least the current version Juno). Selecting the declaration of i and the loop and doing Refactor > Extract Function, and setting structs to be an output parameter, produces:
void MyMethod(int number, MyStruct*** structs) {
int i;
for (i = 0; i < number; i++)
arrayPush(&*structs, GetNewMyStruct(i));
}
int SomeFunction(int number, MyStruct *elem)
{
MyStruct **structs = NULL;
MyMethod(number, &structs);
arrayPush(&structs, elem);
return arraySize(&structs);
}

Resources