0
typedef struct node{
char *name;
//etc...
}N

If i had char *string got from stdin and i wanted to pass it to N, i could do easily N->name=string, or it would be bettere to use strcpy? which is more correct? which is more efficient? why?

thesmizzle
  • 21
  • 4
  • 3
    We don't know. Show more context. – Joshua Sep 10 '19 at 16:57
  • which one would you use? if "it depends", in what depends? – thesmizzle Sep 10 '19 at 17:00
  • @Joshua the result is the same, but what's the difference? – thesmizzle Sep 10 '19 at 17:01
  • The result is not the same. It's up to you to describe your use-case, not us to list the possible ones. – Eugene Sh. Sep 10 '19 at 17:01
  • @thesmizzle It comes down to the details of the application. How long does the string need remain accessible? It's like the difference between me saying "the document you need is on my desk" or "here's your own copy of the document". If I'm sure it will stay on my desk as long as you might possibly need to see it, you don't need your own copy. If it might not, you do. – David Schwartz Sep 10 '19 at 17:01
  • 1
    Note that if you call `strcpy` without allocation enough memory to the `N->name`, a `segmentation fault` will be thrown. – XBlueCode Sep 10 '19 at 17:02
  • @DavidSchwartz collected in a linked list and deleted if someone from stdin writes the command to delete it. p.s. beautiful explanation – thesmizzle Sep 10 '19 at 17:02
  • if you've got a linked list then very likely you will use pointers. You will probably either use `strcpy` or directly read into allocated memory. – Antti Haapala -- Слава Україні Sep 10 '19 at 17:03
  • 1
    @thesmizzle If it is guaranteed to remain valid for as long as any other code might need to see it then a pointer to it is sufficient. If not, then you will need to allocate a separate chunk of memory and copy the string into it. – David Schwartz Sep 10 '19 at 17:03
  • If you use `N->name = string;`, you need to make sure that there's a different `string` for each `N`. – Barmar Sep 10 '19 at 17:04
  • @Barmar And that each `string` lives as long as `N` does. – Eugene Sh. Sep 10 '19 at 17:04
  • The choice probably isn't between pointers and strcpy, it's between pointers and arrays, e.g. `char name[MAXSIZE];` – Barmar Sep 10 '19 at 17:05
  • By doing `N->name=string` you're assigning the pointer, so every change to `string` will also change `N->name`, so if you plan to process multiple values then it's better to use `strdup` which allocate new memory for N->name. – XBlueCode Sep 10 '19 at 17:08

2 Answers2

2

You want to use a buffer to read your input from stdin. But if you don't make a copy, your string will be lost at the next read iteration. If you are going to allocate memory, and if you don't know the size of the string you receive, you should use a function like strdup instead of strcpy.

node->name = strdup(string_to_copy);
if (node->name == NULL)
     printf("My allocation has failed!\n");

The allocated memory will have to be freed afterward. If the allocation fails, you will have a message (you should always check the success of your memory allocation).

If you don't want to allocate memory and if you know that the size of your input will never be higher than say, 100, you could get away with something like this:

typedef struct node{
char name[100];
//etc...
}N

In that case you could use the following. Note that strcpy is a dangerous function that should be used with extra-care:

strncpy(node->name, buffer, 100);
strcpy(node->name, buffer);

EDIT:

Here is a way to free your memory properly:

if (node->name != NULL)
{
   free(node->name);
   node->name = NULL;
}

This construction will free your memory and helps preventing double-free.

AugustinLopez
  • 348
  • 1
  • 3
  • 13
0

Answering "the result is the same, but what's the difference?" (from comment)

Starting from:

N *node = malloc(sizeof(N));
char input_from_stdin[80];

If we do

strcpy(node->name, input_from_stdin);

we invoke undefined behavior, but it might appear to work.

If we do

node->name = input_from_stdin;

than node->name only contains its expected value until input_from_stdin is reused, which is typically when the next line is read form input.

If we do

node->name = malloc(strlen(input_from_stdin) + 1);
strcpy(node->name, input_from_stdin);

we make a copy of the input that lives until we free it; but we must remember to free node->name before freeing node.

We can also do

typedef struct node{
    char name[MAXSIZE];
    //etc...
 }N;

and then expect

strncpy(node->name, input_from_stdin, MAXSIZE-1)[MAXSIZE-1] = 0;

to work.

Some poeple do

strncpy(node->name, input_from_stdin, MAXSIZE);

which is valid but getting it back out again is touchier. This is rarely seen out of fixed-width records on disk now. We don't like MAXSIZE much anymore and prefer everything stretchy.

Joshua
  • 40,822
  • 8
  • 72
  • 132