failed while trying to reach pointer in struct - c

my project is to build book structure - and fill it with users parameters.
involving dynamic allocation, arrays and pointers.
my book structure has the following:
struct BOOK
{
char* author;
char** genders;
int totalGenders;
char* name;
int* chapterPages;
int totalChapters;
}typedef book;
when I tried reaching author name, line 1 in structure:
struct BOOK
{
char* author;
I failed doing that.. my code in main :
int main()
{
book* b;
char authorChar[10] = { 0 };
int authorLen;
char* authorName;
// get author name
puts("please enter the name of the author");
scanf("%s", &authorChar);
authorLen = strlen(authorChar);
printf("%d", authorLen); //print to see that lentgh is correct.
authorName = (char*)calloc(authorLen, sizeof(char));
strcpy(authorName, authorChar);
puts("\n");
b->author = authorName;
printf("%d", b->author);
when i have debugged i got a problem in this line :
b->author = authorName;
ideas please? :)

The problem is in the following line
b->author = authorName;
at this point, b is not allocated memory, i.e., b is an uninitialized pointer. It points to some random memory location which is not a valid one. Any attempt to access invalid memory invokes undefined behavior.
You can use either of the following approach to resolve the issue:
allocate memory to b dynamically before using it, like b = malloc(sizeof*b); and a check for success.
define b as a variable of type book, instead of a pointer-to-type.
That said, int main() should be int main(void) at least, to conform to the standards.

You are forgetting to do the memory allocation for b variable.
b = malloc(sizeof(book));
b->author = malloc(sizeof(100000)); // replace value for the size you want

Related

C passing string between functions

I'm writing simple program in C and got stucked. I have three functions:
void changeStatusOfBook(User users[], Book books[]) {
char *id= askForBookID();
Book book = getBookById(books, id);
.
.
.
}
char * askForBookID() {
char id[6];
printf("Tell me which book (ID)\n");
scanf_s("%5s",id, 6);
return id;
}
Book getBookById(Book books[], char bookID[]) {
int counter = 0;
//bookID becomes a trash here
.
.
.
}
The problem is: In the first function I get correct user string input, but when I pass it to third function I'm getting some trash in it. How to fix it?
You can't return a local variable char id[] from a function.It's memory is on the stack and when the function returns all stack memory for that function and its local variables are no more accessible.
when memory is need on the stack for another program it overrides the memory space for char id, and this becomes a problem for your program.
char * askForBookID() {
//char id[6];
char *id = malloc(sizeof(char)*6);
if(!id){ //check if malloc got some memory for id
printf("Sorry not enough memory"); return NULL;
}
printf("Tell me which book (ID)\n");
scanf_s("%5s",id, 6);
return id;
}
The function askForBookID returns the address of the first element of an array with automatic storage duration.
The behaviour on your using that pointer oncce the function has been called is undefined.
Use malloc instead.

Create an element of a struct array using struct pointer function

I have been trying to write a function with a pointer point to a struct array. After calling it my array should have a new struct element.
This is my function changed by ur guys suggestion
void addPic(pic *picture_Record, int picNumber){
pic tmp_Pic;
char tmp_fileName[100];
char tmp_description[100];
char tmp_location[100];
if (picture_Record[picNumber].description ==NULL || picture_Record[picNumber].fileName ==NULL||picture_Record[picNumber].location==NULL)
return;
printf("Enter: Picture Name, Picture Description, Picture Location, Picture People(int)\n");
scanf("%s%s%s%d",tmp_fileName, tmp_description, tmp_location, &picture_Record[picNumber].peopleCount);
tmp_Pic.fileName = (char*)malloc(strlen(tmp_fileName)+1);
tmp_Pic.description=(char*)malloc(strlen(tmp_description)+1);
tmp_Pic.location = (char*)malloc(strlen(tmp_location)+1);
strcpy(tmp_Pic.fileName, tmp_fileName);
strcpy(tmp_Pic.description, tmp_description);
strcpy(tmp_Pic.location, tmp_location);
picture_Record[picNumber] = tmp_Pic;
free(tmp_Pic.fileName);
free(tmp_Pic.description);
free(tmp_Pic.location);
printf("\nInput Done!\n");
This is how I call it.
int picNumber = 0
pic pictureRecord[Maximun_Picture +1]= { "" };
addPic(&pictureRecord[picNumber], picNumber);
picNumber++;
//testing
printf("%s",pictureRecord[0].location)
This is my struct.
typedef struct picture_Data
{
char* fileName;
char* description;
char* location;
int peopleCount;
}pic;
It doesn‘t work and printing me Null as th location of the first element. Why? Can somebody help me.
The problem is that this line
scanf("%s%s%s%d",pic_tmp.fileName, pic_tmp.description, pic_tmp.location, &pic_tmp.peopleCount);
assumes that pic.tmp has sufficient space allocated for fileName, description, and location. None of that is true, however, because all three fields remain uninitialized.
In order to fix this, change the code to read strings into a temporary buffer, and then copy it into dynamically allocated strings.
Here is how you do it for fileName; you need to do the same thing for all three:
char tmp_fileName[100];
char tmp_description[100];
char tmp_location[100];
scanf("%99s%99s%99s%d",tmp_fileName, tmp_description, tmp_location, &pic_tmp.peopleCount);
pic_tmp.fileName = malloc(strlen(tmp_fileName)+1);
strcpy(pic_tmp.fileName, tmp_fileName);
...
You can copy the struct with a single assignment, too:
picture_Record[picNumber] = pic_tmp;
Don't forget to call free on all three members of each struct to avoid memory leaks.
You should first have to allocate memory
void addPic(pic *picture_Record, int picNumber){
pic pic_tmp;
printf("Enter: Picture Name, Picture Description, Picture Location, Picture
People(int)\n");
pic_tmp.fileName = (char *)malloc(5);
picture_Record[picNumber].fileName = (char *)malloc(5);
scanf("%s%d",pic_tmp.fileName, &pic_tmp.peopleCount);
printf("\nInput Done!\n");
strcpy(picture_Record[picNumber].fileName, pic_tmp.fileName);
//picture_Record[picNumber].fileName = pic_tmp.fileName;
picture_Record[picNumber].description= pic_tmp.description;
picture_Record[picNumber].location = pic_tmp.location;
picture_Record[picNumber].peopleCount = pic_tmp.peopleCount;
printf("%s,%s",pic_tmp.fileName,picture_Record[picNumber].fileName );
}

Changing values in elements of an array of structs

I am working on an assignment and ran into challenging problem. As far as I'm concerned and from what I've learnt the code that follows should be correct however it does not work. Basically what I am trying to is copy a string value into the variable member of a structure the is part of an array passed into a method as a pointer. What am I missing?
typedef struct
{
char * name; //variable in struct I am trying to access
} Struct;
void foo(Struct * arr) //array of Structs passed into function as a pointer
{
int i = 0;
while(i++ < 2)
{
arr[i].name = malloc(sizeof(char *)); //assigning memory to variable in each Struct
arr[i].name = strdup("name"); //copying "name" to variable in each Struct
printf("C - %s\n", arr[i].name); //printing out name variable in each Struct
}
}
main()
{
Struct * arr; //defining pointer
arr = calloc(2, sizeof(Struct)); //allocating memory so pointer can hold 2 Structs
foo(arr); //calling function foo passing pointer into function
return 0;
}
This code compiles and runs however it does not do what it is designed to do. Forgive me if it is something trivial. I am new to the language C
Two issues:
while(i++ < 2) This line changes the value of i as soon as it checks it, so your loop body will not be the same as it was checked.
arr[i].name = strdup("name"); overwrites the value of the .name pointer, causing a memory leak of the memory you malloc()'ed earlier.
Extending on 2 pointed out correctly already,
arr[i].name = strdup("name");
Even if you use following instead of above,
strcpy(array[i].name, "name");
you haven't allocated enough bytes to store the string i.e. this is wrong
arr[i].name = malloc(sizeof(char *));
// even if pointer is 8 byte here, concept isn't right
Should be something like
arr[i].name = malloc(strlen("name")+1);
// or MAX_SIZE where it is greater than the possible "name".
Or better yet, remove the malloc at all, strdup takes care of allocation itself
This is not answering your question directly, but addresses an issue to big to put into a comment...
Additional issue: You probably did not intend to allocate only a (char *) worth of memory to a variable intended to hold at least "name". Change;
arr[i].name = malloc(sizeof(char *));
to:
arr[i].name = malloc(sizeof(char)*strlen("name")+1); //+1 for '\0'
or better yet, use char *name="name";, then:
arr[i].name = malloc(sizeof(char)*strlen(name)+1);
Even more general (and better):
char *name;
name = malloc(strlen(someInputString)+1);
//do stuff with name...
free(name);
Now, you can allocate name to any length needed based on the length of someInputString.
[EDIT]
Etienz, I wanted to address one more thing, alluded to by #H2CO3 above, but not really explained, that I think might be useful to you:
Regarding your desire to have room for two structs, because you typedef'd your struct, you can simply do something like this: (but I am going to change the name you used from Struct to NAME :) The whole point being that when a struct is created as an array, you do not need to use calloc or malloc to create space for them, it is done as shown below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *name;
}NAME;
//use new variable type NAME to create global variables:
NAME n[2], *pN; //2 copies AND pointer created here
//prototype func
int func(NAME *a);
int main()
{
pN = &n[0]; //pointer initialized here
func(pN); //pointer used here (no malloc or calloc)
printf("name1 is %s\nname 2 is %s", pN[0].name, pN[1].name);
return 0;
}
int func(NAME *a)
{
char namme1[]="andrew";
char namme2[]="billebong";
//You DO have to allocate the members though
a[0].name = malloc(strlen(namme1)+1);
a[1].name = malloc(strlen(namme2)+1);
strcpy(a[0].name, namme1);
strcpy(a[1].name, namme2);
return 0;
}

Trying to structure with call by value and call by reference...code compiles without any error..but prints garbage value?

Hi friends as I am new to C practising hard to understand all nitygrity things in C. While trying Structure I manage to write a piece of code where I am trying to pass structure to a function by value and reference. But I think I am doing something wrong...please help friends...it would be a great help if you guys can guide me to a proper in depth tutorial on Structures...thanks
#include <stdio.h>
#include <stdlib.h>
struct foo{
char arr[200];
int x_val;
int y_val;
float result;
};
struct foo my_foo;
int foo_fun(struct foo var); //proto declearation
int foo_fun1(struct foo *var1); //proto declearation
int main()
{
//As I was not getting prover string printed by using function foo_fun1
// I have tried to print directrly calling another ptr here
int i = 0;
struct foo *ptr;
ptr = (struct foo *)malloc(sizeof(struct foo)*10);
ptr->arr[0] = "calculator";
printf("Ptr zero contains a string %s\n",ptr->arr[0]); //even here prints wrong value
i = foo_fun(my_foo);
printf("Result from foo_fun is %d\n",i);
//Expecting this function to print string ....but getting some unexpected result
foo_fun1(&my_foo);
system("pause");
return 0;
}
// pass by value
int foo_fun(struct foo var)
{
int i;
int total = 0;
for(i=0;i<sizeof(var.arr); i++)
{ var.arr[i] = i;
total = total+var.arr[i];
}
var.x_val = 230;
var.y_val = 120;
return total;
}
// pass by reference
int foo_fun1(struct foo *var1)
{
int i = 0;
var1 = (struct foo *)malloc(sizeof(struct foo)*20);
var1->arr[0] = "A";
printf("%s\n",var1->arr);
return 0;
}
The following is wrong:
ptr->arr[0] = "calculator";
(BTW, your compiler should have warned you about this.)
You should use strcpy() instead.
The same goes for the other place where you're using a similar construct.
Finally, the malloc() in foo_fun1() is unnecessary. Not only you're overwriting the value of the function argument (why?), you are also leaking memory.
The line
ptr->arr[0] = "calculator";
is wrong, you cannot assign a string to a single character, that's what ptr->arr[0] represents.
ptr->arr = "calculator";
would be wrong too, since you cannot assing a string to a char array in that way, you have to use strcpy().
printf("Ptr zero contains a string %s\n",ptr->arr[0]);
should also be
printf("Ptr zero contains a string %s\n",ptr->arr);
since you are printing an array not a single char
Three problems in your code:
You must not cast return value from malloc() -
you are trying to assign a constant string to an indexed array - so it should be
strcpy(ptr->arr, "calculator"); and strcpy(var1->arr,"A");
Also - there is a massive memory leak in your code. No call to free() anywhere.

How to pass array element to structure?

I am trying to learn C. I have created this structure where I am trying to pass names from an existing array to one of the structure element name[100], I am unable to understand how to pass it? Guys please help me and guide me how to do it. It would be a great help if somebody can guide me to a good structure tutorials(there are lots on web, but only basics)…thanks.
typedef struct new_st{
char name[100];
int icon_number;
float calculation;
}var;
char arr_name[] = {“name1”, “name1”, “name1”, “name1” };/this lines throws error
int main(){
var *ptr_var;
New_var = malloc(sizeof(struct new_st)*100);
strcpy(&arr_name[0], ptr_var[1].name);//this lines throws error
return 0;
}
use strcpy() :
strcpy(New_var[0].name, arr_name[0]);
Advice: do not cast the return value from malloc()
--EDIT after the source code posted --
You probably meant: strcpy(ptr_var[1].name, arr_name[0]); and
this is suppose to be:
char *arr_name[] = {“name1”, “name1”, “name1”, “name1” };/*this lines throws error*/
I think what you want to do is this:
var *ptr_var;
ptr_var = malloc(sizeof(struct new_st) * 100);
ptr_var[0].calculation = 1.5f; //assigning variable inside your struct 0 in your array of structs
ptr_var[0].name = "Foobar";
strcpy(&arr_name[0], ptr_var[1].name); //copy string
//Free memory at end of your program
free(ptr_var);

Resources