• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Problems with strcat

 
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Using gcc-5.3.1-2.fc23.x86_64 on Fedora 23.

pluma catenate.c &
[1] 16640
[critchie@AsusCRitchie CPrograms]$ gcc -o catenate catenate.c
[critchie@AsusCRitchie CPrograms]$ ./catenate Campbell Ritchie
Original a1 = "CampbellRitchie"
Original a2 = "itchie"
Catenated = "CampbellRitchie"
Later a1 = "CampbellRitchie"
Original a2 = "itchie"

Now, I notice that the catenated version of *(argv + 1) is being used for the first printout; presumably if I broke that printf instruction in two it would print "Campbell". It took me a bit to work out that strcat alters the state of its left argument, so it becomes the same as the catenated version. But what has happened to the R? Why have I become a mouse on The Simpsons after catentation? That doesn't seem to be how strcat should work. Reinstalling gcc made no difference.
 
Ranch Hand
Posts: 165
12
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
On entry to your main function the argv input buffer contains the following (where # represents null):-

0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
.|/|c|a|t|e|n|a|t|e|#|C|a|m|p|b|e|l|l|#|R|i|t|c|h|i|e|#|


argv[1] points to C at index [11]
argv[2] points to R at index [20]

Recall that strcat concats the p2 string to the end of p1 string IN PLACE, it does not create a new string like java would.
The strcat is executed before the printf (as its an argument its value is needed) . Thus it concats "Ritchie" to the position of the null at end of "Campbell" which therefore overwrites your input buffer, giving this:-

0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
.|/|c|a|t|e|n|a|t|e|#|C|a|m|p|b|e|l|l|R|i|t|c|h|i|e|#|#|


argv[2] still points to index [20] so the string at argv[2] now says "itchie".
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you. So if I copied the (argv + 2) string into another String with malloc and strcopy, that wouldn't apply? Let's try it out.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you Copying the *(argv + 2) to another char * sorted out that problem.

gcc -o catenate catenate.c
[critchie@AsusCRitchie CPrograms]$ ./catenate Campbell Ritchie
Original a1 = "CampbellRitchie"
Original a2 = "Ritchie"
Catenated = "CampbellRitchie"
Later a1 = "CampbellRitchie"
Original a2 = "Ritchie"

I know sizeof(char) is redundant because it returns 1.
 
Steffe Wilson
Ranch Hand
Posts: 165
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, copying arv[2] to a separate string does the trick at least in terms of avoiding the side-effect of (apparently) losing the 'R', as you have seen. But note that the oringinal input buffer still gets changed. You have still lost forever the original value of argv[1] because it now points to the concatenated value.

I would be inclined to preserve the original input buffer contents in case needed in the future. I would create a custom buffer for the concatenated string (big enough to accommodate both arv[1] plus argv[2] plus null. Then strcpy argv[1] into it and strcat argv[2] to the end of it.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you
 
Steffe Wilson
Ranch Hand
Posts: 165
12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Most welcome Campbell. I haven't written any C for quite a while, pleased I actually remember some of it! Cheers for the cow
 
Greenhorn
Posts: 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
it use for string concat
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Welcome to the Ranch

Do you have any more information? Or do you wish to ask another question?
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic