
-----------------------------------
wtd
Mon Dec 11, 2006 11:40 pm

C TYS
-----------------------------------
Consider:

void strcpy(char *dest, char *src)
{
   while (*dest++ = *src++);
}

Implement the smallest change possible to this to get a function with the following signature.

void strcat(char *dest, char *src);

-----------------------------------
wtd
Mon Dec 11, 2006 11:45 pm


-----------------------------------
Extra kudos to the programmer who can explain the performance issue with repeated uses of the resulting strcat function, and how it can be remedied.

-----------------------------------
ericfourfour
Tue Dec 12, 2006 1:06 am


-----------------------------------
For the extra kudos:
"Because strcat does not check for sufficient space in strDestination before appending strSource, it is a potential cause of buffer overruns." (http://msdn2.microsoft.com/en-us/library/h1x0y282(VS.80).aspx)

If you want to avoid it, "Preventing buffer overruns is primarily about writing good code. Always validate all your inputs and fail gracefully when necessary."
I guess you should give the kudos to the person who understands what all of that means though. :D

-----------------------------------
wtd
Tue Dec 12, 2006 1:10 am


-----------------------------------
Not bad, but the problem I asked about was performance related.  :)

-----------------------------------
md
Tue Dec 12, 2006 2:12 am


-----------------------------------
As there really isn't any ways of checking that the character array is big enough before adding to it without changing the function to accept maximum lengths... you really have to ignore buffer overruns.

Oh, I know the answer; and I almost figured it out entirely on my own before giving in ask asking for the wtd's version :P

-----------------------------------
Monstrosity_
Tue Dec 12, 2006 12:03 pm


-----------------------------------
Extra kudos to the programmer who can explain the performance issue with repeated uses of the resulting strcat function, and how it can be remedied.
If you mean calling the function with the same 'dest' repeatedly, then the performance issue would be the need to traverse the character array (which would get increasingly larger with each call) looking for the null character. A way to avoid this is returning something meaningful.

-----------------------------------
wtd
Tue Dec 12, 2006 1:36 pm


-----------------------------------
What would be "meaningful"?  :)

-----------------------------------
md
Tue Dec 12, 2006 3:24 pm


-----------------------------------
The end of the character string after concatenation ;-)

-----------------------------------
Monstrosity_
Tue Dec 12, 2006 4:16 pm


-----------------------------------
What would be "meaningful"?  :)
Yes, I left that part vague for the same reason I didn't do the actual TYS. Which besides laziness, was that I'll leave it for someone else who wishes to test thier skills ;p. Also, I'm sure when people actually do write the code, they will be able to come up with some more (perhaps less important) performance issues. 

md gave a good meaningful return value, I can think of at least one more. Lets see what people can come up with...

-----------------------------------
[Gandalf]
Tue Dec 12, 2006 9:08 pm


-----------------------------------
My first, not so good, but working attempt:
void strcat(char *dest, char *src)
{
   int len = 0;
   while (*(dest+len++) != '\0');
   while (*(dest+++sizeof(char)*len-1) = *src++);
}
Please excuse the lack of whitespace.

-----------------------------------
wtd
Tue Dec 12, 2006 9:22 pm


-----------------------------------
Much simpler than that, Gandalf.  :)

Do you understand how the strcpy function works?

-----------------------------------
Andy
Tue Dec 12, 2006 9:28 pm


-----------------------------------
tsk tsk gandalf...


void strcat(char *dest, char *src)
{
    while (*dest++ = (*dest)?*dest:*src++);
}



for strings that do not end with a substring of 0s


void strcat(char *dest, char *src)
{
    while (*dest++ = (*dest) ? *dest: *((src+=1 + (*(dest+1)=0)) -1));
}


-----------------------------------
wtd
Tue Dec 12, 2006 10:16 pm


-----------------------------------
Simpler than that.  :P

-----------------------------------
Monstrosity_
Tue Dec 12, 2006 10:35 pm


-----------------------------------
Sorry guys, couldn't help myself :)

"]My first, not so good, but working attempt:
void strcat(char *dest, char *src)
{
   int len = 0;
   while (*(dest+len++) != '\0');
   while (*(dest+++sizeof(char)*len-1) = *src++);
}
Please excuse the lack of whitespace.

sizeof(char) == 1

tsk tsk gandalf...


void _strcat(char *dest, char *src)
{
    while (*dest++ = (*dest) ? *dest: *((src+=1 + (*(dest+1)=0)) -1));
}


I can't speak for C++, but in C we call this undefined behaviour. A variable can only be modified once in an expression.

-----------------------------------
Monstrosity_
Tue Dec 12, 2006 10:54 pm


-----------------------------------
uhg, is there no edit button or am I blind?

Anyway, I reread what I wrote and it's not that your modifying a variable twice, it's that your both modifying and reading a variable in the same expression. Sorry about that.

-----------------------------------
[Gandalf]
Tue Dec 12, 2006 11:02 pm


-----------------------------------
Nope, no edit button in help forums because it was abused.
Much simpler than that, Gandalf.  :)

Do you understand how the strcpy function works?
Well, I assumed so.  :P Even simpler than Andy's too?  Something with recursion maybe?

And yes, I'm quite confident in my understanding of your strcpy function.

-----------------------------------
md
Wed Dec 13, 2006 12:51 am


-----------------------------------

char *cat(char *dest, char *src)
{
    while( *dest ) dest++;
    while( *dest++ = *src++ ) ;
    return dest;
}


please excuse any typos... beer makes typing hard.

-----------------------------------
Andy
Wed Dec 13, 2006 5:44 am


-----------------------------------
ohh, multiple lines! lol. 

md, you cant return a pointer when your functions shifts it. but i'm sure that was just the beer thinking =P

-----------------------------------
bugzpodder
Wed Dec 13, 2006 9:29 am


-----------------------------------
tsk tsk gandalf...


void strcat(char *dest, char *src)
{
    while (*dest++ = (*dest)?*dest:*src++);
}




tsk tsk Andy...


while ((*d++) || *d = *s++);


-----------------------------------
Monstrosity_
Wed Dec 13, 2006 11:43 am


-----------------------------------
md, you cant return a pointer when your functions shifts it.
And why not?

-----------------------------------
md
Wed Dec 13, 2006 11:43 am


-----------------------------------
ohh, multiple lines! lol. 

md, you cant return a pointer when your functions shifts it. but i'm sure that was just the beer thinking =P

Sure you can! though it should really be return dest--;

I think bugzpodder's code is the shorted however...

-----------------------------------
wtd
Wed Dec 13, 2006 12:15 pm


-----------------------------------
I think bugzpodder's code is the shorted however...

And yet represents more of a change than the code I demonstrated to you.  ;)

-----------------------------------
bugzpodder
Wed Dec 13, 2006 12:44 pm


-----------------------------------
the correct code should actually be:
 And yet represents more of a change than the code I demonstrated to you.  What do you mean?

-----------------------------------
Monstrosity_
Wed Dec 13, 2006 1:00 pm


-----------------------------------
the correct code should actually be:

The grouping for those two is right to left, (*(++d)). If it were (++(*d)), where d gets dereferenced first then incremented, then your stuck in loop where the pointer never changes.

Also, your increments in both examples would skip assigning/checking to the first value in the array. Try with d as an empty string.

I think bugzpodder's code is the shorted however...
And yet represents more of a change than the code I demonstrated to you.  ;)
Hmm, I'm interested in what yours could be now. I would have just added another line to the strcpy function.

-----------------------------------
bugzpodder
Wed Dec 13, 2006 1:23 pm


-----------------------------------
I was too greedy. Tried to put everything in the conditional statement.


while(*d||(*d=*s++))d++;


Take that, punk!   :P

-----------------------------------
bugzpodder
Wed Dec 13, 2006 1:28 pm


-----------------------------------
and before anyone claims andy's code is shorter, both code sets has comparable character counts, and my code do |d| less assignments than andy's code

-----------------------------------
wtd
Wed Dec 13, 2006 1:33 pm


-----------------------------------
void strcat(char *dest, char *src)
{
   while (*dest) dest++;
   while (*dest++ = *src++);
}

This represents a very minimal change to the strcpy function as provided.

-----------------------------------
Monstrosity_
Wed Dec 13, 2006 1:40 pm


-----------------------------------
void strcat(char *dest, char *src)
{
   while (*dest) dest++;
   while (*dest++ = *src++);
}

This represents a very minimal change to the strcpy function as provided.


I would have done
void strcat(char *dest, char *src)
{
   dest += strlen(dest);
   while (*dest++ = *src++);
}
same deal, just function call over head ;p

-----------------------------------
bugzpodder
Wed Dec 13, 2006 1:44 pm


-----------------------------------
then you might as well use memcpy

-----------------------------------
wtd
Wed Dec 13, 2006 2:00 pm


-----------------------------------
void strcat(char *dest, char *src)
{
   dest += strlen(dest);
   while (*dest++ = *src++);
}

This actually won't work.  ;)

Anyone care to guess why?

-----------------------------------
md
Wed Dec 13, 2006 2:02 pm


-----------------------------------
I may have an issue with your code bugz (haven't tested it yet...) What if d has  non-zero characters after the first '\0'? seems like your code would consider that part of the string and not copy s over it as should happen.

/me also notes that the code he psoted was given by wtd... after much though and almost having the same thing by me

-----------------------------------
md
Wed Dec 13, 2006 2:21 pm


-----------------------------------
#include 
#include 

void cat(char *d, char*s) { 
while( *d || ( *d = *s++ ) ) 
	d++; 
}
 

main()
{     
	char dest

-----------------------------------
bugzpodder
Wed Dec 13, 2006 3:40 pm


-----------------------------------
my code is based on andy's and i believe he put a disclaimer up on this issue, which was known to me.  Note the "tsk tsk Andy"

-----------------------------------
bugzpodder
Wed Dec 13, 2006 4:14 pm


-----------------------------------
and heres a patched version md

while(*d||((*d=*s++) && !(*(d+1)=0)))d++; 

-----------------------------------
Andy
Wed Dec 13, 2006 4:46 pm


-----------------------------------
ohh, multiple lines! lol. 

md, you cant return a pointer when your functions shifts it. but i'm sure that was just the beer thinking =P

Sure you can! though it should really be return dest--;


err what? at the end of your function, dest is at the end of the string. without knowing how long the string is, you cant set it the pointer back to the beginning

-----------------------------------
Andy
Wed Dec 13, 2006 4:49 pm


-----------------------------------
void strcat(char *dest, char *src)
{
   dest += strlen(dest);
   while (*dest++ = *src++);
}

This actually won't work.  ;)

Anyone care to guess why?

works for me...

-----------------------------------
Monstrosity_
Wed Dec 13, 2006 5:10 pm


-----------------------------------
void strcat(char *dest, char *src)
{
   dest += strlen(dest);
   while (*dest++ = *src++);
}
This actually won't work.  ;)

Anyone care to guess why?
strlen is not declared. I figured that would be a given, but in all fairness this could cause trouble if you leave it up to the implicit function declaration.

-----------------------------------
Andy
Wed Dec 13, 2006 8:23 pm


-----------------------------------
oh! because if you include string.h, the function strcat with the same parameters would have existed already.

-----------------------------------
wtd
Wed Dec 13, 2006 8:25 pm


-----------------------------------
If you include string.h to get the strlen function, then you'd have mismatched types for strcat, as that is also present in string.h, but is not declared to return "void".  :)

-----------------------------------
Monstrosity_
Thu Dec 14, 2006 1:15 pm


-----------------------------------
If you include string.h to get the strlen function, then you'd have mismatched types for strcat, as that is also present in string.h, but is not declared to return "void".  :)
True, _IF_ you include string.h. The code I had pasted didn't, so all it's missing is a declaration for strlen. Which of course the easiest and most portable way is to include the header, but not the only way. :)

-----------------------------------
Monstrosity_
Thu Dec 14, 2006 1:20 pm


-----------------------------------
And if you want to be even more pedantic then you can say the code is undefined because it uses a reserved identifier, but then how fun would the problem be?
