Pointers in array of Structures in C [duplicate] - c

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 5 years ago.
What i intend to achieve with this code is to take a string character from main function, and then assign it to name in structure at a specific index.
Example: It should print for me Name=> Charles Key=> 0
Next line will be Name=> George Key=> 1...and so on. But it rather picks the last name entered and use it for all though my structure is an array of structure. I don't also want to take it direct in the main...like scanf("%s", &node[i].name) because in the real project i am building, i will calculate for i based on the what the user enters. Please help me out. Thanks
#include<stdio.h>
#include<stdlib.h>
typedef struct{
int key;
char *name;
}test;
int main(){
test node[5];
int i;
char see[10];
//for loop for taking string character in see and then assigning name in structure to it
for(i=0; i<5; i++){
printf("Enter name\t");
scanf("%s", &see);
//assigns name in structure index i to see
node[i].name=see;
node[i].key=i;
}
//prints data stored in structure
for(i=0; i<5; i++){
printf("Name=> %s\t\tKey=> %d",node[i].name, node[i].key);
}
return 0;
}

Change as per following...
char *name; ----> char name[10];
scanf("%s", &see); ----> scanf("%s", see);
node[i].name=see; ----> strcpy(node[i].name, see);

You need to malloc space inside the struct and copy the text rather than assigning it. When you assign the pointer you are effectively making the struct's pointer point to the same memory so the next time you read into that memory you overwrite the old value.
Try replacing:
node[i].name = see;
with:
node[i].name = malloc(strlen(see) + 1);
if (node[i].name == NULL)
{
// Handle Malloc error
}
strncpy(node[i].name, see, strlen(see) + 1);

Related

How to allocate memory using struct and pointers [duplicate]

This question already has answers here:
dynamic memory allocation and dynamic array
(2 answers)
Closed 1 year ago.
I have a struct called TCarro with this properties.
typedef struct {
char nome[20];
char placaDoCarro[5];
} TCarro;
And I would like to know how I could allocate this variable struct TCarro *carro; dynamically.
For example, when I use scanf to read the number of cars, how should I allocate some memory so that I could do carro[0]->..., carro[1]->..., ...
To dynamically allocate memory for a struct, the following can be used:
TCarro *carVariable=malloc(sizeof(TCarro)*someNumbers);
, where someNumbers are the number of elements you want to allocate.
From the error you posted in the comment, I assume you tried doing something like:
printf("%d",carVariable);
As you have specified the integer specifier in printf (%d), the compiler expects the function to receive an integer, but you give it a struct TCarro instead.
So now you may be wondering, what specifier can I use to print my carVariable?
C, actually, does not offer such specifier, because structs are types created by the programmer, so it has no idea of how to print it.
What you could do, if you wanted to print your variable would be to print each individual elements of the array.
Something like this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct{
char nome[20];
char placaDoCarro[5];
}TCarro;
int main(void){
size_t someNumbers=10; //if you want to allocate 10 cars
TCarro *carVariable=malloc(sizeof(TCarro)*someNumbers);
//notice that struct before TCarro is not needed, as you defined it as an existing type (named TCarro)
strcpy(carVariable[0].nome,"Mercedes");
strcpy(carVariable[0].placaDoCarro,"xxxx");
strcpy(carVariable[1].nome,"Ford");
strcpy(carVariable[1].placaDoCarro,"xxxx");
//printf cars
printf("%s %s\n",carVariable[0].nome, carVariable[0].placaDoCarro);
printf("%s %s\n",carVariable[1].nome, carVariable[1].placaDoCarro);
free(carVariable);
return 0;
}
Notice that I used strcpy, because I needed to copy a string to each field of the struct.

access to a member of a struct (pointer) with the use of double pointer

hey I am trying to create a program in which I am trying store elements from one array to another with the use of a pointer to pointer but the problem is that is caused undefined behavior I believe that the problem is that I do not pass the elements in members with a proper way
I know it is a vague way of doing this but It is in only for practising reasons
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct student{
char *name;
int *number;
}T;
int main(void) {
char array[10][100]={"araaaa","bbgt","gffkghgh"};
T arr[10][100];
T *p;
T **p1;
p=&arr[0][0];
p1=&p;
int i=0;
for(i = 0 ; i < 3 ; i++)
{ p=arr[i];
strcpy((*p1)->name,array[i]);
}
/*******print_elements*************/
for(i = 0 ; i < 3 ; i++)
{ p=arr[i];
printf("\n the elements are %s",(*p1)-> name);
}
return 0;
}
When you do this:
strcpy ((*p1)->name, array[i]);
(*p1)->name is an uninitialised pointer. What happens, therefore, is in the lap of the gods.
The easiest fix is to modify your student structure such that name is a buffer, rather than a pointer. At the same time, change number to an int, rather than a pointer to an int::
typedef struct student{
char name [100];
int number;
} T;
If you want to keep name as a pointer then you have to allocate some memory before you store your string in it. This should work:
(*p1)->name = strdup (array[i]);
Don't forget to free the memory when done.
T is made of of two pointers, this first one points to a string of characters in memory.
arr is a 2D array that is allocated to store a total of 1000 T structures.
arr[i] would reference a 1D array of T structures within arr
*p1 would essentially be arr[i], since dereferencing p1 gives you p, which was just set to arr[i]. So, that is not a pointer to a T structure, but to an array of T structures. Forcing the cast will likely give you a reference to the first T structure in that row, however.
->name This value is never set. You allocated an array, but "name" is a pointer to memory, not an array of characters, so '->name' is undefined.
I think you need to change arr to be a single dimension array. You aren't using 90% of it.
And, you need to initialize every T struct in that array. You can use malloc or strdup, and then remember to free them all. Or, set the struct to use an array instead.

How to access struct members using pointers [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 3 years ago.
I created a structure in a header file to store student information. I initialize these member variable in a function called createStudent(). The createStudent() function returns a pointer to a newly initialized student. Now, when I test that this all works I get some unexpected results.
The code compiles and runs, however, only the first access of the students information returns useful values. In the code below I print out the students age first and I get the correct age, but the gpa and num values are garbage values. However, if I comment out the print statement for the students age, the gpa value is correct and the num value is still garbage. It seems that only the first access returns goof values. Now I'm fairly certain this is an issue to do with my pointers and memory allocation, I just don't know what the problem is.
I initially thought that memory was being freed up after the first access (I don't know why this would happen but that what seemed to be happening). So I tried to use malloc in order to make sure there was memory available at all times storing the students info, but the results did not change.
I have also tried re-assigning age in the createStudent() function after gpa and num were assigned, but age still gets the corrected value and gpa and num have garbage values.
If you guys need any more information concerning this please let me know.
Header File:
typedef struct Students{
int num; //holds the students number
char name[256]; //holds the students name
int age; //holds the students age
int gpa; //holds the students grade point average
}Student;
Student * createStudent();
Implementation file:
Student * createStudent(){
Student newStud;
Student *studPtr;
newStud.age = 10;
newStud.gpa = 5;
newStud.num = 307234;
studPtr = &newStud;
return studPtr;
}
Main File:
int main(int argc, char *argv[]){
int retCode = 0;
Student *stdPtr = createStudent();
printf("The students age is: %d\n", stdPtr->age);
printf("The students gpa is: %d\n", stdPtr->gpa);
printf("The students number is: %d\n", stdPtr->num);
return retCode;
}
As mentioned in the comments, the allocated memory for Student newStud only lives as long as your function is executed. as soon as it returns, the memory is freed again.
If you want to return the address of a created structure, you have to allocate the memory by yourself:
Student * createStudent(){
Student *studPtr = malloc(sizeof(Student));
studPtr->age = 10;
studPtr->gpa = 5;
studPtr->num = 307234;
return studPtr;
}
Do not forget to free the allocated memory and check the return value of malloc

Structures used to store postal codes

It asks me to create a hash function that turns the postal code into an integer by summing its characters. This is my code. I haven't got to the hash function yet.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct PostalCode
{
int size;
char *array[6];
} PostalCode;
int main()
{
int size = 6, i;
PostalCode *h = malloc(sizeof(PostalCode));
h->size = size;
h->array = malloc(sizeof(char)*size);
printf("Please enter your postal code: \n");
for (i=0; i<6; i++)
scanf(" %c", &(h->array[i]));
}
And the errors I get now are: postalcode.c:9:11: error: assignment to expression with array type
h->array = malloc(sizeof(char)*size);
The line
char *array[6]
declares an array of 6 pointers to char, and that's not what you want here. You can just make it
char * array
and resolve the error that way, or follow chux's advice, i.e. have
char array[6]
in which case you don't need the line that's causing the error, just remove it. No need to dynamically allocate the array.
A few other suggestions:
If your postal code is always 6 characters, then you don't really
need the PostalCode structure, unless you plan on keeping some other
information about the postal code there. You could just do
typedef char PostalCode[6];
Of course, if you expect postal codes to have
variable length, then size might help.
Regardless of whether you want a struct or typedef a char array, hard-coding the value 6 is a bad idea. If it's always 6 characters, then you can #define it; or if you keep the size in the structure, then make sure you initialize it and use the struct member instead of the literal number 6.
There is no need to dynamically allocate memory here, but if you do make sure you free it.
Good luck!

Using variables from a struct within an array of structs in C

So the primary objective here is to take input from the user and store it in an array where each element in the array is a struct srecord. I would like to be able to retrieve the strings fname and lname as well as the score. This is crucial because I am going to also design other methods that will calculate the average of all students in the array and tell which students have the highest or lowest score.
For example in fill_in_srecord_array, if I wanted to print out the information in a[i] after running fill_in_srecord, would this be the proper line?
printf("%s %s: Score= %d\n", a[i].fname, a[i].lname, a[i].score);
But this does not compile, so what is wrong here?
Is my fill_in_srecord method working properly and actually filling in the array properly?
For future reference, what is the best way to access variables from a struct being stored in an array?
#include <stdio.h>
#include <string.h>
struct srecord {
char fname[20]; /* first name */
char lname[20]; /* last name */
int score;
};
void fill_in_srecord(struct srecord *r){
struct srecord new_student; //declare a new student record
r = &new_student; //assign a value to the pointer
printf("Enter student first name: "); //request input
scanf("%s", r->fname);
printf("First: %s",r->fname);
printf("\nEnter student last name: ");
scanf("%s", r->lname);
printf("Last: %s",r->lname);
printf("\nEnter student score: ");
scanf("%d", &(r->score));
printf("Score: %d\n", r->score);
}
void fill_in_srecord_array(struct srecord a[], int len){
a[len];
//struct srecord *p; //srecord pointer
for(int i = 0; i<len; i++) {
fill_in_srecord(&a[i]);
}
}
int main(){
struct srecord students[2];
fill_in_srecord_array(students, 2);
exit (0);
}
The problem here is that in the fill_in_srecord function you do
struct srecord new_student;
r = &new_student;
This is problematic for three reasons:
First is that new_student is a local variable, and it will go out of scope and disappear once the function returns. Any pointers to it will be stray pointers and using them will lead to undefined behavior.
The second problem actually makes the first problem moot, because when you pass a value to a function in C the values are copied and the function only gets a copy. Modifying a copy (like e.g. r = &new_student) will of course not modify the original.
The third problem is that when the function is called, you pass a pointer to a valid and existing instance of the srecord structure. There's simply no need for the new_student variable or the reassignment of r inside the function. Modifying r directly will be enough.
So the solution is simply to not have the two problematic lines.
There's another thing as well, the statement a[len]; that you have in the fill_in_srecord_array function it doesn't really do anything. But if it did anything it would lead to undefined behavior because you would index the array a out of bounds.
Right now you were making changes to local variable , which is not accessible out of function block and changes made to it are not done on the variable in calling function itself .
When you pass address of a[i] to function ,and if you make changes to that in function ,a[i] will be modified in the calling function itself . Because the changes will be made directly to content at its address , that is to itself .
What you need to do is write your function like this -
void fill_in_srecord(struct srecord *r){
/* struct srecord new_student; //declare a new student record */
/* r = &new_student; //assign a value to the pointer */
printf("Enter student first name: "); //request input
scanf("%s", r->fname);
printf("First: %s",r->fname);
printf("\nEnter student last name: ");
scanf("%s", r->lname);
printf("Last: %s",r->lname);
printf("\nEnter student score: ");
scanf("%d", &(r->score));
printf("Score: %d\n", r->score);
}

Resources