I remember trying to help fellow students with their C and C++ assignments back in undergrad, and reading some of their code I got the distinct feeling that most of it was “random-walked” code. Like they tried writing things that looked like C, making random, iterative changes until it compiled. Then once it compiled, made random, iterative changes until the output approached what the expected output would be. Sometimes the functionality ended up right, but with bizarre stuff like: unused variables all over the place, variables assigned then reassigned without using the first value, uses of pointer indirection that look like the student kept adding or removing asterisks until it didn’t crash, elaborate class hierarchies that went unused, etc. It’s like the Infinite Monkeys Eventually Producing Shakespeare thing but with programming assignments.
Oh c'mon, that's practically a right of passage when learning C or C++ for the first time, especially if you're new to programming as a whole :-)
The amount of students prevents us from real selection, instead we take exercises which failed tests (and that are not empty) and explain what was wrong, identify common mistakes or bad style and try to make it correct.
We had a very good feedback on this. And we saw an evolution in students' code. It was way better than trying to do collection of bad practice ...