Because the resulting string will only be shorter (never longer), this works. You simply keep track of where you're copying to and where you're copying from, and move character by character until you reach the end. The resulting string may have extra stuff at the end, but since it's null terminated the standard C string functions will not see that cruft as they will stop at the first null.
Some people allocated memory, copied out the input, then put back the bits they wanted to keep. That is not "in place".
The main point of the whole exercise is to see if the candidate can write any code - anything after that is a bonus.
Now if the input and output of a function are correct I think you where simply less clear than you may have thought. If you had said "string in place (don't allocate any memory)," I suspect far more people would have given you the output you wanted.
As it says elsewhere, the purpose is to get some code, then use it as a start for the discussion. If someone allocates memory then that's where I start. In that case they clearly they don't understand the usual meaning of the expression "in-place."
> If you had said "string in place (don't allocate
> any memory)," I suspect far more people would have
> given you the output you wanted.
I suspect you're wrong, and I would be interested to see if anyone else comments on that point. I got nearly 100 submissions, and only one (from memory) allocated memory. All the others did the modification "in-place" as requested.I would have done it in place because that was the simplest approach and not doing so would have been silly. However, just because it seems that way to us does not mean everyone knew you required more than just output in that fashion.
Anyway, I was more commenting on the style where you mix the requirements for an interface with the requirements for the algorithm. IMO "I need a function / API that does X efficiently" is much better than saying "does X using hash tables". AKA, if you don’t' want someone to use malloc then you can say so, but giving the reasons why you don't want malloc is more useful.
PS: It’s really a minor point and I thank you for doing this bit of research. I was simply trying to help you communicate in a more clear fashion.
Firstly, thanks for being constructive. Your points are noted, although I don't necessarily agree with all of them.
To me, "some people" does not imply strictly more than one. That's possibly a mathematician thing.
But the point about mixing implementation detail and interface requirements, this is normal in much of the coding I do. I'm often working in a constrained environment, and performance requirements are very much a part of the specification. Stating that something must happen "in place" is a common requirement for me, and goes beyond saying "must not malloc" or whatever. More, it's having someone being able to cope with the mix that I was, in part, looking for.
I'm also well aware that many of the people here on HN do big machine programming, or web programming, and aren't accustomed to constrained programming. That's partly why I chose this particular question. My next challenge won't have that sort of constraint, and will be more in line with your comments. (Yes, sucker that I am, I'm planning another small exercise by way of comparison/contrast).
And again, these are the sorts of questions that I would expect to discuss during the de-brief. The very fact that you bring them up at all means you are in the top 0.01% of programmers (for some value of 0.01).
But z_terminated is a pointer to a lump of memory that contains bytes. In that context "in-place" means that you move things around in the lump of memory you are given (the one pointed to by z_terminated) rather than allocating some more memory and using that.
If I'm right, your misconception is by no means unique, but it's a dangerous one that shows that you don't understand what's going on in C with regards pointers, memory and strings.
If I'm wrong then I apologise.
This is also why quicksort is considered to take up log(n) space: it calls itself recursively, and thus uses up a bit of the stack for each recursive call.