アプリ版:「スタンプのみでお礼する」機能のリリースについて

プログラムが書いてあるため非常に長文です。
お許しください。
いま、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();
}

A 回答 (12件中1~10件)

方眼紙を用意して、大きさが2の場合、3の場合…の図形を手書きしてみては?


手計算の方法が分からないものは、プログラムで書きようが無いです。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

そうですね。まずは紙に起こすことからはじめてみます。

お礼日時:2007/09/08 23:25

中抜き三角形の考え方。


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

この回答への補足

ご回答ありがとうございます。

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

補足日時:2007/09/08 23:25
    • good
    • 0

入力数分の縦×横の図形を描くということで、「偶数の場合、三角旗とダイヤ形って、どんなんだろ?」と不思議なんですけど、奇数の場合は、まあ、それっぽいものを出力します(笑)。

適当に参考にしてください。

考えにくければ、行ごとに図形を出力しながら処理するのではなく、
 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()も意味がよくわからなかったので、全体のループはなくしました)。

この回答への補足

ご回答ありがとうございます。

プログラムまで考えていただきありがとうございます。
ですが、学校でならっている構文(?)が質問にあるようなものしかないのでそれ以上の技術を使ってはいけないのです。
for,while,ifのみでループなどを記述しなければいけません。

申し訳ありませんがもう一度お教えいただけませんでしょうか。

ちなみに、入力数値が偶数の場合は、上半分を入力数値で、下半分を入力数値-1で出力させています。

補足日時:2007/09/08 23:33
    • good
    • 0

 


 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;
}
 
    • good
    • 0

 


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

 


 他にも間違いがあったので、まとめて書き直し。

#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;
}
 

この回答への補足

ご回答ありがとうございます。

まとめてでの補足となりますがよろしくお願いします。
したの方にもお伝えしたのですが、いま持っている技術以上のプログラムを組むことはダメなんです。

よろしくお願いします。
説明不足で申し訳ありません。

補足日時:2007/09/08 23:36
    • good
    • 0

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" );
}
といった具合ですよ ...
    • good
    • 0

> 学校でならっている構文(?)が質問にあるようなもの…



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;
}
    • good
    • 0

あっ、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;
}
    • good
    • 1

あぁそうか。


 N = n % 2 ? n : 2 * n - 1;
とかも、使ってはいけないのかな?^^ 以下の if 文と同じ意味です。

if (n % 2) N = n; /* n が奇数 */
else N = 2 * n - 1; /* n が偶数 */
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!