Whilst scanning my C programming textbook, I saw this practice problem from a very early chapter:
I got to thinking that the problem probably wants you to draw each shape separately, which would be very easy.
But to do literally what the question asks (print them on the same line), I couldn't see any easy way! The rectangle is 9x9, but they seem 5 spaces apart, the oval is 7 wide, the arrow tip is 5x3, etc. Maybe if the arrow had tips on both ends, I could dissect the whole picture horizontally.
After dabbling with ways to produce the rectangle, oval, arrow, and diamond by themselves, and then to somehow print each row correctly with loops and if
s, I realized maybe I should just draw it literally.
#include <stdio.h>
int main() {
puts("********* *** * *");
puts("* * * * *** * *");
puts("* * * * ***** * *");
puts("* * * * * * *");
puts("* * * * * * *");
puts("* * * * * * *");
puts("* * * * * * *");
puts("* * * * * * *");
puts("********* *** * *");
return 0;
}
I could have put it all in one puts
with newlines but I found that was pretty unreadable.
Is there any better way to do this? Am I completely missing something / am I doing it in the most efficient way?
-
\$\begingroup\$ The question asks to "print the following shapes", it doesn't say anything about them having to be on the same line. \$\endgroup\$Mat– Mat2016年01月14日 06:40:27 +00:00Commented Jan 14, 2016 at 6:40
-
\$\begingroup\$ @Mat The example output has them on the same line, so if you follow the problem literally and also based on other problems in the book, you should print them on the same line. I think you're right though, they should be done separately, but as I said that'd be too easy :P \$\endgroup\$Insane– Insane2016年01月14日 06:44:13 +00:00Commented Jan 14, 2016 at 6:44
-
\$\begingroup\$ Did you consider to use a bitmap (an array of 64 bit integers where each bit is a column and each item is a row of your output? 1 for asterisk and 0 for space). Less readable to write (unless you can use 0b notation) but more compact and reusable. \$\endgroup\$Adriano Repetti– Adriano Repetti2016年01月14日 08:11:06 +00:00Commented Jan 14, 2016 at 8:11
2 Answers 2
It really is that simple. Your idea of putting everything into one puts()
call would be an improvement, because I/O calls are relatively expensive. Not that it really matters in this exercise. It's just a good habit.
The second shape should be a little bit wider. =)
Note that a return 0;
at the end of main()
is automatically implied, as a special case.
#include <stdio.h>
int main() {
puts("********* *** * *\n"
"* * * * *** * *\n"
"* * * * ***** * *\n"
"* * * * * * *\n"
"* * * * * * *\n"
"* * * * * * *\n"
"* * * * * * *\n"
"* * * * * * *\n"
"********* *** * *");
return 0;
}
-
\$\begingroup\$ Ah, didn't know you could split it up like that. +1 \$\endgroup\$Insane– Insane2016年01月14日 21:37:56 +00:00Commented Jan 14, 2016 at 21:37
-
\$\begingroup\$ @SirPython (1) I mentioned that it's optional, but I wouldn't necessarily drop
return 0
if it's already written. (2)#include <stdio.h>
should be there, at least on OS X and Linux. \$\endgroup\$200_success– 200_success2016年01月14日 23:43:25 +00:00Commented Jan 14, 2016 at 23:43
You're not really asking for a code review here; you're more like asking the community how they would write the code for this problem. So, not really on-topic.
However, here's a hint (partial answer) for you.
Consider each of the four shapes in isolation. Write four functions, one per shape, each taking an int
parameter that indicates which of the 9 lines (top to bottom) the function should be outputting. For example:
#include <stdio.h>
void square(int line)
{
if (line == 0 || line == 8) {
printf("*********\n");
} else {
printf("* *\n");
}
}
void arrow(int line)
{
if (line == 1) {
printf(" *** \n");
} else if (line == 2) {
printf(" ***** \n");
} else {
printf(" * \n");
}
}
int main()
{
for (int i=0; i < 9; ++i) {
square(i);
}
for (int i=0; i < 9; ++i) {
arrow(i);
}
}
Compile and run that program. Look at its output. Then, make a relatively small modification to the program so that it outputs the square and the arrow side-by-side instead of one-above-the-other.
Then, add the circle and the diamond.
-
\$\begingroup\$ Yes, this is actually exactly what I was doing before! I'm happy I'm not the only one who thought to do it like that. +1 \$\endgroup\$Insane– Insane2016年01月14日 21:37:14 +00:00Commented Jan 14, 2016 at 21:37
-
\$\begingroup\$ FYI, the "small modification" I had in mind is to remove the
\n
s, move the call toarrow(i)
into the firstfor
loop inmain()
, and get rid of the secondfor
loop. \$\endgroup\$Quuxplusone– Quuxplusone2016年01月16日 22:13:36 +00:00Commented Jan 16, 2016 at 22:13