By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,918 Members | 2,240 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,918 IT Pros & Developers. It's quick & easy.

A concatenation problem

P: n/a
The following is not working

int num = 0,
char *string;

string = "qwerty";
strcpy(string, num);
strcpy(string, ".png");
Nov 14 '05 #1
Share this Question
Share on Google+
24 Replies


P: n/a
Caroline <pl***@letsdothatagain.com> spoke thus:
The following is not working
Not really a surprise...
int num = 0,
char *string; string = "qwerty";
Fine and dandy, but...
strcpy(string, num);
....what is this? The prototype for strcpy is

char * strcpy( char * dst, const char * src );

What do you suppose happens when you pretend that num is a const char
*? It certainly has a very low probability of doing anything useful.
strcpy(string, ".png");


And likewise... string points to a string literal, which is not
guaranteed to be modifiable. strcpy'ing to it is certainly a bad
plan.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 14 '05 #2

P: n/a
"Caroline" <pl***@letsdothatagain.com> wrote in message
news:da**************************@posting.google.c om...
The following is not working

int num = 0,
char *string;

string = "qwerty";
strcpy(string, num);
strcpy(string, ".png");


1. Your string points to constant "qwerty". You cannot modify the contents
of a constant string.
2. strcpy(string, num) does not conform to the prototype of the function
strcpy(). It takes two pointers to char as arguments. You probably want
sprintf()
Nov 14 '05 #3

P: n/a
Caroline wrote:
The following is not working

int num = 0,
char *string;

string = "qwerty";
strcpy(string, num);
strcpy(string, ".png");


Nor should it be, for several reasons.

In your code, `string' points to a string literal ("qwerty"), which is
not modifiable.

The function strcpy() expects a (const) char * as its second argument,
where you have provided, `num', an int.

Even if your use had been correct, you'd be overwriting whatever
`string' points to, which is evidently not what you want.

Look up the function `sprintf()'. *That's* what you're looking for.

HTH,
--ag

BTW - the identifier `string' is reserved for the implementation.

--
--
Artie Gold -- Austin, Texas

Nov 14 '05 #4

P: n/a
On 29 Dec 2003 08:21:41 -0800, pl***@letsdothatagain.com (Caroline) wrote:
The following is not working

int num = 0,
char *string;

string = "qwerty";
string points to a constant character array.
strcpy(string, num);
1) num is an integer, and not elegable for copying to a string.
2) /if/ num were a character array, your strcpy() would attempt to
alter a constant character array, which is a violation of the C rules,
and would result in an error condition.
strcpy(string, ".png");


If this didn't have the same flaw as above (#2), it would copy the string ".png"
over top of the original contents of the array pointed to by string.

--
Lew Pitcher
IT Consultant, Enterprise Technology Solutions
Toronto Dominion Bank Financial Group

(Opinions expressed are my own, not my employers')
Nov 14 '05 #5

P: n/a

"Caroline" <pl***@letsdothatagain.com> wrote in message
news:da**************************@posting.google.c om...
The following is not working

int num = 0,
char *string;

string = "qwerty";
strcpy(string, num);
strcpy(string, ".png");


Besides all of the errors that have already been pointed out by everyone
else, you are also using strcpy() where you mean to use strcat().

Sean

Nov 14 '05 #6

P: n/a
Le*********@td.com (Lew Pitcher) writes:
On 29 Dec 2003 08:21:41 -0800, pl***@letsdothatagain.com (Caroline) wrote:
The following is not working

int num = 0,
char *string;

string = "qwerty";


string points to a constant character array.
strcpy(string, num);


1) num is an integer, and not elegable for copying to a string.
2) /if/ num were a character array, your strcpy() would attempt to
alter a constant character array, which is a violation of the C rules,
and would result in an error condition.


Strictly speaking, the character array isn't *necessarily* constant,
but you should always assume that it is. Attempting to modify it
causes undefined behavior (which, in the worst case, can look like
behaving just the way you want it to).

In my opinion, the language would be cleaner if it did define the
array to be constant, requiring a diagnostic if you attempt to modify
it, but the authors of the standard had to allow for existing
implementations that allow (the array allocated for) a string literal
to be modified.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)
Nov 14 '05 #7

P: n/a
"Sean Kenwrick" <sk*******@hotmail.com> writes:
"Caroline" <pl***@letsdothatagain.com> wrote in message
news:da**************************@posting.google.c om...
The following is not working

int num = 0,
char *string;

string = "qwerty";
strcpy(string, num);
strcpy(string, ".png");


Besides all of the errors that have already been pointed out by everyone
else, you are also using strcpy() where you mean to use strcat().


And if you could write to the array, and corrected the strcpy() to
strcat(), you'd still be writing past the end of the array.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)
Nov 14 '05 #8

P: n/a
Concatenating a string with an int with strcat is painful.

sprinf(string, "%*c%d", strlen(string), string, num);

should do it, right?

Greets.
Nov 14 '05 #9

P: n/a
"stau" <st**@pretogal.pt> wrote in message
news:pa****************************@pretogal.pt...
Concatenating a string with an int with strcat is painful.

sprinf(string, "%*c%d", strlen(string), string, num);

should do it, right?
In what context?

But let's have a look at your line again:
sprinf(string, "%*c%d", strlen(string), string, num);


For the moment, I assume that string is declared as char *, num as int and
that stdio.h and string.h are #included...

1. What is sprinf? I suppose you mean sprintf.
2. * in %*c expects an int in the parameter list. And what it gets? A
size_t.
3. c in %*c expects a char in the parameter list. And what iy gets? A char
*.
4. * in %*c specifies the width; if you mean what I think you mean, it has
no effect here

Using my crystal ball (beware, it may be broken!), I think that what you
want is something like this:

#include <stdio.h>

int main (void)
{
char filename[115]; /* Or suitably wide enough */
int number;

/* Assign number, let's say... */ number = 42;

sprintf(filename, "%s%d.%s", "prefix", number, "ext");

/* Use filename */
return 0;
}

Peter
Nov 14 '05 #10

P: n/a
stau wrote:
Concatenating a string with an int with strcat is painful.
Please quote some context so we know what you are talking about.

sprinf(string, "%*c%d", strlen(string), string, num);

should do it, right?


No way to know, without knowing something about what sprinf is.

If you meant sprintf, then no. string still points to something that is
not modifiable. Even if it where, there's not enough space for the
resulting string. If those were fixed, this would still be broken. At a
purely syntactic level, you have supplied incorrect types for the first
2 arguments. The '*' tells it to expect an int, but you provide a
size_t. %c expects an int, but you provide a char *.

As for the logic, it's completely wrong. %c prints a single character,
not a string. The width specifier just adds spaces.

It's not clear whether strlen(string) would be useful or well-defined
when 'string' is the destination buffer (depends on whether it contains
anything useful initially).

I doubt sprintf() is well-defined when the destination buffer is also
used as a source.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #11

P: n/a
Peter Pichler wrote:
3. c in %*c expects a char in the parameter list. And what iy gets? A char
*.
Actually it expects an int, which is converted to unsigned char.
4. * in %*c specifies the width; if you mean what I think you mean, it has
no effect here
Except that it will add spaces on the left if the provided width is more
than the number of characters to be printed (1 in this case).

Using my crystal ball (beware, it may be broken!), I think that what you
want is something like this:

#include <stdio.h>

int main (void)
{
char filename[115]; /* Or suitably wide enough */
int number;

/* Assign number, let's say... */ number = 42;

sprintf(filename, "%s%d.%s", "prefix", number, "ext");


You *could* do it something like this:

char *filename;
/* ... */

filename = malloc(strlen(prefix) + strlen(ext)
+ (sizeof(int) * CHAR_BIT + 2) / 3 + 1 + 1);
if (filename != NULL)
sprintf(filename, "%s%d.%s", prefix, number, ext);

assuming 'prefix' and 'ext' are strings. That way you'd be sure to have
enough space (if I got the calculation right).

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #12

P: n/a
On Mon, 29 Dec 2003 22:30:37 +0000, stau <st**@pretogal.pt> wrote in
comp.lang.c:
Concatenating a string with an int with strcat is painful.

sprinf(string, "%*c%d", strlen(string), string, num);

should do it, right?

Greets.


Assuming that you meant "sprintf"...

Absolutely not, even is string points to a large enough array of
writable characters. If there is an overlap between the destination
buffer passed to sprintf() and any source string, you produce
undefined behavior.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
Nov 14 '05 #13

P: n/a
Caroline wrote:

The following is not working

int num = 0,
char *string;

string = "qwerty";
strcpy(string, num);
strcpy(string, ".png");


Define "working". It certainly won't compile, and even if wrapped
in a main and some #includes it won't run.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Nov 14 '05 #14

P: n/a
stau <st**@pretogal.pt> writes:
Concatenating a string with an int with strcat is painful.

sprinf(string, "%*c%d", strlen(string), string, num);

should do it, right?


No, for reasons that others have satisfactorily explained.
However, the following will append a %d-formatted int to
`string':
sprintf (strchr (string, '\0'), "%d", num);
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Nov 14 '05 #15

P: n/a
On 29 Dec 2003 08:21:41 -0800, pl***@letsdothatagain.com (Caroline)
wrote:
The following is not working
Be thankful.

int num = 0,
char *string;

string = "qwerty";
string now points to the memory occupied by the string literal.
strcpy(string, num);
This attempts to copy data to the area pointed to by string.
Attempting to modify a string literal invokes undefined behavior.

You apparently did not #include string.h. If you had, your compiler
would have told you the second argument is invalid because strcpy
requires a char* and you used an int.

Assuming your compiler "did you a favor" and generated the code to
convert the int to a pointer, num has the value 0 so the pointer would
have the value NULL. Attempting to dereference a NULL pointer invokes
undefined behavior.
strcpy(string, ".png");


Had this worked, it would have overlaid the data copied in the
previous statement. Did you perhaps mean strcat to be consistent with
the title of your message? It still would invoke undefined behavior
but at least it would have done so while attempting to concatenate the
new data with the old.

<<Remove the del for email>>
Nov 14 '05 #16

P: n/a
On Mon, 29 Dec 2003 23:41:31 +0000, Kevin Goodsell wrote:
Peter Pichler wrote:

You *could* do it something like this:

char *filename;
/* ... */

filename = malloc(strlen(prefix) + strlen(ext)
+ (sizeof(int) * CHAR_BIT + 2) / 3 + 1 + 1);

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
god, what's this?

Thanks.

Nov 14 '05 #17

P: n/a

"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
"Sean Kenwrick" <sk*******@hotmail.com> writes:
"Caroline" <pl***@letsdothatagain.com> wrote in message
news:da**************************@posting.google.c om...
The following is not working

int num = 0,
char *string;

string = "qwerty";
strcpy(string, num);
strcpy(string, ".png");


Besides all of the errors that have already been pointed out by everyone
else, you are also using strcpy() where you mean to use strcat().


And if you could write to the array, and corrected the strcpy() to
strcat(), you'd still be writing past the end of the array.

I did say 'besides all the errors that have been pointed out by everyone
else'. There were about 10 other posts all pointing out the obvious
flaws in this code, but no-one had yet spotted that the OP was using
strcpy() instead of strcat() - which according to the subject of the post is
whart they were trying to do....

Sean
Nov 14 '05 #18

P: n/a
On Tue, 30 Dec 2003 08:57:20 +0000, stau <st**@pretogal.pt> wrote:
On Mon, 29 Dec 2003 23:41:31 +0000, Kevin Goodsell wrote:
Peter Pichler wrote:

You *could* do it something like this:

char *filename;
/* ... */

filename = malloc(strlen(prefix) + strlen(ext)
+ (sizeof(int) * CHAR_BIT + 2) / 3 + 1 + 1);

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
god, what's this?

Isn't it a (crude) worst case estimate of the maximum length needed to
hold the string representation of any possible integer? How big does
ch[] need to be for sprintf(ch, "%d", INT_MIN) to never overflow?
<<Remove the del for email>>
Nov 14 '05 #19

P: n/a
Barry Schwarz wrote:
On Tue, 30 Dec 2003 08:57:20 +0000, stau <st**@pretogal.pt> wrote:

On Mon, 29 Dec 2003 23:41:31 +0000, Kevin Goodsell wrote:
Peter Pichler wrote:

You *could* do it something like this:

char *filename;
/* ... */

filename = malloc(strlen(prefix) + strlen(ext)
+ (sizeof(int) * CHAR_BIT + 2) / 3 + 1 + 1);


^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
god, what's this?


Isn't it a (crude) worst case estimate of the maximum length needed to
hold the string representation of any possible integer? How big does
ch[] need to be for sprintf(ch, "%d", INT_MIN) to never overflow?


That is what the expression represents (though the two '+ 1's should
also be included - one reserves space for the null terminating
character, the other for a possible negative/minus sign).

The expression is taken from the FAQ for this group. You should be able,
with a bit of effort, to derive it yourself. The key point is that it
determines the maximum number of *octal* digits (and other characters)
needed for an int. The number of decimal (or hexadecimal) digits needed
is guaranteed to be no more than the number of octal digits needed.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #20

P: n/a
On Tue, 30 Dec 2003 08:57:20 +0000
stau <st**@pretogal.pt> wrote:
On Mon, 29 Dec 2003 23:41:31 +0000, Kevin Goodsell wrote:
Peter Pichler wrote:

You *could* do it something like this:

char *filename;
/* ... */

filename = malloc(strlen(prefix) + strlen(ext)
+ (sizeof(int) * CHAR_BIT + 2) / 3 + 1 + 1);

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
god, what's this?


An overestimate of the number of characters required to print an
integer.

sizeof(int) * CHAR_BIT == the number of bits used to store an integer

With 3 bits you can represent integers 0-7, so assuming 3 bits per
printed digit is a slight overestimate.

+2 before dividing by 3 so make sure any odd bits count as a digit to be
printed.
--
Flash Gordon
Paid to be a Geek & a Senior Software Developer
Although my email address says spam, it is real and I read it.
Nov 14 '05 #21

P: n/a
Thank you all for your help.
The following gave me the result I wanted on the first iteration:
char *nameOfFile;
char *ext ;
char *prefix;
sprintf(nameOfFile, "%s%d.%s", prefix, Comp, ext);

"Peter Pichler" <pi*****@pobox.sk> wrote in message news:<3f**********@mk-nntp-2.news.uk.tiscali.com>...
...

Using my crystal ball (beware, it may be broken!), I think that what you
want is something like this:

#include <stdio.h>

int main (void)
{
char filename[115]; /* Or suitably wide enough */
int number;

/* Assign number, let's say... */ number = 42;

sprintf(filename, "%s%d.%s", "prefix", number, "ext");

/* Use filename */
return 0;
}

Peter

Nov 14 '05 #22

P: n/a
Thank you all for your help.
The following gave me the result I wanted on the first iteration:
char *nameOfFile;
char *ext ;
char *prefix;

nameOfFile ="";
sprintf(nameOfFile, "%s%d.%s", prefix, SomeNumber, ext);
....
but when I the function executed again, similar results appeared.

1 - How can I reset the variables at each iteration?
2 - How (and why) would MALLOC be used in this case?
"Peter Pichler" <pi*****@pobox.sk> wrote in message news:<3f**********@mk-nntp-2.news.uk.tiscali.com>...
...

Using my crystal ball (beware, it may be broken!), I think that what you
want is something like this:

#include <stdio.h>

int main (void)
{
char filename[115]; /* Or suitably wide enough */
int number;

/* Assign number, let's say... */ number = 42;

sprintf(filename, "%s%d.%s", "prefix", number, "ext");

/* Use filename */
return 0;
}

Peter

Nov 14 '05 #23

P: n/a
Caroline wrote:
Thank you all for your help.
Please stop top-posting. It's rude.
The following gave me the result I wanted on the first iteration:
char *nameOfFile;
char *ext ;
char *prefix;

nameOfFile ="";
This spells trouble later on. You should never assign a string literal
to a (non-const) pointer. String literals may not be modified, so you
should *only* use const pointers to point to a string literal.
sprintf(nameOfFile, "%s%d.%s", prefix, SomeNumber, ext);
This is a serious error that will be caught by the compiler if you
follow my advice above. nameOfFile points to a string literal, so you
are attempting to write your output over that string literal. This gives
undefined behavior. Even if string literals happen to be modifiable on
your implementation, you'll probably write past the end of the array.
...
but when I the function executed again, similar results appeared.

1 - How can I reset the variables at each iteration?
I don't know what you mean by that.
2 - How (and why) would MALLOC be used in this case?


malloc() is really only used in one way - it is called to allocate a
chunk of memory. The reason you might want to do that is because you
might only be able to determine how much memory you need at run-time
(not at compile-time).

You need an array to store the sprintf output into. You are currently
trying to use a string literal, which is not appropriate. You could
declare your array like this:

char nameOfFile[N];

But in order to do so you need to know an appropriate value for N when
you write the source. If you *don't* know how large the array needs to
be, but you can calculate it at run-time, you can do this instead:

char *nameOfFile;
size_t nameLength = /* calculate length here */;

nameOfFile = malloc(nameLength * sizeof(*nameOfFile));
if (nameOfFile != NULL)
{
sprintf(nameOfFile, "%s%d.%s", prefix, SomeNumber, ext);
}
else
{
/* handle allocation error */
}

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Nov 14 '05 #24

P: n/a
"Caroline" <pl***@letsdothatagain.com> wrote...
Thank you all for your help.

Caroline,

Please learn to post properly, starting with writing your post *below* the
post you are replying to and snipping the stuff that is not relevant.

Fortunately, nothing of that applies here because your post makes sense on
its own ;-)
The following gave me the result I wanted on the first iteration:
char *nameOfFile;
char *ext ;
char *prefix;

nameOfFile ="";
sprintf(nameOfFile, "%s%d.%s", prefix, SomeNumber, ext);
If this worked, then only purely by accident. You are causing an undefined
behaviour twice here:
1. by ovewriting a string literal ""
2. by writing beyond the space allocated for it
Please read on...
...
but when I the function executed again, similar results appeared.

1 - How can I reset the variables at each iteration?
What do you mean by "reset the variables?" If you want a new string, just
use new values.
2 - How (and why) would MALLOC be used in this case?


Hurray! I'm glad you've asked.

You need a space to write your string to. Your string (filename) will be N
bytes long, where N is strlen(prefix) + number of digits in your number + 1
for the dot + strlen(ext). You will need N+1 bytes for your string, the +1
is for a terminating 0. How you make that space is not important, you may
have an array declared somewhere, but in many cases you use malloc() to make
the space.

Peter
Nov 14 '05 #25

This discussion thread is closed

Replies have been disabled for this discussion.