C and strings

A

Anthony Irwin

Hi,

I am new to c and am having trouble with strings can anyone give me some
quick pointers or point me to a good c strings tutorial? Below is a
program I am working on.

Kind Regards,
Anthony Irwin

#include <stdio.h>

char teststring[40] = "test string now";
char teststring1[40];

int main() {
printf("teststring = %s", teststring);
strcpy(teststring1, teststring);
printf("\nteststring1 = %s", teststring1);

/* How can I assign a new value to teststring say
* the value "I changed string text" */

printf("\n\nI changed teststring to = %s\n", teststring);

return 0;
}
 
J

John

Hi,

I am new to c and am having trouble with strings can anyone give me some
quick pointers or point me to a good c strings tutorial? Below is a
program I am working on.

Kind Regards,
Anthony Irwin

#include <stdio.h>

char teststring[40] = "test string now";
char teststring1[40];

int main() {
printf("teststring = %s", teststring);
strcpy(teststring1, teststring);
printf("\nteststring1 = %s", teststring1);

/* How can I assign a new value to teststring say
* the value "I changed string text" */
/* What you mean? just call strcpy() again! */
strcpy(teststring, "I changed string text");
 
J

John Bode

Anthony said:
Hi,

I am new to c and am having trouble with strings can anyone give me some
quick pointers or point me to a good c strings tutorial? Below is a
program I am working on.

Kind Regards,
Anthony Irwin

#include <stdio.h>

char teststring[40] = "test string now";
char teststring1[40];

int main() {
printf("teststring = %s", teststring);
strcpy(teststring1, teststring);
printf("\nteststring1 = %s", teststring1);

/* How can I assign a new value to teststring say
* the value "I changed string text" */

printf("\n\nI changed teststring to = %s\n", teststring);

return 0;
}

strncpy(teststring, "I changed string text", sizeof teststring-1);

or

sprintf(teststring, "%.*s", sizeof teststring-1, "I changed string
text");

The conversion specifier "%.Ns" indicates that no more than N
characters should be written; for example, we could have written
"%.39s". Using * instead of a constant means that N is specified in
one of the arguments to printf() (in this case, by the expression
sizeof teststring-1).

The expression "sizeof teststring-1" gives the size of the destination
buffer, less one character for a 0 terminator, so in both cases, no
more than 39 characters are being written to teststring.
 
A

Anthony Irwin

Thanks for the reply guys. For some reason I thought you had to use
variables with strcpy.

Kind Regards,
Anthony Irwin
 
K

kernelxu

I agree with John.
using strncpy() is better than strcpy().

if teststring1 doesn't have enough room for the copied string , there
will be a overflow.
strncpy() reminds you pay attention to it.
 
K

Keith Thompson

I agree with John.
using strncpy() is better than strcpy().

if teststring1 doesn't have enough room for the copied string , there
will be a overflow.
strncpy() reminds you pay attention to it.

First, please provide some context when you post a followup. Search
for "google broken reply link" in this newsgroup for many many copies
of the same explanation.

Second, strncpy() isn't as superior to strcpy() as you might think.
It does let you limit the number of bytes to copy, but its behavior is
questionable in many cases. For example, if you do
strncpy(s, "hello", 5);
it will copy exactly 5 characters to s; it will *not* copy the
terminating '\0' character. On the other hand, if you do
strncpy(s, "hello", 500);
(assuming that s is big enough) it will pad the target with null
characters, wastefully writing 495 '\0' characters when one would have
been sufficient.

The strncpy() function, despite the name, doesn't consistently work
with C strings; it works with a specific data structure that's rarely
used these days, a '\0'-padded character array in which the trailing
'\0' is optional if the actual data fills the array. (This was used
by early versions of Unix to store file names, back when they were
limited to 14 characters.)

strcpy() is safe *if* you first confirm that the target is big enough
to hold the string being copied. strncpy() can avoid array overflow
bugs, but at the expense of introducing other problems.
 
B

bwaichu

If you are looking for safer, look at the strlcpy() over at openBSD or
write one like it.

Brian
 
J

John

Anthony said:
Hi,

I am new to c and am having trouble with strings can anyone give me some
quick pointers or point me to a good c strings tutorial? Below is a
program I am working on.

Kind Regards,
Anthony Irwin

#include <stdio.h>

char teststring[40] = "test string now";
char teststring1[40];

int main() {
printf("teststring = %s", teststring);
strcpy(teststring1, teststring);
printf("\nteststring1 = %s", teststring1);

/* How can I assign a new value to teststring say
* the value "I changed string text" */

printf("\n\nI changed teststring to = %s\n", teststring);

return 0;
}

strncpy(teststring, "I changed string text", sizeof teststring-1);
teststring[sizeof(teststring)-1] = '\0';
/* This is safe, if strncpy will use at most 40
characters from src string. the dest string will not be
null-terminated. */
 
A

Anthony Irwin

I agree with John.
using strncpy() is better than strcpy().

if teststring1 doesn't have enough room for the copied string , there
will be a overflow.
strncpy() reminds you pay attention to it.

Ok so I do the following:

strncpy(teststring, "I changed teststring value", sizeof teststring -1);

Will that put the null terminator on the string or should I do the
following:

strncpy(teststring, "I changed teststring value\0", sizeof teststring -1);


Thanks again for the replys.

Kind Regards,
Anthony Irwin
 
A

Anthony Irwin

On Thu, 11 Aug 2005 01:20:02 +0000, Keith Thompson wrote:

terminating '\0' character. On the other hand, if you do
strncpy(s, "hello", 500);
(assuming that s is big enough) it will pad the target with null
characters, wastefully writing 495 '\0' characters when one would have
been sufficient.

The strncpy() function, despite the name, doesn't consistently work
with C strings; it works with a specific data structure that's rarely
used these days, a '\0'-padded character array in which the trailing
'\0' is optional if the actual data fills the array. (This was used
by early versions of Unix to store file names, back when they were
limited to 14 characters.)

strcpy() is safe *if* you first confirm that the target is big enough
to hold the string being copied. strncpy() can avoid array overflow
bugs, but at the expense of introducing other problems.

Hi,

I don't understand how strncpy() can cause problems. I wrote a small test
app below and as far as I can tell the extra \0 null terminators don't
effect how the c code works.

It seems as though c stops looking past the first \0 it finds in the
string. Also it doesn't change strlen() or other functions I tested.

#include <stdio.h>

char teststring[40] = "test string now";
char teststring1[40];
char teststring2[20];

int main() {
printf("teststring = %s", teststring);
strcpy(teststring1, teststring);
printf("\nteststring1 = %s", teststring1);

strncpy(teststring, "I changed string value\0", sizeof teststring);
strcpy(teststring1, "I changed string value\0");
strcpy(teststring2, "test\0now");

printf("\n\nteststring now = %s", teststring);
printf("\n\nteststring1 now = %s", teststring1);
printf("\n\nteststring2 now = %s", teststring2);

printf("\n\nteststring size = %d", strlen(teststring));
printf("\n\nteststring1 size = %d", strlen(teststring1));

return 0;
}


Kind Regards,
Anthony Irwin
 
R

Rich Webb

Second, strncpy() isn't as superior to strcpy() as you might think.
It does let you limit the number of bytes to copy, but its behavior is
questionable in many cases. For example, if you do
strncpy(s, "hello", 5);
it will copy exactly 5 characters to s; it will *not* copy the
terminating '\0' character. On the other hand, if you do [snip...snip...]
strcpy() is safe *if* you first confirm that the target is big enough
to hold the string being copied. strncpy() can avoid array overflow
bugs, but at the expense of introducing other problems.

There's always the option of
strncpy(s, "hello", S_BUF_LEN)[S_BUF_LEN - 1] = '\0';

Ugly, but ...
 
P

pete

as far as I can tell the extra \0 null terminators don't
effect how the c code works.

That's right.
Keith Thompson's objection was to the wasted effort in writing them.
 
K

Keith Thompson

Anthony Irwin said:
On Thu, 11 Aug 2005 01:20:02 +0000, Keith Thompson wrote:



Hi,

I don't understand how strncpy() can cause problems. I wrote a small test
app below and as far as I can tell the extra \0 null terminators don't
effect how the c code works.

It seems as though c stops looking past the first \0 it finds in the
string. Also it doesn't change strlen() or other functions I tested.
[sample program snipped]

The problem with the extra '\0' bytes, as pete wrote in another
followup, is merely the wasted time spent writing them.

That's not a serious flaw unless the third argument is very large.
The more serious problem is one that your test program doesn't
illustrate. Consider this:

#include <stdio.h>
#include <string.h>
int main(void)
{
char buf[10] = "0123456789";
strncpy(buf, "hello", 5);
printf("buf = \"%s\"\n", buf);
return 0;
}

The output is:

buf = "hello56789"

If I had declared buf as an array of 5 characters, and used the 3rd
argument to strncpy() to avoid overflowing it, I would have been left
with no '\0' in the array. The printf() call most likely would have
kept printing characters until it happened to run into a '\0'
somewhere else (strictly speaking, it would invoke undefined behavior
as soon as it ran off the end of the array).

strcpy() is dangerous unless you first check that the target string is
big enough. strncpy() is dangerous unless you understand exactly how
it works -- and if you *think* you know how it works, you should
probably read the documentation one more time just to make sure.

It's easy to assume that strncpy is to strcpy as snprintf is to
sprintf, but it's not. snprintf takes an extra argument that
specifies the maximum number of characters to write to the target, but
it always writes the trailing '\0'.
 
M

Malcolm

Anthony Irwin said:
I am new to c and am having trouble with strings can anyone give me some
quick pointers or point me to a good c strings tutorial?
C strings are often confusing for people who come from another programming
language.

C is so low-level that effectively there is no such thing as a string type.
"strings" are sequences of chars terminated by a NUL (ASCII zero).

The only support C gives for strings in the strict sense of the word is that
entering a string literal
char *str = "Fred Bloggs";
creates the sequence 'F' 'r' 'e' 'd' ' ' 'B' 'l' 'o' 'g' 'g' 's' '\0'
in memory.

Also there are library functions which operate on such sequences.

The best tutorial on strings is to try to implement strlen(), strcpy() etc
yourself. call them my-strlen() etc to avoid namespace problems.

Below is a
program I am working on.

Kind Regards,
Anthony Irwin

#include <stdio.h>

char teststring[40] = "test string now";
char teststring1[40];

int main() {
printf("teststring = %s", teststring);
strcpy(teststring1, teststring);
printf("\nteststring1 = %s", teststring1);

/* How can I assign a new value to teststring say
* the value "I changed string text" */

printf("\n\nI changed teststring to = %s\n", teststring);

return 0;
}
 
K

Keith Thompson

Anthony Irwin said:
Ok so I do the following:

strncpy(teststring, "I changed teststring value", sizeof teststring -1);

Will that put the null terminator on the string

It will if there's enough room for it. If sizeof teststring - 1
happens to be 26 (the length of your string literal), strncpy() won't
write a '\0' to teststring.
or should I do the
following:

strncpy(teststring, "I changed teststring value\0", sizeof teststring -1);

No, that's equivalent. strncpy() treats its second argument as a
pointer to the first character of a string, i.e., as an array of
characters terminated by the first '\0' character. The string literals
"I changed teststring value"
and
"I changed teststring value\0"
specify different character array values, but they specify the same
string.

You want to copy a string into the variable teststring without
overflowing it. If you *know* that teststring is big enough to hold
the value you want to copy to it, just use strcpy(). If you don't
know this, you have to ask yourself what you want to do if there isn't
enough room. If strncpy's behavior matches what you need, then by all
means use it (and don't treat teststring as a string unless you're
sure it's properly terminated). If not, you'll have to do something
else.

Sometimes the hardest part of error handling is deciding what to do if
the error occurs. And once you've decided that, the error-handling
code can sometimes be more complex than the code that handles the
normal case.
 
P

Peter Nilsson

Malcolm said:
"strings" are sequences of chars terminated by a NUL (ASCII zero).

No, strings are sequences of characters terminated by a null (zero)
byte.

There is no requirement that ASCII be the basic or execution character
set
of any implementation. Of course, most are, but there is rarely any
reason
to write C programs that assumes this, even if you are writing a
program
that is not strictly conforming.
 
L

Lawrence Kirby

Second, strncpy() isn't as superior to strcpy() as you might think.
It does let you limit the number of bytes to copy, but its behavior is
questionable in many cases. For example, if you do
strncpy(s, "hello", 5);
it will copy exactly 5 characters to s; it will *not* copy the
terminating '\0' character. On the other hand, if you do [snip...snip...]
strcpy() is safe *if* you first confirm that the target is big enough
to hold the string being copied. strncpy() can avoid array overflow
bugs, but at the expense of introducing other problems.

There's always the option of
strncpy(s, "hello", S_BUF_LEN)[S_BUF_LEN - 1] = '\0';

The best advice is simply not to use strncpy(), it isn't a true string
handling function so don't try to use it as one. A far better function for
this is strncat()

s[0] = '\0';
strncat(s, "Hello", S_BUF_LEN-1);

and don't forget memcpy() which can sometimes be an appropriate
alternative. snprintf() is very powerful when you're building a string
from a number of parts:

snprintf(s, S_BUF_LEN, "%s %.*s", str1, maxlen, str2);

Lawrence
 
J

Joe Wright

Malcolm said:
C strings are often confusing for people who come from another programming
language.

C is so low-level that effectively there is no such thing as a string type.
"strings" are sequences of chars terminated by a NUL (ASCII zero).

The only support C gives for strings in the strict sense of the word is that
entering a string literal
char *str = "Fred Bloggs";
creates the sequence 'F' 'r' 'e' 'd' ' ' 'B' 'l' 'o' 'g' 'g' 's' '\0'
in memory.

Also there are library functions which operate on such sequences.

The best tutorial on strings is to try to implement strlen(), strcpy() etc
yourself. call them my-strlen() etc to avoid namespace problems.

I would avoid arithmetic operators in composing function names. It's
actually a syntax error. my_strlen() is much better.
Below is a
program I am working on.

Kind Regards,
Anthony Irwin

#include <stdio.h>

char teststring[40] = "test string now";
char teststring1[40];

int main() {
printf("teststring = %s", teststring);
strcpy(teststring1, teststring);
printf("\nteststring1 = %s", teststring1);

/* How can I assign a new value to teststring say
* the value "I changed string text" */

printf("\n\nI changed teststring to = %s\n", teststring);

return 0;
}
 

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
474,169
Messages
2,570,918
Members
47,458
Latest member
Chris#

Latest Threads

Top