• ベストアンサー

課題なんですが・・・

プログラムが書いてあるため非常に長文です。 お許しください。 いま、C++でのプログラミング課題が出ているのですが、 正方形の中抜きは出来たのですが、三角形・逆三角形の中抜きが作れません・・・。 もちろん、宿題・課題の丸投げは禁止されているのは分かっています。 しかし、一向に進まないのでなにかヒントだけでも(できたら答えも・・・というのは冗談です)教えていただけないでしょうか。 ちなみに問題は、入力数分の縦×横の図形を描くプログラムを組む。 というものです。 #include <stdio.h> void main (void) { /*変数の宣言*/ int cnt1, cnt2,n; /*数字の入力*/ do { printf("数字2~19を入力してください:"); scanf("%d",&n); if(n<2 || n>19) { printf("入力エラーです!!\nもう一度"); } }while(n<2 || n>19); /*正方形の作成*/ printf("\n正方形\n"); for(cnt1=0;cnt1<n;cnt1++) { for(cnt2=1;cnt2<=n;cnt2++) { printf("*"); } printf("\n"); }   printf("\n三角形\n"); for(cnt1=1;cnt1<=n;cnt1++) { for(cnt2=0;cnt2<cnt1;cnt2++) { printf("*"); } printf("\n"); } printf("\n逆三角形\n"); for(cnt1=1;cnt1<=n;cnt1++) { for(cnt2=n;cnt2>=cnt1;cnt2--) { printf("*"); } printf("\n"); } printf("\n三角旗\n"); for(cnt1=1;cnt1<=n;cnt1++) { for(cnt2=0;cnt2<cnt1;cnt2++) { printf("*"); } printf("\n"); } for(cnt1=n-1;cnt1>=0;cnt1--) { for(cnt2=0;cnt2<cnt1;cnt2++) { printf("*"); } printf("\n"); } printf("\nダイヤ形\n"); for(cnt1=1;cnt1<=n;cnt1++) { for(cnt2=1;cnt2<=n*2;cnt2++) { if(cnt2<=n-cnt1 || cnt2>=n+cnt1) { printf(" "); } else { printf("*"); } } printf("\n"); } for(cnt1=n-1;cnt1>0;cnt1--) { for(cnt2=1;cnt2<=n*2;cnt2++) { if(cnt2<=n-cnt1 || cnt2>=n+cnt1) { printf(" "); } else { printf("*"); } } printf("\n"); } printf("\n中抜き正方形\n"); for(cnt1=1;cnt1<=n;cnt1++) { if(cnt1==1 || cnt1==n) { for(cnt2=1;cnt2<=n;cnt2++) { printf("*"); } } else for(cnt2=1;cnt2<=n;cnt2++) { if(cnt2==1 || cnt2==n) { printf("*"); } else { printf(" "); } } printf("\n"); } rewind(stdin); getchar(); }

質問者が選んだベストアンサー

  • ベストアンサー
  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.12

> かなり高度なものだと思うのですが・・・ まったく通常レベルのものだと思いますけど。。。^^; > 質問欄にある形式(構文)のみで組むことは出来ませんか? 組むことはできるでしょうね^^ 関数呼び出しもダメ、if/while/for だけしか使うな、とか無意味、というより害があると思いますよ(笑) でもまあ、課題をクリアして、学校を信じてがんばってください。

tatsunami
質問者

お礼

ありがとうございます。 そうですね、学校、先生を信じて頑張ってみます。

その他の回答 (11)

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.11

void skipws(void) の名前の付け方がおかしいですね。 void skipline(void) に変えたほうがいいかも^^;

tatsunami
質問者

補足

ご回答ありがとうございます。 遅くなり申し訳ありません。 いろいろと教えていただきありがとうございます。 しかし、mikaemiさまの教えてくださったプログラムは かなり高度なものだと思うのですが・・・ 今ある技術のみで制作しないといけないので、 質問欄にある形式(構文)のみで組むことは出来ませんか? お手数をおかけして申し訳ありません。

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.10

あぁそうか。。  N = n % 2 ? n : 2 * n - 1; とかも、使ってはいけないのかな?^^ 以下の if 文と同じ意味です。 if (n % 2) N = n; /* n が奇数 */ else N = 2 * n - 1; /* n が偶数 */

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.9

あっ、C99 じゃないかもしれないので、変数宣言はブロックの先頭でしておいたほうが無難でしたね。 === #include <stdio.h> /* static const char asterisk[] = "*"; */ static const char asterisk[] = "*"; /* static const char space[] = " "; */ static const char space[] = " "; void skipws(void) { int c; while ((c = getchar()) != EOF) if (c == '\n') break; } int main (void) { // 数字の入力 int n, row, col, N; while (1) { fputs("数字2~19を入力してください:", stderr); if (scanf("%d", &n) != 1 || n < 2 || n > 19) { skipws(); fputs("入力エラーです!!\nもう一度", stderr); continue; } break; } // 正方形の作成 puts("\n正方形"); for (row = 0; row < n; ++row) { for (col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); } // 直角三角形の作成 puts("\n三角形"); for (row = 0; row < n; ++row) { for (col = 0; col <= row; ++col) fputs(asterisk, stdout); putchar('\n'); } // 逆直角三角形の作成 puts("\n逆三角形"); for (row = 0; row < n; ++row) { for (col = 0; col < n - row; ++col) fputs(asterisk, stdout); putchar('\n'); } // 三角旗の作成 puts("\n三角旗"); N = n % 2 ? n : 2 * n - 1; for (row = 0; row < N / 2 + 1; ++row) { for (col = 0; col < 2 * row + 1; ++col) fputs(asterisk, stdout); putchar('\n'); } for (row = N / 2 - 1; row >= 0; --row) { for (col = 0; col < 2 * row + 1; ++col) fputs(asterisk, stdout); putchar('\n'); } // ダイヤ形の作成 puts("\nダイヤ形"); N = n % 2 ? n : 2 * n - 1; for (row = 0; row < N / 2 + 1; ++row) { for (col = 0; col < (N - (2 * row + 1)) / 2; ++col) fputs(space, stdout); for (col = 0; col < 2 * row + 1; ++col) fputs(asterisk, stdout); putchar('\n'); } for (row = N / 2 - 1; row >= 0; --row) { for (col = 0; col < (N - (2 * row + 1)) / 2; ++col) fputs(space, stdout); for (col = 0; col < 2 * row + 1; ++col) fputs(asterisk, stdout); putchar('\n'); } /// 中抜き正方形を作成 puts("\n中抜き正方形"); for (col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); for (row = 1; row < n - 1; ++row) { fputs(asterisk, stdout); for (col = 1; col < n - 1; ++col) fputs(space, stdout); puts(asterisk); } for (col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); // 中抜き直角三角形の作成 puts("\n三角形"); for (row = 0; row < n - 1; ++row) { fputs(asterisk, stdout); for (col = 1; col < row; ++col) fputs(space, stdout); if (row != 0) fputs(asterisk, stdout); putchar('\n'); } for (col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); // 中抜き逆直角三角形の作成 puts("\n逆三角形"); for (col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); for (row = n - 2; row >= 0; --row) { fputs(asterisk, stdout); for (col = 1; col < row; ++col) fputs(space, stdout); if (row != 0) fputs(asterisk, stdout); putchar('\n'); } return 0; }

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.8

> 学校でならっている構文(?)が質問にあるようなもの… C++ と書いていたので、iostream を使ったんですが^^; C++ じゃなくて、C なんですね。 > 偶数の場合は、上半分を入力数値で、下半分を入力数値-1で出力… なるほど。じゃあ、以下のようになりますかね?^^ ==== #include <stdio.h> /* static const char asterisk[] = "*"; */ static const char asterisk[] = "*"; /* static const char space[] = " "; */ static const char space[] = " "; /* 残りの行をスキップ */ void skipws(void) { int c; while ((c = getchar()) != EOF) if (c == '\n') break; } int main (void) { // 数字の入力 int n, N; while (1) { fputs("数字2~19を入力してください:", stderr); if (scanf("%d", &n) != 1 || n < 2 || n > 19) { skipws(); fputs("入力エラーです!!\nもう一度", stderr); continue; } break; } // 正方形の作成 puts("\n正方形"); for (int row = 0; row < n; ++row) { for (int col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); } // 直角三角形の作成 puts("\n三角形"); for (int row = 0; row < n; ++row) { for (int col = 0; col <= row; ++col) fputs(asterisk, stdout); putchar('\n'); } // 逆直角三角形の作成 puts("\n逆三角形"); for (int row = 0; row < n; ++row) { for (int col = 0; col < n - row; ++col) fputs(asterisk, stdout); putchar('\n'); } // 三角旗の作成 puts("\n三角旗"); N = n % 2 ? n : 2 * n - 1; for (int row = 0; row < N / 2 + 1; ++row) { for (int col = 0; col < 2 * row + 1; ++col) fputs(asterisk, stdout); putchar('\n'); } for (int row = N / 2 - 1; row >= 0; --row) { for (int col = 0; col < 2 * row + 1; ++col) fputs(asterisk, stdout); putchar('\n'); } // ダイヤ形の作成 puts("\nダイヤ形"); N = n % 2 ? n : 2 * n - 1; for (int row = 0; row < N / 2 + 1; ++row) { for (int col = 0; col < (N - (2 * row + 1)) / 2; ++col) fputs(space, stdout); for (int col = 0; col < 2 * row + 1; ++col) fputs(asterisk, stdout); putchar('\n'); } for (int row = N / 2 - 1; row >= 0; --row) { for (int col = 0; col < (N - (2 * row + 1)) / 2; ++col) fputs(space, stdout); for (int col = 0; col < 2 * row + 1; ++col) fputs(asterisk, stdout); putchar('\n'); } /// 中抜き正方形を作成 puts("\n中抜き正方形"); for (int col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); for (int row = 1; row < n - 1; ++row) { fputs(asterisk, stdout); for (int col = 1; col < n - 1; ++col) fputs(space, stdout); puts(asterisk); } for (int col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); // 中抜き直角三角形の作成 puts("\n三角形"); for (int row = 0; row < n - 1; ++row) { fputs(asterisk, stdout); for (int col = 1; col < row; ++col) fputs(space, stdout); if (row != 0) fputs(asterisk, stdout); putchar('\n'); } for (int col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); // 中抜き逆直角三角形の作成 puts("\n逆三角形"); for (int col = 0; col < n; ++col) fputs(asterisk, stdout); putchar('\n'); for (int row = n - 2; row >= 0; --row) { fputs(asterisk, stdout); for (int col = 1; col < row; ++col) fputs(space, stdout); if (row != 0) fputs(asterisk, stdout); putchar('\n'); } return 0; }

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.7

printf("中抜き三角"); for ( cnt1=0; cnt1 < n; cnt1++ ) {   for( cnt2=0; cnt2 < cnt1+1; cnt2++ ) {     /* cnt2ループの* 出力は       初期値 ... cnt2が 0       終了値 ... cnt2が cnt1       最終行 ... cnt1がn-1の場合 */     if( cnt2==0 || cnt2 == cnt1 || cnt1 == n-1 )       printf( "*" );     else       printf( " ");   }   printf( "\n" ); } printf( "逆三角中抜き\n"); for ( cnt1=0; cnt1 < n; cnt1++ ) {   for( cnt2=(n-cnt1); cnt2 > 0; cnt2-- ) {     /* cnt2ループの*出力は      初期値 ... cnt2が ( n - cnt1 )      終了値 ... cnt2が 1      最初の行 cnt1が0      の場合 */     if( cnt2 == ( n - cnt1 ) || cnt2 == 1 || cnt1 == 0 )       printf( "*" );     else       printf( " ");   }   printf( "\n" ); } といった具合ですよ ...

回答No.6

   他にも間違いがあったので、まとめて書き直し。 #include <stdio.h> void line(int n, int l, int hollow) { char *chars = "* "; int i; for(i = 1; i < l; i ++) putchar(chars[1]); for( ; i <= n; i ++) putchar(chars[(i != l && i != n) * hollow]); putchar('\n'); } void square(int n, int hollow) { int i; for(i = 1; i <= n; i ++) line(n, 1, hollow * (i != 1 && i != n)); } void triangle1(int n, int hollow) { int i; for(i = 1; i <= n; i ++) line(i, 1, hollow * (i != n)); } void triangle2(int n, int hollow) { int i; for(i = 1; i <= n; i ++) line(n, n - i + 1, hollow * (i != n)); } void triangle3(int n, int hollow) { int max = n * 2 - 1, i; for(i = 1; i <= n; i ++) line(max - n + i, n - i + 1, hollow * (i !=n)); } void diamond(int n, int hollow) { int m, i; n -= (~n & 1); m = n / 2 + 1; for(i = 1; i <= m; i ++) line(m + i - 1, m - i + 1, hollow); for( ;i <= n; i ++) line(m + n - i, m - n + i, hollow); } int main(void) { int n, i; void (*draw[5])(int n, int hollow) = {square, triangle1, triangle2, triangle3, diamond}; scanf("%d", &n); for(i = 0; i < 10; i ++) draw[i / 2](n, i & 1); return 0; }  

tatsunami
質問者

補足

ご回答ありがとうございます。 まとめてでの補足となりますがよろしくお願いします。 したの方にもお伝えしたのですが、いま持っている技術以上のプログラムを組むことはダメなんです。 よろしくお願いします。 説明不足で申し訳ありません。

回答No.5

   訂正 "square"関数、 for(i = 1; i < n; i ++) line(n, 1, n, hollow); を、     ~~ for(i = 2; i < n; i ++) line(n, 1, n, hollow); に。     ~~

回答No.4

   Cで、 #include <stdio.h> void line(int n, int l, int r, int hollow) { char *chars = "* "; int i; for(i = 1; i < l; i ++) putchar(chars[1]); for( ; i <= r; i ++) putchar(chars[(i != l && i != r) * hollow]); for( ; i <= n; i ++) putchar(chars[1]); putchar('\n'); } void square(int n, int hollow) { int i; line(n, 1, n, 0); for(i = 1; i < n; i ++) line(n, 1, n, hollow); line(n, 1, n, 0); } void triangle(int n, int hollow) { int i; for(i = 1; i < n; i ++) line(i, 1, i, hollow); line(n, 1, n, 0); } void triangle2(int n, int hollow) { int i; for(i = 1; i < n; i ++) line(n, n - i + 1, n, hollow); line(n, 1, n, 0); } void triangle3(int n, int hollow) { int max = n * 2 - 1, i; for(i = 1; i < n; i ++) line(max, n - i + 1, n + i - 1, hollow); line(max, 1, max, 0); } void diamond(int n, int hollow) { int m, i; n -= (~n & 1); m = n / 2 + 1; for(i = 1; i <= m; i ++) line(m + i - 1, m - i + 1, m + i - 1, hollow); for( ;i <= n; i ++) line(m + n - i, m - n + i, m + n - i, hollow); } int main(void) { int n; scanf("%d", &n); square(n, 0); square(n, 1); triangle(n, 0); triangle(n, 1); triangle2(n, 0); triangle2(n, 1); triangle3(n, 0); triangle3(n, 1); diamond(n, 0); diamond(n, 1); return 0; }  

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.3

入力数分の縦×横の図形を描くということで、「偶数の場合、三角旗とダイヤ形って、どんなんだろ?」と不思議なんですけど、奇数の場合は、まあ、それっぽいものを出力します(笑)。適当に参考にしてください。 考えにくければ、行ごとに図形を出力しながら処理するのではなく、  char *figures = new char[n * n];  std::memset(figures, '*', n * n); とでもしておいて、スペースをいれるべき場所を考えたらいかがですか? 最初に、スペースをいれておいて、'*' を入れるべき場所を考えてもいいですが^^ ==== バグがあったら、アシカラズ^^; #include <iostream> int main () { // 数字の入力 int n; while (1) { std::cerr << "数字2~19を入力してください:"; if (!(std::cin >> n) || n < 2 || n > 19) { std::cin >> std::skipws; std::cerr << "入力エラーです!!\nもう一度"; continue; } break; } // 正方形の作成 std::cout << "\n正方形\n"; for (int row = 0; row < n; ++row) { for (int col = 0; col < n; ++col) std::cout << '*'; std::cout << '\n'; } // 直角三角形の作成 std::cout << "\n三角形\n"; for (int row = 0; row < n; ++row) { for (int col = 0; col <= row; ++col) std::cout << '*'; std::cout << '\n'; } // 逆直角三角形の作成 std::cout << "\n逆三角形\n"; for (int row = 0; row < n; ++row) { for (int col = 0; col < n - row; ++col) std::cout << '*'; std::cout << '\n'; } // 三角旗の作成(n が偶数の場合、どうするんだろ?^^) std::cout << "\n三角旗\n"; for (int row = 0; row < n / 2 + 1; ++row) { for (int col = 0; col < 2 * row + 1; ++col) std::cout << '*'; std::cout << '\n'; } for (int row = n / 2 - 1; row >= 0; --row) { for (int col = 0; col < 2 * row + 1; ++col) std::cout << '*'; std::cout << '\n'; } // ダイヤ形の作成(n が偶数の場合、どうするんだろ?^^) std::cout << "\nダイヤ形\n"; for (int row = 0; row < n / 2 + 1; ++row) { for (int col = 0; col < (n - (2 * row + 1)) / 2; ++col) std::cout << ' '; for (int col = 0; col < 2 * row + 1; ++col) std::cout << '*'; std::cout << '\n'; } for (int row = n / 2 - 1; row >= 0; --row) { for (int col = 0; col < (n - (2 * row + 1)) / 2; ++col) std::cout << ' '; for (int col = 0; col < 2 * row + 1; ++col) std::cout << '*'; std::cout << '\n'; } /// 中抜き正方形を作成する std::cout << "\n中抜き正方形\n"; for (int col = 0; col < n; ++col) std::cout << '*'; std::cout << '\n'; for (int row = 1; row < n - 1; ++row) { std::cout << '*'; for (int col = 1; col < n - 1; ++col) std::cout << ' '; std::cout << "*\n"; } for (int col = 0; col < n; ++col) std::cout << '*'; std::cout << '\n'; // 中抜き直角三角形の作成 std::cout << "\n三角形\n"; for (int row = 0; row < n - 1; ++row) { std::cout << '*'; for (int col = 1; col < row; ++col) std::cout << ' '; if (row != 0) std::cout << '*'; std::cout << '\n'; } for (int col = 0; col < n; ++col) std::cout << '*'; std::cout << '\n'; // 中抜き逆直角三角形の作成 std::cout << "\n逆三角形\n"; for (int col = 0; col < n; ++col) std::cout << '*'; std::cout << '\n'; for (int row = n - 2; row >= 0; --row) { std::cout << '*'; for (int col = 1; col < row; ++col) std::cout << ' '; if (row != 0) std::cout << '*'; std::cout << '\n'; } } ==== これ、正当な数値入力1回で終了します(rewind(stdin)はあまり意味がないし、最後のgetchar()も意味がよくわからなかったので、全体のループはなくしました)。

tatsunami
質問者

補足

ご回答ありがとうございます。 プログラムまで考えていただきありがとうございます。 ですが、学校でならっている構文(?)が質問にあるようなものしかないのでそれ以上の技術を使ってはいけないのです。 for,while,ifのみでループなどを記述しなければいけません。 申し訳ありませんがもう一度お教えいただけませんでしょうか。 ちなみに、入力数値が偶数の場合は、上半分を入力数値で、下半分を入力数値-1で出力させています。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

中抜き三角形の考え方。 (1)Y方向ループの始点と終点は、すべて"*"で出力する。 (2)それ以外は、X方向ループの始点と終点だけ"*"でそれ以外は" "を書く。 中抜き四角形とそんなに違わないと思いますが。

tatsunami
質問者

補足

ご回答ありがとうございます。 頭では理解できてるんですよね。 でもそのifやwhile、for文が考え付かないんですよ。 もう少し考えてみますね。 それでもだめでしたらまたお願いします。

関連するQ&A