1

(newbie question)

Look at this struct:

struct Atom_data{
char *name;
char symbol;
double weight;
};

I want to write a function that gets a struct pointer as input, in this function with the usage of scanf(), I want to give each member of struct a value, which one of them is string. So far I have written this function:

void data_entry(struct Atom_data* ptr){

printf("Please write the Atom's Name:\n");
ptr =(struct Atom_data *)malloc(sizeof *ptr);
ptr->name = malloc(20);

scanf("%s", ptr->name);


printf("Please write the Atom's symbol:\n");
scanf("%c", &ptr ->symbol);


printf("please write the Atom's weight:\n");
scanf("%lf", &ptr ->weight);
}

for symbol and weight there was no problem (when I mask the codes related to name). But for name there is a crash without Error. these codes inside the function (specially codes related to name) worked perfectly outside of the function. (I tried to test each part of them on the main function)

I learnt to write this line of code ptr =(struct Atom_data *)malloc(sizeof *ptr); from a question about passing values to pointer! but for the line after that which is ptr->name = malloc(20);, I just did it based on some ideas about creating dynamic memory for name, which worked outside of the function! (Any clarification about it would show your great favour).

  • What exactly is your question? A pointer does not point anywhere valid until you assign the address of valid memory to it. So yes, you do need to `malloc` the `name` pointer before writing to it. An alternative is to declare `name` as an array instead of a pointer: e.g. `char name[20];` – kaylum Jan 22 '21 at 01:51
  • @kaylum my main question is about my function that is not working! thanks for your clarification about malloc the name . – Babak Abdolahzade Jan 22 '21 at 01:55
  • 2
    You need [a good book on C](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list). The questions you're asking are more on the learning curve best suited by well-developed, well-presented, education program (be it a book, a course, or ideally, *both*). C isn't a very complicated language; but it can be incredibly frustrating to learn if you're not accustom to how ruthless and unforgiving it can be, especially when it comes to matters of allowing one to shoot themselves in the foot. Your intuition isn't bad at all, but concrete references help a LOT. – WhozCraig Jan 22 '21 at 01:55
  • @WhozCraig, Thank you for your suggestion, well I am doing Coursera specialization for it, I am slow but I search a lot for deep understanding the concept. but at last, I need a good book for getting totally familiar with the language. but for this question, I couldn't really find something useful on the Internet. – Babak Abdolahzade Jan 22 '21 at 01:59
  • I'm not familiar with their program. Hopefully for your sake they're not terrible, and if not, they're in the tragic minority of online tutelage, because most are absolute crap. A handy site for language and library *reference* is [this one](https://en.cppreference.com/w/c), which has both C and C++ and is frankly unbeatable for content and compliance with current and past standards. Bookmark that if you're ever stuck on a function or wondering about language intrinsics (and of course, this one too). – WhozCraig Jan 22 '21 at 02:06
  • `char symbol;` is good for 1 character. Many elements use 2 or sometimes more characters. [Uuo](https://en.wikipedia.org/wiki/Oganesson#Naming). – chux - Reinstate Monica Jan 22 '21 at 02:48
  • 1
    *"(newbie question) ... with the usage of `scanf()`..."* STOP. Don't go down that well worn road of pitfalls all new C programmers fall into. Do it right. *"with the usage of `fgets()` and a sufficiently sized buffer, I will read all input and use `sscanf()` to parse values from the buffer for each member of the struct ..."* I will ***Validate*** EVERY user-input by ***checking the return*** of the input function used to verify the input. Now continue in a good direction. – David C. Rankin Jan 22 '21 at 03:17

1 Answers1

2
void data_entry(struct Atom_data* ptr){

printf("Please write the Atom's Name:\n");
ptr =(struct Atom_data *)malloc(sizeof *ptr);

Will do nothing useful for you. You are setting ptr to a dynamically allocated piece of memory, but it won't change the pointer you pass into the function:

struct Atom_data *data = NULL;
data_entry(data);
// data will still be NULL

If the desired behaviour is in fact, to set a pointer from within the function you need to use a "pointer to a pointer" like this:

void data_entry(struct Atom_data **ptr) {
    *ptr = malloc(sizeof(** ptr));
}

And then later:

struct Atom_data *data = NULL;
data_entry(&data);
// data will not be NULL (if malloc worked.)

However, this is unecessarily complicated, the common way to do it is like this:

struct Atom_data *data_entry() {
    struct Atom_data *ptr = malloc(sizeof(* ptr));
    // check for NULL pointer returned by malloc (out of memory)
    if (!ptr) return NULL;

    // initalisation
    ptr->name = NULL;
    ptr->symbol = 'a';
    ptr->weight = 0;
    return ptr;
}

And use it like this:

struct Atom_data *data = data_entry();

Of course, if you want to initialize the struct within the function, you'll need to pass those as well:

struct Atom_data *data_entry(char *name, char symbol, double weight)

It really depends on how you want to initialize the struct.

Note: memory allocated with malloc can/should be "released" (or given back to the OS) with free. Failing to do so, can lead to memory leaks.

Also, be careful with scanf:

Disadvantages of scanf

Reading a string with scanf

Some other resources, that might be of interest to you:

Difference between pointer and array

Difference between char * and char []

Difference between "." and "->".

marco-a
  • 4,996
  • 1
  • 15
  • 41
  • 1
    Not an error, but since `ptr` is a variable name and not a type, `sizeof **ptr` is sufficient. Parens are only required surrounding a type. – David C. Rankin Jan 22 '21 at 03:21
  • @marco-a Thank you for your great information! can you explain more about `struct Atom_data *data_entry()` for creating function? I mean, I can understand what you did, but I want to know deep what is exactly function az pointer to struct? – Babak Abdolahzade Jan 23 '21 at 00:29
  • @BabakAbdolahzade You are very welcome. `struct Atom_data *data_entry()` means the function `data_entry()` returns a pointer to a struct `Atom_data`. You need to be careful about what you return in a function. For example, you cannot return a pointer to something that is saved on the stack: `int *do_not_do_this() { int my_var = 1; return &my_var; }`. This is because the variable `my_var` gets popped off the stack, once the function finished running. In the case of `malloc` it works because the memory is allocated in a different location, called the heap. – marco-a Jan 23 '21 at 11:24
  • That is why you need to `free()` the memory you allocated with `malloc()`. – marco-a Jan 23 '21 at 11:25
  • @BabakAbdolahzade If you want to know more search for `stack vs heap` or something like this. I **highly** recommend you understand the difference between the two – marco-a Jan 23 '21 at 11:27
  • @marco-a thank you so much. – Babak Abdolahzade Jan 23 '21 at 21:22