Suppose the things passed to the method were:
array: [1,0,42,-1,2,666,-99,*,*,*] length: 7
(I've written * because it might be the case that you want to pass longer arrays and simply ignore the elements that come after the length). What you want to end up with is:
array: [1,0,42,2,666,*,*,*,*,*] length (returned): 5
Can you see that this would meet the requirements of the method? And now the tricky question: how
did you see that the array and its returned length are correct?
Eliminating the negative values and determining the new length is child's play. What is difficult is formulating a recipe with steps that are that comprehensive (nothing left out) and unambiguously simple - formulating and expressing
the recipe (algorithm) in words. Only once you have such a "plan of attack" can you begin to write code. And until you have expressed it all we have is a homework dump.
One starting point might be to maintain a "pointer" or index which you increment as you move down the array. In fact you might need two such pointers: one describing the position you are looking at and one describing the position in the array that things should be shifted to.
Take some numbers written on small pieces of paper and a line of empty squares representing array positions and play around with it. (Ie try the discard and shift operations you described) Aim to be conscious of the algorithm that you instinctively follow.
[Edit] Rereading my reply it occurs to me that a whiteboard might be a better place to experiment than numbers written on pieces of paper. The problem is that there are never any empty array slots - they always have something in them.
Given that one hand will hold the eraser and the other the whiteboard marker you soon find you have to enlist the help of an associate whose hands are free to point at where you got to with the eraser and where you are to write with the marker. In fact for really long arrays two friends will be needed: precisely the two pointers I suggested.