where is the error?, It should print out the age entered by the user to the student 0 of struct
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Students
{
int age;
int id;
char name[30];
int grade;
};
void main(void)
{
struct Students *student[10]; // Array of Pointers to Structs.
// Containing (10) Pointers (student) to Structs. To save memory unlike the normal array
printf("Enter your Age: ");
scanf("%d", &student[0]->age);
printf("Age equals: %d", student[0]->age);
}
You have an array of ten pointers to Students structs, but each of those pointers has not been initialized.
As a result, undefined behavior is invoked when you dereference any of those pointers.
You should either dynamically allocate memory for each pointer to point to, or change your array to:
struct Students student[10];
This automatically allocates space on the stack for ten Students structs. At that point you can read an age with:
scanf("%d", &student[i].age);
As a sidenote, I think your pluralization is backwards. If your struct Students only hold info on a single student, then Student would be a better name, and students would be an apt name for an array of those structs.
You should also check the return value of scanf. If a single integer has been successfully read, scanf will return 1. Do not assume your user will enter valid information. Checking the return value of scanf gives you the option of handling that scenario before it can create further runtime bugs.
Related
I came across something I don't understand why and I'd like to hear an explanation about it.
I have this struct:
typedef struct Student {
int age;
char *name;
} Student;
int main()
{
Student **test1 = calloc(2, sizeof(*test1));
Student **test2 = calloc(2, sizeof(**test2));
return 0;
}
I've noticed that test1 gets 2 memory allocations (as it should) while test2 gets 4. Why is that and which is the correct usage? I assume its the first one but i'm not sure why.
Thanks!
sizeof(*test1) is the size of a pointer Student*, while sizeof(**test) is the size of a structure Student.The structure has a pointer, so its size should be larger than the size of a pointer.
Student **test1 = calloc(2, sizeof(*test1));
Is the typical usage. This is allocating 2-element array of Student* and assigning the pointer to its first element to test1.
Two things here:
You're allocating two different amounts of memory here. In the first case, you allocate space for 2 objects of type Student *, while in the second case you allocate space for 2 objects of type Student. The latter is likely larger than the former, so you'll be able to put more object of type Student * there.
You don't show how you're verifying how much memory you've gotten, but it's undefined behavior to read or write past the bounds of allocated memory. Your program might crash, or it might not.
sizeof(*test) is a size in bytes of the pointer to Student. It will be on most systems 4 or 8.
sizeof(**test)gives you the size of the Student. The allocation (test2) makes no sense at all.
You can easily test it yourself by printing the sizes:
#include <stdio.h>
#include <malloc.h>
typedef struct Student {
int age;
char *name;
double somedata[100];
} Student;
int main()
{
Student **test1;
Student **test2;
printf("%zu\n", sizeof(*test1));
printf("%zu\n", sizeof(**test2));
return 0;
}
https://godbolt.org/z/W6e8YzKKf
I am building a contact management application that requires info about the user and the user's spouse. I started with a struct where I initialized a name and a pointer to the spouse.
I have tried saving the input information to the pointer but I get the following error
GestionCarnet.c: In function ‘main’:
GestionCarnet.c:19:37: error: dereferencing pointer to incomplete type ‘struct Contact’
scanf("%s", (contact_00->Spouse)->Name);
And this is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char Name[20];
struct Contact *Spouse;
} Contact;
int main()
{
Contact *contact_00;
contact_00 = (Contact *)malloc(sizeof(Contact));
printf("Add a contact: \n");
printf("Name: \n");
scanf("%s", (contact_00)->Name);
printf("Spouse Name: \n");
scanf("%s", (contact_00->Spouse)->Name);
printf("================\n");
free(contact_00);
return 0;
}
Is it possible to save info to a struct's pointer ? If , then how do I do it in my code? Thank you.
This error can be avoided by typing the struct name after typedef struct. So the struct definition becomes:
typedef struct Contact
{
char Name[20];
struct Contact *Spouse;
} Contact;
If you want to use struct Contact *Spouse; inside the struct then you will have to tell the compiler that it is going to be defined later, otherwise you will get an error.
The Spouse is a pointer here. It means that you will need to allocate memory for it whenever you want to use it. The following is the complete program that works fine after allocating memory for Spouse too:
#include <stdio.h>
#include <stdlib.h>
typedef struct Contact
{
char Name[20];
struct Contact *Spouse;
} Contact;
int main()
{
Contact *contact_00;
// Allocate both pointers
contact_00 = (Contact *)malloc(sizeof(Contact));
contact_00->Spouse = (Contact *)malloc(sizeof(Contact));
printf("Add a contact: \n");
printf("Name: \n");
scanf("%s", (contact_00)->Name);
printf("Spouse Name: \n");
scanf("%s", (contact_00->Spouse)->Name);
printf("================\n");
// Testing:
printf("Name: %s\n", (contact_00)->Name);
printf("Spouse: %s\n", (contact_00->Spouse)->Name);
// Free both pointers
free(contact_00->Spouse);
free(contact_00);
return 0;
}
The reason for that error is that you are using the new type that you are defining when it was still undefined, a new type is defined after it was given a name.
Is it possible to save info to a struct's pointer?
Yes it is, when you allocate memory for a struct you are allocating memory to all of its fields on the heap, if one of those fields is a pointer, you are allocating memory to a variable that holds a memory address. But you still haven't allocated memory for that address.
Also, don't forget that when you are freeing such struct you need to first of all free all the memory that its fields might point to, and then free the struct itself.
If , then how do I do it in my code?
First of all we need to fix the struct and then allocate memory for the pointer, notice that I defined Contact as a pointer to a struct contact_t:
typedef struct contact_t{
char Name[20];
struct contact_t *Spouse;
} *Contact;
using the struct:
Contact contact_00 = malloc(sizeof(*contact_00));
//check malloc result
contact_00->Spouse = malloc(sizeof(*contact_00->Spouse));
//check malloc result
//your code
free(contact_00->Spouse);
free(contact_00);
Note that casting void* (malloc return value) to other pointers is pointless.
#include <string.h>
#include <stdio.h>
struct student{
char last[25] ;
char first[25];
};
struct seating {
struct student **seat;
};
//Set the first and last name to default values
void student_init_default(struct student *s ) {
strcpy(s->last_name,"***");
strcpy(s->first_name,"***");
}
void seating(int rowNum, int columnNum, struct seating *a ){
//Instantiate a 2D array specfied by the parameters
struct student students[rowNum][columnNum];
a->seat = students;
//Initialize each element to the default
for(int rows = 0; rows < rowNum; rows++){
for(int columns = 0; columns < columnNum; columns++){
student_init_default(&students[rows][columns]);
}
}
}
void main() {
struct seating room;
struct student student;
int row, col, rowNum, columnNum;
char student_info[30];
// Ask a user to enter a number of rows for an classroom seating
printf ("Please enter a number of rows for an classroom seating.");
scanf ("%d", &rowNum);
// Ask a user to enter a number of columns for an classroom seating
printf ("Please enter a number of columns for an classroom seating.");
scanf ("%d", &columnNum);
// seating
seating(rowNum, columnNum, &room);
}
To start off, I am a beginner at C. My problem is using pointers. The main point in this code is to make a 2D array of the struct student and then fill in the array by setting the default as first and last name. What Im asking for is if someone can give a easy explanation or hints on how to connect the parameter, struct classroom_seating *a, with struct student **seating, along with the 2D array. Along with that, how would I use struct classroom_seating *a to access the 2D array? I do know the basics of pointers but I've been researching for hours and haven't found a connection to work.
I do know that this line printf("%s", listOfStudents[0][2].firstName); prints *** (assuming the user entered 3,3 for row/columns). It's that I don't know how I would be able to access that in later methods.
a->seat = students;
The compiler is explicit about the error
error: cannot convert 'student [rowNum][columnNum]' to 'student**' in assignment
a->seat = students;
^
is wrong because here you are assigning a 2d array to a double pointer. 2d array decayed into struct student (*)[] and then you tried to assign it to struct student **.
Instead you should create the jagged array yourself and work with it.
a->seat = malloc(sizeof(struct student*)* rowNum);
if(!a->seat){
perror("malloc");
exit(EXIT_FAILURE);
}
for(int i = 0; i< rowNum; i++){
a->seat[i] = malloc(sizeof(struct student)* columnNum);
if(!a->seat[i]){
perror("malloc");
exit(EXIT_FAILURE);
}
}
After that you can pass the address of each struct student instance like you did and make changes to it.
To clarify further about the organization that you are likely to follow
struct seating room; Here room is a structure instance containing a double pointer. That's it. That pointer points to no where significant. It contains indeterminate value (garbage value).
Now you want to allocate some memory and work with it. That is being done in the function seating. As it is just a pointer, you allocate memory of rowNum struct student * and why struct student*? Because that in turn will point to a series of struct student variable instance.
After successful allocation, now you have the memory and it is not of automatic storage duration - it will stay when the function seating ends also. It's storage duration extends beyond the scope of the function.
Notice one thing, strcpy(s->last_name,"***"); but there is no last_name variable in the structure definition. It would be last. Same goes with other member variable also.
After making the changes you would pass the instance of struct student like this:-
for(int rows = 0; rows < rowNum; rows++){
for(int columns = 0; columns < columnNum; columns++){
student_init_default(&a->seat[rows][columns]);
}
}
You are trying to assign to a->seat something that does not fit(not possible). But even if it would fit it would be wrong as struct student students[rowNum][columnNum]; is defined locally to the function seating(), so the moment the code returned from this function all memory a->seat pointed to would have become invalid. Accessing it would be undefined behavior then. (alk pointed this).
#include<stdio.h>
#include<string.h>
struct employee
{
int id;
char name[20];
float salary;
char addr[];
}*emp;
void get_emp(struct employee **record)
{
printf("\tplease enter details of employee:\n");
printf("id= ");
scanf("%d",(*record)->id);//code to get input value
printf("Name= ");
scanf(" %s",(*record)->name);
printf("salary= ");
scanf("%f",(*record)->salary);
}
int main()
{
get_emp(&emp);
printf("id=%d\n",emp->id); // code to display the value
printf("Name=%s\n",emp->name);
printf("salary=%f\n",emp->salary);
return 0;
}
I have a structure example and I want to pass structure pointer to the function without using normal variable but only pointer. Is the parameter(double pointer) in the function get_emp(struct employee **record) a correct way to do if not what changes should be made? Also how to get input value from users in the function get_emp(struct employee **record) and how to display the value?
A double pointer is not needed. You can accomplish this with single pointer as well. You would however need to allocate memory for the structure before populating it.
struct employee *emp = malloc(sizeof(struct employee));
Also the size of char addr[] in your structure is undefined. That needs to be allocated separately similar to:
emp->addr = malloc(N*sizeof(*emp->addr));
All other fields in the structure which has a fixed size such as integer,float and a character array of 20 elements does not need allocation. The allocation for them would be done by malloc we did earlier. However since addr is a pointer, memory equivalent to size of pointer would be reserved for it. To store anything in the address the addr points to, we need to allocate.
Afterwards pass emp to your function. Remove the double pointer
So I am trying to make a simple program which opens up a text file, reads the number of students that the file contains, their first names, last names and student numbers, and stores values in variables, and then finally returns a pointer to an array of those student objects. My code is as follows: -
#include <stdio.h>
#include <stdlib.h>
struct student
{
double studentNumber;
char *firstName;
char *lastName;
};
struct student *readStudentRecordFile(char *fileName, int *numOfStudents)
{
int i;
struct student a;
FILE *fp;
fp=fopen(fileName,"r");
fscanf(fp,"%d",&numOfStudents);
for(i=0;i<*numOfStudents;i++)
{
fscanf(fp, "%s" "%s" "%f", a[i].firstName,a[i].lastName,&a[i].studentNumber);
}
fclose(fp);
}
int main(void)
{
int nStudents;
struct student *readArray;
readArray=readStudentRecordFile("hello.txt", &nStudents);
return 0;
}
The problem is that when I run the program, I get an error stating the sub scripted value is neither an array nor pointer. I am sort of new to this concept, so I am sort of don't understand what it means. If anyone can tell me what I am doing wrong, and how I can achieve the result that I want, I will be very great-full. Thank you.
In your program a is neither an array nor a pointer. It is of struct student type . You should declare a as an array of struct.
struct student a[SIZE];
a[i].firstName
This is array notation.
a.firstName
This is variable notation.
struct student a;
This is what you have. It's a variable.
struct student a[LEN];
This is what you need. It's an array.