Searching in an array of structs in C - c

What is the best way to search through an array of structs containing both strings and integers in C programming?
An axamle of the array of structs:
struct person {
int age;
int length;
char fname[20];
char lname[20];
};
Typedef struct person Person
int main()
{
Person personarray[100];
}

One commenter pointed out you can use bsearch.
But a simple loop based coding example to answer your question about how to walk the array follows.
#define MAX_NUMBER_OF_PEOPLE 100
#define NAME_BOB "Bob"
struct person {
int age;
int length;
char fname[20];
char lname[20];
};
typedef struct person Person;
int main()
{
Person people[MAX_NUMBER_OF_PEOPLE];
for (int i; i < sizeof (people) / sizeof (struct people); i++) {
Person *person = &people[i];
if (person->age == 21) {
println("%s %s can legally drink\n",
person->fname, person->lname);
}
if (strncmp(person->fname, NAME_BOB, sizeof (NAME_BOB)) == 0) {
println("Bob is %d years old\n",
person->age);
}
}
}

Related

I want to access a general struct field inside another struct's field in C

I have a struct defined like this:
typedef struct {
char id[20];
char descrizione[250];
char tipoSet[30];
int scatoleDisponibili;
float costo;
} Set;
I have another struct called Complex in which I want a field to store an array of only Set struct IDs.
typedef struct {
char idComplesso[20];
content[10];
int dimLogica;
} complex;
So, I want the content array (of max size 10) to be able to store only the string id from a max of 10 Set.
How could I do this in C?
typedef struct {
char id[20];
char descrizione[250];
char tipoSet[30];
int scatoleDisponibili;
float costo;
} Set;
typedef struct {
char idComplesso[20];
int dimLogica;
size_t nsets;
char *content[];
} complex;
complex *assign(Set *s, size_t nsets)
{
complex *cml = malloc(sizeof(*cml) + nsets * sizeof(cml -> content[0]));
/* allocation check */
cml -> nsets = nsets;
for(size_t i = 0; i < nsets; i++)
{
cml -> content[i] = s[i].id;
}
return cml;
}
You'll have to make the content array be an array of char* and when you create the structure only accept id from a Set struct.
Something like this:
complex* createComplex(Set* sets) {
complex* comp = (complex*)malloc(sizeof(complex));
for (int i=0; i<10; i++) {
comp->content[i] = sets[i].id;
}
return comp;
}
And don't let any other function create the comp struct

C program - skipping user input

I created a program that uses arrays and array pointers to store a user's animal name, category of animal, and age. But when I run it, there is a segmentation fault after I type the name age and category. I was wondering if someone could guide me in how to fix it, I am very new to C programming.
This is the task I am supposed to complete:
Write a program that defines an animal data type, with an animal name, age, and category (cat, dog, etc.), as well as an animal array type that stores an array of animal pointers.  Your program will prompt the user to enter the data for as many animals as they wish.  It will initialize a dynamically allocated animal structure for each animal, and it will store each animal in an instance of the animal array structure.  Your program will then print all the animal information to the screen.  You will upload your C program as one file.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char *name;
char *category;
int age;
} AnimalType;
typedef struct {
AnimalType basicInfo;
AnimalType *arr[];
} AnimalArrayType;
void initAnimal(char *n, char *c, int a, AnimalArrayType *ar);
void printAnimal(const AnimalArrayType *stuPtr);
int main() {
AnimalArrayType *array;
int numAn;
char name[20];
char category[20];
int age;
printf("Please enter the number of animals you want to input: ");
scanf("%d", &numAn);
array = calloc(numAn, sizeof(AnimalArrayType));
for (int i=0; i<numAn; ++i) {
printf("Enter animal name: ");
scanf("%s", name);
printf("Enter their category: ");
scanf("%s", category);
printf("Enter age: ");
scanf("%d", &age);
initAnimal(name, category, age, array + I);
}
printf("\n LIST:\n");
for (int i=0; i<numAn; ++i) {
printAnimal(array + I);
}
return 0;
}
void initAnimal(char *n, char *c, int a, AnimalArrayType *ar)
{
strcpy(ar->basicInfo.name, n);
strcpy(ar->basicInfo.category, c);
ar->basicInfo.age = a;
}
void printAnimal(const AnimalArrayType *stuPtr)
{
printf("Animal: %s, Category: %s age %d\n",
stuPtr->basicInfo.name, stuPtr->basicInfo.category,
stuPtr->basicInfo.age);
}
The char *name and char *category fields in the AnimalType struct are being initialized to NULL (from the call to calloc()), but you don't allocate any char[] memory for them to point at afterwards, so you end up crashing in initAnimal() when it tries to copy data into those fields using strcpy().
You need to either:
change those fields into char[] arrays instead of char* pointers:
typedef struct {
char name[20];
char category[20];
int age;
} AnimalType;
allocate memory for them to point at, such as from strdup():
typedef struct {
char *name;
char *category;
int age;
} AnimalType;
...
void initAnimal(char *n, char *c, int a, AnimalArrayType *ar)
{
ar->basicInfo.name = strdup(n);
ar->basicInfo.category = strdup(c);
ar->basicInfo.age = a;
}
Don't forget to free() anything you dynamically allocate when you are done using it.

initialise constructor values of structure using pointer in c [duplicate]

This question already has answers here:
How do malloc() and free() work?
(13 answers)
Closed 3 years ago.
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
struct Person {
char name[50];
int year_of_birth;
char sex[7];
char father[50];
char mother[50];
char significant_other[50];
char children[50];
};
struct Person* person_constructor(char *name, int year_of_birth, char *sex);
int main(){
struct Person* p1 = person_constructor("Abbas", 1970, "male");
}
struct Person* person_constructor(char *name, int year_of_birth, char *sex) {
struct Person *p;
printf("%s",*name);
printf("%s",*sex);
printf("%d",&year_of_birth);
// how to initalise these here and return name, age and sex everytime , can you tell me in print function
}
i want to do :
Person* person_constructor(char *name, int year_of_birth, char *sex);
A person with the given arguments and return it.
Also allocate memory.
In example code bellow you can find one of possible solutions to your question.
In C language is not possible to return more then one variable, but you can return pointer to constructed structure object and access structure members using notation stuct_ptr->struct_member.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
struct Person {
char name[50];
int year_of_birth;
char sex[7];
char father[50];
char mother[50];
char significant_other[50];
char children[50];
};
struct Person* person_constructor(char *name, int year_of_birth, char *sex);
int main(){
struct Person* p1 = person_constructor("Abbas", 1970, "male");
/* it is not possible to return more variables in C */
/* you can use pointer to access members from constructed structure: */
printf("print from main:\n %s %d %s \n", p1->name, p1->year_of_birth, p1->sex);
if( p1 != NULL) free(p1); /* do not forget do deallocate something taht is allocated */
return 0;
}
struct Person* person_constructor(char *name, int year_of_birth, char *sex) {
struct Person *p = calloc(1, sizeof(struct Person));
if( p == NULL ) return p; /* memory alocation failed! */
strcpy(p->name, name);
p->year_of_birth = year_of_birth;
strcpy(p->sex, sex);
printf("print from constructor:\n");
printf("%s ",p->name);
printf("%s ",p->sex);
printf("%d \n",p->year_of_birth);
return p;
}

passing a struct to a function and loop through it

Trying to pass a struct to a function and browse through it. Is this the correct way to pass a struct to a function? The for loop in the function view() doesn't seem to work. Any help with that too would be appreciated.
My structs:
typedef struct {
char name[20];
employee *list_employees;
int empl_count;
} agency;
typedef struct {
char name[30];
int age;
} employee;
Important pars of the code:
int main()
{
//...
int nmbr_agencies;
agency *list_agencies = malloc(sizeof(agency) * nmbr_agencies);
view(&list_agencies, &nmbr_agencies);
}
void view(agence *ListA[], int *nmbr)
{
int i=0;
for (i = 0; i < *nmbr; i++){
printf("name of agency: %s\n", ListeA[i]->name);
printf("number of employees\n, ListeA[i]->empl_count);
}
}
No.
You should just pass a single array if that is what you have, not pretend (in the call) that you have an array of pointers which you don't have.
Make the function:
void view(const agency *list, size_t number);
and call it like so:
view(list_agencies, nmbr_agencies);
Then inside the function, do direct accesses:
printf("name of agency: %s\n", list[i].name);
since you don't have an array of pointers.

How to allocate memory with different type in C?

I have the following code in C:
typedef struct
{
int age;
int phoneNumber;
} Student;
typedef struct
{
int id;
int student[1];
} People;
#define NUM_OF_PEOPLE
void *p = malloc(sizeof(People) + sizeof(int) * NUM_OF_PEOPLE + sizeof(Student) * NUM_OF_PEOPLE);
How could I find the pointer to the memory point to the first element of struct Student in the memory?
I try to do it in the following way:
int i = 0;
for(i = 0; i < NUM_OF_PEOPLE; i++)
{
Student * student_p = p.student[NUM_OF_PEOPLE];
}
It does not work, so can we allocate memory in the way?
And how to find the first element of struct Student in the memory?
What you have is an ancient way of having a flexible array member, which was technically also undefined behavior.
You are looking for this.
First, you need to define your struct like this (I don't know what the ints before the Students are, so let's just call it id):
typedef struct
{
int age;
int phoneNumber;
} Student;
typedef struct
{
int id;
Student student;
} StudentAndId;
typedef struct
{
int id;
StudentAndId students[];
} People;
Note the lack of size in the array inside People. Now you do this:
People *p = malloc(sizeof(People) + sizeof(StudentAndId[NUM_OF_PEOPLE]));
Then you can access students inside p as if it was an array of NUM_OF_PEOPLE elements.
Remember to compile with C99 (or C11) support. With gcc that would be -std=c99 or -std=gnu99.
This will allocate memory for storing the date but how you access it depends on how you store date. using C pointers you can store and access data using this structure and allocation but accessing the members will not be direct. it will involve pointer arithmetic. So better to use other structure if possible. If using this way of allocation then you need to do pointer arithmetic to get the next elements.
Try this:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int age;
int phoneNumber;
} Student;
typedef struct
{
int id;
int student[1];
} People;
#define NUM_OF_PEOPLE 10
int main()
{
People *p = malloc(sizeof(People) + sizeof(int) * NUM_OF_PEOPLE + sizeof(Student) * NUM_OF_PEOPLE);
int* id = (int*)(p+1);
Student* s = (Student*)(id+NUM_OF_PEOPLE);
printf("Size of People : %d\n", sizeof(People));
printf("p points to : %p\n", p);
printf("id points to : %p\n", id);
printf("s points to : %p\n", s);
}
Here's a sample output:
Size of People : 8
p points to : 0x80010460
id points to : 0x80010468
s points to : 0x80010490
You may want to add the id field to your Student data structure, e.g.:
typedef struct {
int id;
int age;
int phoneNumber;
} Student;
Then, you can define a structure having a fixed header (in this case, this can be the number of students), followed by a variable-sized array of Students:
#define ARRAY_OF_ANY_SIZE 1
typedef struct {
int count;
Student students[ARRAY_OF_ANY_SIZE];
} People;
This blog post explains this technique of having "arrays of size 1", including a discussion of the alignment problem.
I won't repeat the original blog post code here. Just consider that you can use the portable offsetof() instead of the Windows-specific FIELD_OFFSET() macro.
As a sample code, you may want to consider the following:
#include <stdio.h> /* For printf() */
#include <stddef.h> /* For offsetof() */
#include <stdlib.h> /* For dynamic memory allocation */
typedef struct {
int id;
int age;
int phoneNumber;
} Student;
#define ARRAY_OF_ANY_SIZE 1
typedef struct {
int count;
Student students[ARRAY_OF_ANY_SIZE];
} People;
int main(int argc, char* argv[]) {
People* people;
const int numberOfStudents = 3;
int i;
/* Dynamically allocate memory to store the data structure */
people = malloc(offsetof(People, students[numberOfStudents]));
/* Check memory allocation ... */
/* Fill the data structure */
people->count = numberOfStudents;
for (i = 0; i < numberOfStudents; i++) {
people->students[i].id = i;
people->students[i].age = (i+1)*10;
people->students[i].phoneNumber = 11000 + i;
}
/* Print the data structure content */
for (i = 0; i < people->count; i++) {
printf("id: %d, age=%d, phone=%d\n",
people->students[i].id,
people->students[i].age,
people->students[i].phoneNumber);
}
/* Release the memory allocated by the data structure */
free(people);
return 0;
}
Output:
id: 0, age=10, phone=11000
id: 1, age=20, phone=11001
id: 2, age=30, phone=11002

Resources