Char pointer - How to give value?

A

alij

Hi,

I have just started learning C and am working on pointers but am
having difficulty with the following:

If i have a struct, that includes a pointer to char (in my case, i've
named it filename), and in the main code, I want to use that pointer
to create a memory location and assign a character string.

I have gotten the following in the main code (structPtr is a pointer
to they type of struct i have created):

structPtr->filename = malloc(10 * sizeof(char));

How do I give a value, lets stay string value of "cust.txt" to this
field?

Will appreciate any help,

Thanks,

Alij
 
F

Francine.Neary

Hi,

I have just started learning C and am working on pointers but am
having difficulty with the following:

If i have a struct, that includes a pointer to char (in my case, i've
named it filename), and in the main code, I want to use that pointer
to create a memory location and assign a character string.

I have gotten the following in the main code (structPtr is a pointer
to they type of struct i have created):

structPtr->filename = malloc(10 * sizeof(char));

How do I give a value, lets stay string value of "cust.txt" to this
field?

strcpy(structPtr->filename,"cust.txt");

By the way, sizeof(char) is always 1, so malloc(10) will do.
 
M

Martin Ambuhl

alij said:
Hi,

I have just started learning C and am working on pointers but am
having difficulty with the following:

If i have a struct, that includes a pointer to char (in my case, i've
named it filename), and in the main code, I want to use that pointer
to create a memory location and assign a character string.

I have gotten the following in the main code (structPtr is a pointer
to they type of struct i have created):

structPtr->filename = malloc(10 * sizeof(char));
^^^^^^^^^^^^^^
sizeof(char) is 1 by definition. The above is typing practice to no end.
How do I give a value, lets stay string value of "cust.txt" to this
field?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FIELDSIZE 10
#define FILENAME "cust.txt"

struct foo
{
char *filename;
};

int main(void)
{
struct foo thething, *structPtr = &thething;

if (!(structPtr->filename = malloc(FIELDSIZE))) {
printf("malloc failed. I quit!\n");
exit(EXIT_FAILURE);
}
if (strlen(FILENAME) >= FIELDSIZE) {
printf("\"" FILENAME "\" is too long. I quit!\n");
free(structPtr->filename);
exit(EXIT_FAILURE);
}
strcpy(structPtr->filename, FILENAME);
printf("structPtr->filename is \"%s\"\n"
" and thething.filename is \"%s\"\n",
structPtr->filename, thething.filename);
free(structPtr->filename);
return 0;
}


structPtr->filename is "cust.txt"
and thething.filename is "cust.txt"
 
T

Tobias Rischer

alij said:
I have gotten the following in the main code (structPtr is a pointer
to they type of struct i have created):

structPtr->filename = malloc(10 * sizeof(char));

How do I give a value, lets stay string value of "cust.txt" to this
field?

You need to copy the data from one place in memory (your "cust.txt" in
the code also ends up somewhere in memory) to another; the most normal
way is with the standard library function strcpy(), as in:

strcpy(structPtr->filename, "cust.txt");

But watch out that the string you are copying is not longer than the
place you have allocated (with room for the null-character that
terminates the string)! Otherwise you have a "buffer overflow" and will
destroy internal data structures and your program will most probably crash.

A function that is useful to avoid these problems is strncpy(), which
takes the maximal string length as extra argument.

Or you first find out how long the content is, and then allocate the
buffer space for it; this avoids artificial limits in the code. Like this:

/* imagine a more interesting way to get the content, it's an example */
const char* content = "cust.txt";
int n = strlen(content);
/* allocate memory for the string, plus 1 byte for termination */
structPtr->filename = malloc(n+1);
/* make sure we have the memory */
if (structPtr->filename == NULL)
exit(1); /* or some other way to give up */
/* copy the content */
strcpy(structPtr->filename, content);

Have fun,

Tobias
 
N

Nick Keighley

Tobias said:
alij wrote:

You need to copy the data from one place in memory (your "cust.txt" in
the code also ends up somewhere in memory) to another; the most normal
way is with the standard library function strcpy(), as in:

strcpy(structPtr->filename, "cust.txt");

But watch out that the string you are copying is not longer than the
place you have allocated (with room for the null-character that
terminates the string)! Otherwise you have a "buffer overflow" and will
destroy internal data structures and your program will most probably crash.

A function that is useful to avoid these problems is strncpy(), which
takes the maximal string length as extra argument.

the semantics of strncpy() are non-intuitive (it's broken). So
generally
*don't* use strncpy.

/* what is wrong with this? */
char sbuff[4];
strncpy(sbuff, "bomb", 4);
printf ("%s\n", buff);

/* how many characters are written to bbuff? */
char *bbuff [1000000];
strncpy(bbuff, "bomb", 1000000);

<snip>
 
N

Nick Keighley

Nick said:
Tobias said:
alij wrote:

You need to copy the data from one place in memory (your "cust.txt" in
the code also ends up somewhere in memory) to another; the most normal
way is with the standard library function strcpy(), as in:

strcpy(structPtr->filename, "cust.txt");

But watch out that the string you are copying is not longer than the
place you have allocated (with room for the null-character that
terminates the string)! Otherwise you have a "buffer overflow" and will
destroy internal data structures and your program will most probably crash.

A function that is useful to avoid these problems is strncpy(), which
takes the maximal string length as extra argument.

the semantics of strncpy() are non-intuitive (it's broken). So
generally
*don't* use strncpy.

/* what is wrong with this? */
char sbuff[4];
strncpy(sbuff, "bomb", 4);
printf ("%s\n", buff);

/* how many characters are written to bbuff? */
char *bbuff [1000000];

char bbuff [1000000];

how did that happen?
 
E

Ed Prochak

You need to copy the data from one place in memory (your "cust.txt" in
the code also ends up somewhere in memory) to another; the most normal
way is with the standard library function strcpy(), as in:
strcpy(structPtr->filename, "cust.txt");
But watch out that the string you are copying is not longer than the
place you have allocated (with room for the null-character that
terminates the string)! Otherwise you have a "buffer overflow" and will
destroy internal data structures and your program will most probably crash.
A function that is useful to avoid these problems is strncpy(), which
takes the maximal string length as extra argument.

the semantics of strncpy() are non-intuitive (it's broken). So
generally
*don't* use strncpy.

/* what is wrong with this? */
char sbuff[4];
strncpy(sbuff, "bomb", 4);
printf ("%s\n", buff);

/* how many characters are written to bbuff? */
char *bbuff [1000000];
strncpy(bbuff, "bomb", 1000000);

<snip>

neither of these seem to show strncpy() as broken. This is C
programming after all. Both examples are basically user error. Would
you also say a 1970's car is broken because it does not have ABS?

Ed
 
D

Doug

On Mar 20, 7:17 am, "Nick Keighley" <[email protected]>
wrote:

neither of these seem to show strncpy() as broken. This is C
programming after all. Both examples are basically user error. Would
you also say a 1970's car is broken because it does not have ABS?

I don't think he meant it literally, just that's it harder to use than
it should be.

You use the example of a 1970's car without ABS. I completely see
your point.

However, I think a better analogy is the good old vending machine
which labels BOTH rows and columns with numbers. People using the
machine who don't stop to think sometimes end up putting the price in
instead of the product identifier. (Maybe they're busy in their head
trying to figure out why strncpy doesn't do what they think it does!)

Now, the vending machine isn't 'broken'. But it's a silly design and
no one uses it. Pretty much all of them label one axis with a number
and the other with a letter. Thus, it's impossible to enter 59 pence
(or cents or whatever) and you generally end up with what you wanted.
Instead of something that's technically correct, but just likely to
piss you off.

I don't think strncpy is as bad as all that, but it's certainly not
'good' from the point of view of ease of use. It would not have been
difficult or performance-costly to have designed a sensible strncpy.
Oh well, eh?

Doug
 
B

Bill Pursell

the semantics of strncpy() are non-intuitive (it's broken). So
generally
*don't* use strncpy.

/* what is wrong with this? */
char sbuff[4];
strncpy(sbuff, "bomb", 4);
printf ("%s\n", buff);


There's nothing inherently wrong with that. It copies
4 characters into sbuff. It doesn't include a null,
so sbuff doesn't contain a proper string, but I don't
find that un-intuitive at all, quite the opposite.
Perhaps you think it would be better if the above
code made sbuff's first 4 entries be: 'b', 'o', 'm', '\0',
....but it doesn't.

/* how many characters are written to bbuff? */
char *bbuff [1000000];
strncpy(bbuff, "bomb", 1000000);

(ignoring the syntax error)...this copies 1000000
characters into bbuff. I don't see how this
is non-intuitive.

In each case, the number of characters written
is the 3rd argument, and those characters
match the values given in the 2nd argument.
It seems to me that mangling the semantics
to ensure that the result is a proper string
would be non-intuitive. What do you propose
would be better?
 
N

Nick Keighley

Bill said:
On Mar 20, 12:17 pm, "Nick Keighley"
the semantics of strncpy() are non-intuitive (it's broken). So
generally *don't* use strncpy.

/* what is wrong with this? */
char sbuff[4];
strncpy(sbuff, "bomb", 4);
printf ("%s\n", buff);


There's nothing inherently wrong with that.

true. It is well defined what it does.
It copies
4 characters into sbuff. It doesn't include a null,
so sbuff doesn't contain a proper string, but I don't
find that un-intuitive at all, quite the opposite.
Perhaps you think it would be better if the above
code made sbuff's first 4 entries be: 'b', 'o', 'm', '\0',
...but it doesn't.

I would prefer that. Perhaps my objection is its name.
Since it has "str" in its name and modifies a string
I think it would be reasonable to expect the resulting
char* to also be a string.
/* how many characters are written to bbuff? */
char bbuff [1000000];
strncpy(bbuff, "bomb", 1000000);

(ignoring the syntax error)...

I've fixed it (I hope!)
this copies 1000000
characters into bbuff. I don't see how this
is non-intuitive.

In each case, the number of characters written
is the 3rd argument, and those characters
match the values given in the 2nd argument.
It seems to me that mangling the semantics
to ensure that the result is a proper string
would be non-intuitive. What do you propose
would be better?

ones man's mangling is another man's intuitive semantics...

I'd prefer the result of the operation to always be a string.
No more characters copied than necessary to create a string
(like strcpy()).
And argument 3 to be the maximum number of chars written.

In other words I want a strcpy() with a limit on the number of
characters written.

Example one would write 4 characters and produce a string
of length 3.

Example two would write 5 characters and produce a string
of length 4.

I have never found a use for strncpy(). I have used a function
with the semantics above and found it useful.

I have seen strncpy misused many times (more often than not).
People often express surprise when I point out the actual
semantics of strncpy (perhaps I know too many people that
don't RTFM).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,121
Latest member
LowellMcGu
Top