Simple STRUCT program beginner QUESTIONS - c

So I just started learning struct type in C but I'm a bit confused. I have a pretty long program which I'm working on and I'm not sure to how to insert a name and age into the next unused element in the arrray using a static variable (e.g. called nextinsert) inside the function to remember where the next unused element is.
This is the my code for the insert function.
static void insert (struct person people[], char *name, int age)
{
static int nextfreeplace = 0;
static int nextinsert = 0;
/* put name and age into the next free place in the array parameter here */

For your question "how to insert a name and age", use:
strcpy(people[nextfreeplace],name);
people[nextfreeplace].age = age;
You may need to include string.h for strcpy.

Why not make it simpler: instead of trying to keep track of the index inside the insert function, you alreay have the index inside the main function. Thus:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* these arrays are just used to give the parameters to 'insert',
to create the 'people' array */
#define HOW_MANY 7
#define MAXSTRLEN 32
/* declare your struct for a person here */
struct person
{
char name [MAXSTRLEN];
int age;
};
static void insert (struct person *people, char *name, int age)
{
strncpy(people->name, name, MAXSTRLEN);
people->age = age;
}
int main(int argc, char **argv) {
// Move arrays here; if they are global instead,
// there would be need to pass name and age to insert()
char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim",
"Harriet"};
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};
/* declare the people array here */
struct person people[12];
int i;
for (i =0; i < HOW_MANY; i++)
{
insert (&people[i], names[i], ages[i]);
}
/* print the people array here*/
for (i =0; i < HOW_MANY; i++)
{
printf("%s\n", people[i].name);
printf("%d\n", people[i].age);
}
return 0;
}
The people->name syntax is a shorthand for (*people).name. That is, you dereference the pointer to get to the actual struct (*people), and then access the struct number; because of operator precedence rules you need the parenthesis around *people.
I'm not sure how familiar you are with pointers, but in C, this is very common (passing a pointer to a struct into a function, and then using structure->member inside that function.
Of course, if your whole "exercise" revolves around learning about static variables, this may be of little value. But what I have here is likely preferred to keeping a static variable inside the function for array indexing.

Related

Array of Pointer to Struct

I am a noob to C.I wrote a program that my array people is now an array of pointers to structs. And insert to call malloc to create a new struct and set the correct array element pointing to it.
HERE IS my code.
#include <stdio.h>
/* these arrays are just used to give the parameters to 'insert',
to create the 'people' array
*/
#define HOW_MANY 7 char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim","Harriet"};
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};
/* declare your struct for a person here */
typedef struct{
char* name;
int age;
} person;
static void insert( person *people[], char *name, int age,int i) {
/* put name and age into the next free place in the array parameter
here */
people[i] = malloc(sizeof(person));
people[i]->name = name;
people[i]->age = age;
/* modify nextfreeplace here */
}
int main(int argc, char **argv) {
/* declare the people array here */
person *people[7];
for (int index=0;index < HOW_MANY;index=index+1) {
insert (&people[index], names[index], ages[index],index);
}
/* print the people array here*/
for(int index=0;index < HOW_MANY;index=index+1) {
printf("name: %s, age: %i\n",
people[index]->name, people[index]->age);
}
return 0;
}
And I get errors
part2.c:23:5: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
people[i] = malloc(sizeof(person));
^ part2.c:23:17: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
people[i] = malloc(sizeof(person));
Can anyone help me? appreciate
I have observed a few issues which are causing these problems. Check the code which I have given below.
There in the comments, I have mentioned where to make changes.
You are using the malloc function without including the stdlib file!
See this code, I have tested it in dev-cpp and it's now working.
#include <stdio.h>
#include <stdlib.h>
/* these arrays are just used to give the parameters to 'insert',
to create the 'people' array
*/
#define HOW_MANY 7
char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim","Harriet"};
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};
/* declare your struct for a person here */
typedef struct{
char* name;
int age;
} person;
/* declare the people array here */
person *people[7];
person* insert(char *name, int age,int i) {
/* put name and age into the next free place in the array parameter
here */
people[i] = malloc(sizeof(person));
people[i]->name = name;
people[i]->age = age;
/* modify nextfreeplace here */
}
int main(int argc, char **argv) {
int index;
for (index=0;index < HOW_MANY;index=index+1) {
insert(names[index], ages[index],index);
}
/* print the people array here*/
for(index=0;index < HOW_MANY;index=index+1) {
printf("name: %s, age: %i\n",
people[index]->name, people[index]->age);
}
return 0;
}
Please see my answer below and compare with your code where you need modification and also try to understand what my code is doing. If you are not clear with any part of my code please feel free to ask me question.
char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim","Harriet"};
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};
/* declare your struct for a person here */
typedef struct{
char* name;
int age;
} person;
static void insert( person *people[], char *name, int age,int i) {
/* put name and age into the next free place in the array parameter
here */
people[i] = malloc(sizeof(person));
people[i]->name = name;
people[i]->age = age;
/* modify nextfreeplace here */
}
int main(int argc, char **argv) {
/* declare the people array here */
person *people[7];
for (int index=0;index < HOW_MANY;index=index+1) {
insert(people, *(names+index), ages[index],index);
}
/* print the people array here*/
for(int index=0;index < HOW_MANY;index=index+1) {
printf("name: %s, age: %i\n",
people[index]->name, people[index]->age);
}
return 0;
}

How to return an array of structure by reference?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct data{
char name[20];
char lastname[25];
int age;
}person;
void insert(person *p,int *num);
int main()
{
int num;
person p;
insert(&p,&num);
printf("Name: %s",p[0].nome); /* Here i would print the first struct by
my array, but: is not array or not pointer Why?? */
}
void insert(person *p, int *num)
{
int dim;
person *arr;
printf("Insert how many people do you want? "); /* How many index the
array should have */
scanf("%d",&dim);
arr = (person *) malloc(dim*sizeof(person)); /* I'm not sure for
this explicit cast. */
for(int i = 0; i < dim; i++)
{
printf("Insert name: ");
scanf("%s",arr[i].name);
printf("Insert lastname: ");
scanf("%s",arr[i].lastname);
printf("Insert age:': ");
scanf("%d",&arr[i].age);
}
*num = dim;
*p = *arr;
}
I've tried: `person *insert(int *num)
And it's works,but how can pass an array reference?`
This programm should ask how many person do you want to insert ( in function insert) and with a for, he should ask name,surname,age.
After the insert, he should print, but for quick, i would tried with first element (index) of array (structs).
You can't return entire array from the function, but you can return the base location of the array. For example you can do like this : person *insert(int *sz);. But i see in your code you're passing &p and the &num variable into the insert method, maybe you want to modify them within that function and manipulate it afterwards in your main(). For that i would have these recommendations:
Change Line 16 person p to person *p. Since p is supposed to hold base value of an array. Remember array name is nothing but a base address to the first element of the list.
Change your function definition to recieve person** rather than person*. Since you want to modify a pointer variable and therefore you'd need a pointer to a pointer variable. Change it like this:` void insert(person **p, int *num)
Free the memory after usage; add a free(p) at the end of main.
`

C program: need help using pointers

The purpose of this program is to assign the names to their corresponding ages using pointers.
#include <stdio.h>
#include <stdlib.h>
/* these arrays are just used to give the parameters to 'insert',
to create the 'people' array
*/
#define HOW_MANY 7
char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim",
"Harriet"};
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};
/* declare your struct for a person here */
typedef struct {
char *name;
int age;
} person;
static void insert(person *people[], char *name, int age, int *nextfreeplace)
{
/* creates memory for struct and points the array element to it. */
people[*nextfreeplace] = malloc(sizeof(person));
/* put name and age into the next free place in the array parameter here */
(*people[*nextfreeplace]).name = name;
(*people[*nextfreeplace]).age = age;
/* modify nextfreeplace here */
(*nextfreeplace)++;
}
int main(int argc, char **argv)
{
/* declare the people array here */
person *people[HOW_MANY];
int nextfreeplace = 0;
for (int i = 0; i < HOW_MANY; i++)
{
insert (&people, names[i], ages[i], &nextfreeplace);
}
/* print the people array here*/
for (int i = 0; i < HOW_MANY; i++) {
printf("Name: %s. Age: %d\n", (*people[i]).name, (*people[i]).age);
}
/* Releases the memory allocated by malloc */
for (int i = 0; i < HOW_MANY; i++) {
free(people[i]);
}
return 0;
}
It works perfectly, but when I compile it I get two warnings.
arrays.c: In function ‘main’:
arrays.c:41:13: warning: passing argument 1 of ‘insert’ from incompatible pointer type [-Wincompatible-pointer-types]
insert (&people, names[i], ages[i], &nextfreeplace);
^
arrays.c:19:13: note: expected ‘person ** {aka struct <anonymous> **}’ but argument is of type ‘person * (*)[7] {aka struct <anonymous> * (*)[7]}’
static void insert(person *people[], char *name, int age, int *nextfreeplace)
I'm new to pointers and C in general and would like some help explaining why I get these warnings and how to get rid of them. Thanks!
TL; DR
Use people instead of &people.
Long explanation
Here is what the warning messages say:
Your function insert expects a parameter of type person ** (a pointer to pointer to person). Your code sends it a parameter of different type: person * (*)[7], which is a C way for "a pointer to an array of 7 pointers to person".
(you can use the site http://cdecl.org to discover that: enter struct person * (*people)[7] in its field, and it will translate it to English)
If you send your array, and not a pointer to it, to your insert function, the compiler will regard the name people as a "pointer to pointer to person", which in this context is a special case of "array of pointers to person". This process is called "decay" of array to a pointer, and is explained here.
You can also do this:
/* declare your struct for a person here */
typedef struct {
char *name;
int age;
} person, *people_t;
And then
static void insert(people_t people[], char *name, int age, int *nextfreeplace){...}
Then
people_t people[HOW_MANY];
int nextfreeplace = 0;
for (i = 0; i < HOW_MANY; i++){
insert (people, names[i], ages[i], &nextfreeplace);
}
Compiler: Visual Studio 2010
This is actually a single warning, shown over two lines (the source of the warning at line 41, and the declaration causing the problem at line 19).
You can clear the warning by removing the ampersand from the call to insert, thus
insert(people, names[i], ages[i], &nextfreeplace);
In C, the name of an array is synonymous with its address.
Also, to clear up the <anonymous> tag in the warnings, a common idiom when typedefing structures is the following:
typedef struct <name>
{
...
} <name>;
which in your case would be:
typedef struct person {
char *name;
int age;
} person;
You get these warning because the "insert" expects pointer-to-pointer-to-person, but gets just a pointer-to-pointer-to-pointer-to-person.
In line 41, get rid of "&" from "&people", like in:
insert (people, names[i], ages[i], &nextfreeplace);

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.

help with pointers and structs and arrays in c

help needed printing array of pointers to structs
where am i going wrong ? please help
include <stdio.h>
include <stdlib.h>
define HOW_MANY 7
char *names[HOW_MANY]= {"Simon", "Suzie", "Alfred", "Chip", "John", "Tim",
"Harriet"};
int ages[HOW_MANY]= {22, 24, 106, 6, 18, 32, 24};
struct person
{
char *name;
int age;
};
static void insert (struct person *people[], char *name, int age) {
static int nextfreeplace = 0;
typedef struct person newperson;
newperson *structperson = (newperson*)malloc(sizeof(newperson));
(*structperson).name= name;
(*structperson).age = age;
printf("%s",(*structperson).name);
people[nextfreeplace] = &structperson;
printf("%s",(*people[nextfreeplace]).name);
nextfreeplace++;
}
int main(int argc, char **argv) {
struct person *people[HOW_MANY];
for (int c=0; c < HOW_MANY;c++) {
insert (people, names[c], ages[c]);
}
print the people array here
for (int i=0; i < HOW_MANY;i++) {
printf("%s \n",&(*people[i]).name);
}
return 0;
}
Where you malloc, you are declaring your structperson as a value instead of a pointer. Then you try to refer to it from then on as a pointer (ie dereferencing it with the asterisk).
Here is how I would write it. I make a number of changes, such as remove the static var (you should handle the array where your are assigning it, your function shouldn't be storing the state of the array, then no one else can ever use it).
Lots of style problems:
Don't cast the return value of malloc.
Instead of passing sizeof(newperson) to malloc, use sizeof *structperson.
Use the -> operator, i.e. structperson->name instead of (*structperson).name.
Clean up the (confusing a misleading) names you've used for your typedef and variables.
In place of HOW_MANY, you might use sizeof names/sizeof names[0].
i want to add the data to structs which are person and then make an array of pointers to the person and then print them out. currently i am getting output which is not readable e.g 11112012.

Resources