Using function to put values into struct in C - c

Assignment requires using a function to input data into a struct
typedef struct AC {
char code[4];
double cost;
unsigned day;
} AC;
My function so far is
int main(){
AC *ac;
input(&ac);
}
void input(AC * ac)
{
printf_s("Input code (3 characters), cost, and day (0 = Sun 6 = Sat) separated by spaces: \n");
gets(ac->code);
printf_s("\nCode: %s\n", ac->code);
scanf_s(" %lf", ac->cost);
printf_s("\nCost: %.2lf\n", ac->cost);
scanf_s(" %i", ac->day);
printf_s("\nDay: %i\n", ac->day);
}
The gets for the airport code works fine, but the scanf for cost and day don't seem to do anything; using breakpoints, it seems like the function isn't placing the values scanf gets into the struct. Instead, cost just remains garbage code after that part is done.
Don't worry about error checking or anything, I'm just interested in how to make the function properly take the input values and put them in the struct.

You've got undefined behavior all over. The problem is that there is no actual space for the AC struct you're populating. It's a simple change. Replace AC *ac; with AC ac;. That changes ac from a pointer to an actual struct with backing memory.

use & .
Like scanf_s(" %i", &ac->day);
A string is character array ( char * or char [] ) So it does not require &. But non-arrays require it.
Also you should declare AC ac; (as Michael Arbers pointed out first) then pass the address ( &ac) when calling the function call. That is because you are passing address and declared the function to take pointer to AC (AC *ac).
In C language, when you declare an address variable (pointer) you use * . When fetching the address you use & .

Related

Members of struct are being modified, but why? [duplicate]

This question already has answers here:
error: function returns address of local variable
(8 answers)
Closed 4 years ago.
I've been trying to write a program to solve a problem (ex. 19, Chapter 10 'C How to Program' 8th Ed, Deitel & Deitel), but I'm having a lot of trouble trying to identify the source of an issue I'm having.
I've been trying to pass some data to a function 'setData', which assigns the various values passed in to the members of a structure 'HealthProfile'. This seems to be happening successfully, and the function returns a pointer to a struct object to main. The pointer is then passed to function 'printStruct', and this is where the problem occurs. Each time the pointer is passed to the function, the function seems to be altering the values stored in each of the structure members, but I don't know why. I'm not trying to alter the member values, the point of passing the pointer to the structure to each function is so that the functions have access to the values contained in the members (my actual program has other functions, but I haven't included them because I'm still working on them, plus the issue I'm having is illustrated by function 'printStruct' alone.
Can anyone tell me where I've gone wrong?
I have tried a lot of different things, but nothing seems to work. I suspect that maybe the solution to the problem is that I should be passing a pointer to a pointer to the functions instead of a pointer, but I haven't had any luck in trying to fix the program this way. I also thought maybe I should be declaring the structure members as constant, but again no luck.
I've included a few printf statments in main to illustrate that the value of the pointer hasn't changed, but the value of the members of the structure have after the first call of function 'printStruct' (if printStruct is called a second time, a segmentation fault occurs).
#include <stdio.h>
typedef struct {
char *firstName;
char *lastName;
char *gender;
int birthDay, birthMonth, birthYear;
double height, weight;
} HealthProfile;
HealthProfile * setData(char first[20], char last[20], char gender[2],
int BirthDay, int BirthMonth, int BirthYear,
double Height, double Weight);
void printStruct(HealthProfile * variablePtr);
int main(void)
{
char FirstName[20], LastName[20], Gender[2];
int age, BirthDay, BirthMonth, BirthYear, maxRate = 0, targetRate = 0;
double bmi, Height, Weight;
HealthProfile *variablePtr;
puts("\n** Health Profile Creation Program **");
printf("\n%s\n\n%s", "Enter First Name", "> ");
scanf("%s", FirstName);
printf("\n%s\n\n%s", "Enter Last Name", "> ");
scanf("%s", LastName);
printf("\n%s\n\n%s", "Enter Gender (M/F)", "> ");
scanf("%s", Gender);
printf("\n%s\n\n%s", "Enter date of birth (dd/mm/yyyy)", "> ");
scanf("%d/%d/%d", &BirthDay, &BirthMonth, &BirthYear);
printf("\n%s\n\n%s", "Enter Height (m)", "> ");
scanf("%lf", &Height);
printf("\n%s\n\n%s", "Enter Weight (kg)", "> ");
scanf("%lf", &Weight);
variablePtr = setData(FirstName, LastName, Gender, BirthDay,
BirthMonth, BirthYear, Height, Weight);
printf("Address pointer: %p\n", variablePtr);
printf("Address pointer (deref): %p\n", variablePtr->firstName);
printf("Address pointer (deref): %p\n", variablePtr->lastName);
printStruct(variablePtr);
printf("Address pointer (deref): %p\n", variablePtr->firstName);
printf("Address pointer (deref): %p\n", variablePtr->lastName);
/* printStruct(variablePtr); */
}
HealthProfile * setData(char first[20], char last[20], char gender[2],
int BirthDay, int BirthMonth, int BirthYear,
double Height, double Weight)
{
HealthProfile profile, *profilePtr;
profilePtr = &profile;
profile.firstName = first;
profile.lastName = last;
profile.gender = gender;
profile.birthDay = BirthDay;
profile.birthMonth = BirthMonth;
profile.birthYear = BirthYear;
profile.height = Height;
profile.weight = Weight;
return profilePtr;
}
void printStruct(HealthProfile * variablePtr)
{
printf("\n%s%s\n%s%s\n%s%s\n%s%d/%d/%d\n%s%.2lfm\n%s%.1lfkg\n",
"First Name: ", variablePtr->firstName,
"Last Name: ", variablePtr->lastName,
"Gender: ", variablePtr->gender,
"DOB: ", variablePtr->birthDay, variablePtr->birthMonth,
variablePtr->birthYear,
"Height: ", variablePtr->height,
"Weight: ", variablePtr->weight);
}
Based on the way I've written the code, I was expecting the structure pointer passed to 'printStruct' not to be changed after the member values are printed. I would think I could call the function multiple times with no alteration to member values, but after just one call things are changed.
The Problem here is, that your pointer points to an address on the stack, which means, it's 'lifetime' or scope ends, when the Function setData returns. The next calls' stackframe overwirtes in part or whole the place in memory where your pointer points to. This leads to random and sometimes possibly correct output.
To solve this either allocate memory in the heap, instead of pointing to the address of a local variable ( malloc ) or declare a local variable im Main() and pass a pointer to setData.
Both solutions will prevent the issue you Are having.
Your problem is the time local variables are valid:
Both function arguments and local variables are only present in memory as long as the corresponding function is being executed. When the function has finished, the variables become invalid and may be overwritten with other data.
Now let's look at the following part of your code:
... setData( ... )
{
HealthProfile profile, *profilePtr;
profilePtr = &profile;
...
return profilePtr;
}
profilePtr contains a pointer to the local variable profile. As soon as the function setData has finished, this variable is no longer valid and may be overwritten.
The pointer profilePtr (returned by the function) will point to the memory where the variable profilePtr was located before. In other words: The value of the pointer profilePtr also becomes invalid because it points to a variable which no longer exists.
Maybe you have luck and the memory is not needed and the variable is not overwritten. But with a certain probability the function printf will need that memory and overwrite that (no longer valid) variable.
You might try this:
variablePtr = setData( ... );
printf("BirthDay (first time): %d\n", variablePtr->BirthDay);
printf("BirthDay (second time): %d\n", variablePtr->BirthDay);
With a high probability the following will happen:
printf will need the memory occupied by profile and therefore overwrite the data. However, in both lines above the value of BirthDay will first be read from the structure before the function printf is actually called.
Therefore the first printf will print the correct value of BirthDay while the second printf will print a wrong value.

how to put different type of data types in a Array dynamic in C

i try to store name and age in a dynamic array
when we have a different type of data , int , and Char that we dont know the size in the start how to use a dynamic array to store the 2 types
typedef struct personne{
char nom ;
int age ;
}personne;
struct personne saisie_personne_suivante(struct personne* x){
scanf("%s",&x->nom);
scanf("%d",&x->age);
return *x;
}
int main(void){
personne *ali;
ali = malloc(sizeof(char*));
saisie_personne_suivante(ali);
printf("\n %d ",ali->age);
printf("\n %s",&ali->nom);
return 0;
}
Why i dont sucess ?
i think we cant store two types of data at a time in array.If we do so we need to allocate half of memory to char and half to integers provided you should give some size of array.
=>in your program at this line [ali = malloc(sizeof(char*))] you are passsing address of only char not of variable.If you want to store both values just pass address of both int and char.
ali is a pointer to a struct of size sizeof(char) + sizeof(int) which may vary between architectures.
For the time being, let's assume it's 5 bytes (which it probably is on your PC).
What you're doing, is allocate space equal to size of a pointer to char, (which is either 32 or 64bits wide, depending on your OS).
What you probably want to do is allocate space equal to size of your struct (5 bytes), that is:
ali = malloc(sizeof(personne));
Note the lack of *, since you want actual memory for a struct and not a pointer pointing to such a location.
By the way, you wouldn't want to write: malloc(sizeof(char)) either, since that would be just one byte needed for your struct.
I strongly advise you to get your hands on a book on C or a decent tutorial at least.
int main() {
personne *ali;
ali = (struct personne *)malloc(sizeof(personne));
saisie_personne_suivante(ali);
printf("\n %d ", ali->age);
printf("\n %c", ali->nom);
return 0;
}
There is not enough memory for struct personne, so you need to malloc sizeof(personne) memory. nom is not a pointer,it's a char variable,when you print it, use printf("%c",ali->nom);
I can concur with the commenters who recommended a good book/tutorial to get started but nevertheless: here is your repaired code, with a bit of comment.
// printf(), fprintf(), and puts()
#include <stdio.h>
// exit(), malloc(), and scanf()
#include <stdlib.h>
#define PERSONNE_ERROR 0
#define PERSONNE_OK 1
typedef struct personne {
// fixed width for 49 characters and the trailing NUL
char nom[50];
int age;
} personne;
int saisie_personne_suivante(struct personne *x)
{
// For the returns of the scanf()s.
// Because you always check the returns if available
// (well, actually: the returns of printf() et al. rarely get checked)
// preset it to a value meant to say "OK"
int res = PERSONNE_OK;
// UX: let the users know what they are supposed to do.
puts("Your name, please");
// we have a fixed maximum size of name and we can set it here within scanf()
// scanf() returns the number of elements it parsed, *not* the number of characters
// sacnf() needs a pointer to the memory it is expected to put the value into.
// x->nom is already a pointer to a char array, no need to use "&"
if ((res = scanf("%49s", x->nom)) != 1) {
// we can return immediatly here.
// If we would need to cleanup (free memory, for example) we would
// set res to PERSONNE_ERROR and use a goto to jump at the place
// where all the cleanup happens. But that should be done if the clean-up
// is always the same (or could be sorted) and you need such cleanups
// more than just two or three times.
return PERSONNE_ERROR;
}
puts("Your age, too, if you don't mind.");
// x->age is not a pointer to an int, hence we need to prefix "&"
if ((res = scanf("%d", &x->age)) != 1) {
return PERSONNE_ERROR;
}
return res;
}
int main(void)
{
personne *ali;
int res;
// reserve momory for the struct
ali = malloc(sizeof(personne));
// call function that fills the struct and check the return
if ((res = saisie_personne_suivante(ali)) != PERSONNE_OK) {
fprintf(stderr, "Something went wrong with saisie_personne_suivante()\n");
exit(EXIT_FAILURE);
}
// print the content of struct personne
// you can feed printf() directly, no need to find the pointer to the memory
// holding the int
printf("Age: %d\n", ali->age);
// To print strings it needs to know the start of the string whcih needs to be
// a pointer and ali->nom is a pointer to the start of the string
printf("Name: %s\n", ali->nom);
// free allocated memory (not really necessary at the end of the
// program but it's deemed good style and because it costs us nothing
// we cannot find a good reason to skip it)
free(ali);
// exit with a value that tells the OS that this programm ended without an error
// It shoudl be 0 (zero) which it almost always is.
// *Almost* always
exit(EXIT_SUCCESS);
}
But really: go and get some beginners book/tutorial. I cannot give you a recommendation because I don't know about any good ones in your native language (sometimes the english version is good but the translation lacks a lot).

Can I create an Array of Char pointers in C?

I am new to C, and things are different in C than in any other language I've learned. In my homework I want to create an array of chars which point to an array of chars, but rather than make a multidimensional char array, I figure I'd have more control and create char arrays and put each individual one into the indexes of the original char array:
char keywords[10];
keywords[0] = "float";
The above example is to clarify and a simple case. But my question is due to the research I've been doing, and I am confused about something. Normally this would work in other languages, but in C it would be:
char *keyword[10];
keywords[0] = "float";
But when I want to send it through a function, why is this necessary:
void function(char **keyword); //function prototype
Wouldn't just passing the array pointer be enough?
It looks like you're confused by the double stars in
void function(char ** keyword);
The double stars just means that this function expects you to pass a pointer to a pointer to a char. This syntax doesn't include any information about the fact that you are using an array, or that the char is actually the first char of many in a string. It's up to you as the programmer to know what kind of data structure this char ** actually points to.
For example, let's suppose the beginning of your array is stored at address 0x1000. The keyword argument to the function should have a value of 0x1000. If you dereference keyword, you get the first entry in the array, which is a char * that points to the first char in the string "float". If you dereference the char *, you get the char "f".
The (contrived) code for that would look like:
void function(char **keyword)
{
char * first_string = *keyword; // *keyword is equivalent to keyword[0]
char first_char = *first_string; // *first_string is equivalent to first_string[0]
}
There were two pointers in the example above. By adding an offset to the first pointer before dereferencing it, you can access different strings in the array. By adding an offset to the second pointer before dereferencing it, you can access different chars in the string.
char *keyword[10];
keyword is an array 10 of char *. In a value context, it converted to a pointer to a char *.
This conversion is a part of what Chris Torek calls "The Rule":
"As noted elsewhere, C has a very important rule about arrays and pointers. This rule -- The Rule -- says that, in a value context, an object of type ‘array of T’ becomes a value of type ‘pointer to T’, pointing to the first element of that array"
See here for more information: http://web.torek.net/torek/c/pa.html
The C-FAQ also has an entry on this array to pointer conversion:
Question 6.3: So what is meant by the "equivalence of pointers and arrays'' in C?
http://c-faq.com/aryptr/aryptrequiv.html
In C, you can't really pass array to a function. Instead, you pass a pointer to the beginning of the array. Since you have array of char*, the function will get a pointer to char*, which is char**.
If you want, you can write (in the prototype) char *keyword[] instead of char **keyword. The compiler will automatically convert it.
Also, in C you can dereference pointers like arrays, so you loose almost nothing with that "converting to pointer".
If you want to
void function(char **keyword);
Andy, think about that an array is just a pointer(to the beginning of the array), that's why you write:
void function(char **keyword);
Because you have create an array to char pointers.
If it's easier to understand try:
void function(char *keyword[]);
But it's more C standard to use the first one, though if you use a C++ compiler won't really matter.
Here is the answer.
#include<stdio.h>
int main(void)
{
char *CharPtr[3];
char a[4]="abc";
char b[4]="def";
char c[4]="ghi";
CharPtr[0]=a;
CharPtr[1]=b;
CharPtr[2]=c;
printf("\n content of CharPtr[0] =%s",CharPtr[0]);
printf("\n content of CharPtr[1] =%s",CharPtr[1]);
printf("\n content of CharPtr[2] =%s\n",CharPtr[2]);
printf(" \n content of char a[4]=%s",a);
printf(" \n content of char b[4]=%s",b);
printf(" \n content of char c[4]=%s\n",c);
}
char *keywords[10] is an array of character pointers. So keywords[0], keywords[1].. and so on will have the addresses to different character arrays.
In printf you can use %s and keywords[0] to print the entire character array whose address(i.e. address of the first byte in the array) is stored at keywords[0].
While passing to a function, if you give *keywords, you are referring to the value at(address stored at keywords[0]) which is again an address. So, to get the value instead of address, you can add another *... Hope that clarifies a bit..
I am assuming that you are assigning your first string:
"float"
to the first index position of keyword[0]
char keyword[0] = "float";
which is the first index position of the array:
char keyword[10];
If the previous is the case, then in a sense, you are essentially creating a data structure that holds a data structure. The array of any type is the 'smallest' data structure of that type in C. Considering that in your example you are creating a character array, then you are actually utilizing the smallest data type (char=1bit) at each index position of the smallest built in data structure (the array).
With that said, if in your example, you are attempting to create an array of arrays; your character array
/* Hold ten characters total */
char keyword[10];
was designed to hold 10 characters. One at each index position (which you probably already know). So after declaring the array titled keyword, you then try to initialize the first index position of the array with another (the second) character array:
/* I believe this is what you had stated */
char keywords[0] = "float";
With the second character array having an index of 5 positions in size.
In order to achieve your desired goal, you would essentially be creating an array that basically emulates the effect of a data structure that 'holds' other data structures.
NOTE: If you had/have plans on trying to create a data structure that holds a data structure that holds a data structure. A.K.A. a triple nested data structure and in this case I think that would be a Matrix, WHICH I WOULDN'T RECOMMEND!
None the less, the matrix structure would be in the form of the first index position of keyword, being assigned the whole array of keywords, which would include all of the data stored in each index position of the keywords array. Then there would something probably like: keywords1, keywords2, ... keywords9,
which would essentially emulate the form of:
char *keyword[10] = {
char *keywords0[10] = {"float", etc, etc, etc.};
char *keywords1[10] = {"keyword1", "secondIndexOfThisArray", etc, etc, etc.};
and so
};
So basically from right to left, the keyword array, is an array of pointers that points to array of pointers that points to character arrays.
If that is what you are representing you would be better defining a custom data type of struct/record, and with in that custom structure you would want to define a subordinate or child level of structures. You could also pre-declare them then initialize them.
e.g.
typedef *nestedDataStructures {
struct keyWords[];
struct keyWords1[];
struct keyWords2[];
... and so on.
}; nestedDataStructures
Instead of adding ten structs to one custom structure I would break down into 3 or 4 (how ever many structures and use) and create a module in order to yield symmetrical layers of abstraction as you manipulate your data set.
None the less, you can not create the character array and potentially assign the other character array in the fashion that you did (or who knows maybe you can), but the way you would want to emulate the array that holds arrays, is to create a character pointer array up front, of X number index positions and then initialize then use the character arrays in the form of a strings declared with in the initialization of the original declaration.
So basically you could declare your whole array upfront, then with in your program design, either dereference each index position, use assignment, or print/write the index position.
Like for instance you could always do something like this:
/* Example of the program and declaration with out a function */
#include <stdio.h>
int main(){
/*
* A character pointer array that contains multiple
* character arrays.
*/
char *grewMe[2] = {"I want to ", "grow to be bigger"};
int w = 0;
for(; w < 2;) {
printf("%s", grewMe[w]);
++w;
}
printf(" :-)\n");
w = 0;
return 0;
}
// Output:
// I want to grow to be bigger :-)
Or something like this:
/* Example of program: function passed arguments
* of a pointer to the array of pointers
*/
#include <stdio.h>
void mygrowth(char *growMe[]);
int main(){
char *growMe[2] = {"I want to ", "grow to be bigger"};
mygrowth(growMe);
printf(" :-)\n");
return 0;
}
void mygrowth(char *growMe[])
{
int w = 0;
for (; w < 2;) {
printf("%s", growMe[w]);
++w;
}
}
The assignment of each index position as it's passed as an argument:
/*
* This program compiles, runs and outputs properly
* Example of a program with a function of
* arguments pnt2pnter
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
thoughtAsAFunction(iThink);
printf(":-)\n");
return 0;
}
void thoughtAsAFunction(char **iThink) {
int andy = 0;
for (; andy < 10;) {
char * pntThroughPnt = iThink[andy];
printf("%s", pntThroughPnt);
++andy;
}
andy = 0;
}
Or pass by reference, with an increment of the loop count variable:
/*
* This program compiles, runs, and outputs all of the character
* arrays.
*
*/
#include <stdio.h>
#include <stdlib.h>
void thoughtAsAFunction(char **iThink);
int main()
{
char *iThink[10] = {"I am trying to grow, but it's a hard task to ",
"accomplish. My father is short ",
"my mother is even shorter than him, ",
"what is the probability of me getting taller? ",
"Well both my grandfather's were Six ",
"Foot Five, and both my grandmother's ",
"were over 5 foot 8 inches tall! If my ",
"grandparent's genes point to my parents, and my ",
"parent's genes point to mine, then I might have a chance ",
"of being 6 foot. Do you know what I mean? "};
int andy = 0;
for (; andy < 10;) {
// pass by reference and increment.
thoughtAsAFunction(&iThink[andy]);
++andy;
}
printf(":-)\n");
andy = 0;
return 0;
}
void thoughtAsAFunction(char **iThink) {
char * pntThroughPnt = *iThink;
printf("%s", pntThroughPnt);
}
Keep in mind that this is the case if you declare the array of pointers (char *array[10];), and each pointer points to an array of characters.

Program "sometimes" crash when using free

My program sometimes crash, and sometimes not when im calling free() on a element from my array. The elements in the array are a struct. I'll show with some code:
//This first part might be a bit messy, and hard to understand but it is working
int main(int argc, char *argv[]){
komplexNumber komplexNumbers[antal-1];
int i;
float temp;
int realCounter=0;
int imaginarCounter=0;
int numberOfElements=6 // this variable is set by the user using scanf, and can be any number>=2. Each komplexNumber consists of two numbers (i.e 9 -3j is a complex number)
for(i=0;i<numberOfElements*2;i++){ //
printf("Enter number %i\n", i+1);
scanf("%f", &temp);
if(i%2==0){ //a complex number consts of two parts. first entered number is first part of number1, second is second part of number1, third is first part of nr 2 etc
komplexNumbers[realCounter].real=temp;
realCounter++;
}
else{
komplexNumbers[imaginarCounter].imaginar=temp;
imaginarCounter++;
}
//The struct
typedef struct komplexNumber{
float real;
float imaginar;
} komplexNumber;
//The method that mallocs memory for each element:
void calculation(float a1, float a2, float b1, float b2, komplexNumber komplexNumbers[]){
float temp1 = (a1*a2)-(b1*b2);
float temp2 = (a1*b2)+(a2*b1);
komplexNumber *k;
k=(komplexNumber*)malloc(sizeof(komplexNumber));
k->real=temp1;
k->imaginar=temp2;
komplexNumbers[0]=*k;
}
//The loop, in which im calling free each iteration:
int counter=1;
for(i=0;i<(numberOfIterations-1);i++){
a1=komplexNumbers[0].real;
b1=komplexNumbers[0].imaginar;
a2=komplexNumbers[counter].real;
b2=komplexNumbers[counter].imaginar;
calculation(a1, a2, b1, b2, komplexNumbers);
counter++;
free(komplexNumbers[counter]);
}
This program crashes sometimes, and sometimes not. I haven't been able too see a pattern why it does, but it's the free() function that causes the crash (since when I remove free and run the program with the same values, it doesn't crash). I have not been able too see a pattern in which causes the crash. It can handle negative numbers
Note: each struct element is called complexNumber, and the array is called complexNumbers (with an s:) )
There are at least a few issues:
You're always assigning komplexNumbers[0] and freeing komplexNumbers[count]
komplexNumbers[0] = *k probably means komplexNumbers is an array of structs, not an array of pointers - you're assigning a struct, not a pointer
EDIT
In light of recent code, it's easier to show you what to do than to explain what you're doing wrong. As suspected, komplexNumbers is an array of structs. In your calculation function you don't need all that malloc stuff (and consequently you don't need the free bit). Do this instead:
komplexNumbers->real = temp1;
komplexNumbers->imaginar = temp2;
Because in calculation you always set value of 0th item (by copying the value pointed by k), then you want to free unallocated array items.
I find this part of code as little messy :-
komplexNumbers[0]=*k; inside cacluation . As it will again and again set pointer to complex type only in index 0. When you try and free this While itearting in a for loop using counter it Will fail for values of counter > 0 . I guess so But it would be better
if you frame question in a nice way and post so that we can look into it`
How is komplexNumbers (the array) allocated? You can not call free on anything that has not been returned by malloc. And you're leaking memory, the memory for k is lost when returning from calculation.

Dynamic Memory storage issue after realloc - C

For an assignment at school, we have to use structs to make matrices that can store a infinite amount of points for an infinite amount of matrices. (theoretical infinite)
For the assignment I decided to use calloc and realloc. How the sizes for the matrix go is: It doubles in size every time its limit is hit for its points (so it starts at 1, then goes to 2, then 4 and so on). It also doubles in size every time a matrix is added as well.
This is where my issue lies. After the initial matrix is added, and it goes to add the second matrix name and points, it gives me the following:
B???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
B is the portion of it that I want (as I use strcmp later on), but the ? marks are not supposed to be there. (obviously)
I am not sure why it is exactly doing this. Since the code is modular it isn't very easy to get portions of it to show exactly how it is going about this.
Note: I can access the points of the matrix via its method of: MyMatrix[1].points[0].x_cord; (this is just an example)
Sample code that produces problem:
STRUCTS:
struct matrice {
char M_name[256];
int num_points[128];
int set_points[128];
int hasValues[1];
struct matrice_points * points;
} * MyMatrix;
struct matrice_points {
int set[1];
double cord_x;
double cord_y;
};
Setup Matrix Function:
void setupMatrix(){
MyMatrix = calloc(1, sizeof(*MyMatrix));
numMatrix = 1;
}
Grow Matrix Function:
void growMatrix(){
MyMatrix = realloc(MyMatrix, numMatrix * 2 * sizeof(*MyMatrix));
numMatrix = numMatrix * 2;
}
Add Matrix Function which outputs this problem after growing the matrix once.
void addMatrix(char Name, int Location){
int exists = 0;
int existsLocation = 0;
for (int i = 0; i < numMatrix; i++){
if (strcmp(MyMatrix[i].M_name, &Name) == 0){
exists = 1;
existsLocation = i;
}
}
*MyMatrix[Location].M_name = Name;
printf("Stored Name: %s\n", MyMatrix[Location].M_name);
*MyMatrix[Location].num_points = 1;
*MyMatrix[Location].set_points = 0;
*MyMatrix[Location].hasValues = 1;
MyMatrix[Location].points = calloc(1, sizeof(*MyMatrix[Location].points));
}
void addMatrix(char Name, int Location)
char Name represents a single char, i.e. a integer-type quantity. char is just a number, it's not a string at all.
When you do this:
strcmp(..., &Name)
you're assuming that the location where that one character is stored represents a valid C string. This is wrong, there is no reason why this should be the case. If you want to pass a C string to this function, you will need to declare it like this:
void addMatrix(char *Name, int Location)
Then you need to copy that C string into the appropriate place in your matrix structure. It should look like:
strncpy(... .M_name, Name, max_number_of_chars_you_can_store_in_M_Name);
Also these field definitions are strange in your struct:
int num_points[128];
int set_points[128];
int hasValues[1];
This means that your struct will contain an array of 128 ints called num_points, another array of 128 ints calls set_points, and an array of one int (strange) called hasValues. If you only need to store the count of total points and set points, and a flag indicating whether values are stored, the definition should be:
int num_points;
int set_points;
int hasValues;
and correct the assignments in your addMatrix function.
If you do need those arrays, then your assignments as they are are wrong also.
Please turn on all warnings in your compiler.
Try adding '\0' to the end of your data.
*MyMatrix[Location].M_name = Name;
You're copying a single character here, not a string. If you want a string, Name should be defined as char *, and you should be using strcpy.

Resources