4

私はいくつかの C の演習を開始し、入力を介して三角形を出力する必要があるこの素晴らしい演習を見つけました。入力6の場合、印刷されます

*
**
***
****
*****
******
*****
****
***
**
*

今見てみると、まあ、そんなに大変な作業じゃないな、と思いました。そこで、再帰を使用して、ループを使用せず、変数を 2 つだけ使用して作成することにしました。関数は次のようになります。

void PrintTriangle(int iMainNumber, int iCurrNumber)
{
   //Logic goes here
}

数時間後、関数が出力する三角形の数を「記憶」できるようにするには、関数に十分な情報を渡す必要があるため、これが思ったよりもはるかに難しいことに気付きました。

それで、それが可能かどうかを尋ねることにしました。

(ループなし、他の関数なし、再帰のみであることを忘れないでください)。

編集: これは宿題ではなく、純粋な好奇心からです。しかし、私はおそらくあなたのために検証することはできません. これでなんとか中途半端になった

void PrintTriangle(int iMainNumber, int iCurrNumber)
{
    if (iMainNumber == 0)
    {
        printf("\r\n");
    }
    else if (iMainNumber == iCurrNumber)
    {
        printf("\r\n");
        PrintTriangle(iMainNumber - 1, 0);
    }
    else
    {
        printf("%s", MYCHAR);
        PrintTriangle(iMainNumber, iCurrNumber + 1);
    }
}

反対の関数を作成しようとして行き詰まりました。それができれば、iMainNumber と iCurrNumber が正または負であるという事実を利用して、関数フローをナビゲートできると思います。

つまり、パラメーターが負の場合は、入力の長さから 1 を引いた長さに降順の星を出力し、パラメーターが正の場合は、入力の長さに昇順の星を出力します。

フラグの使用について考えましたが、2 つの整数の代わりにはなりません。

別のフラグを追加して 2 つの整数と 1 つのフラグがあれば解決できるかもしれませんが、前述のように、整数を 2 つに制限しようとしました。

私が考え始めているのは、2つ以上の整数と再帰を使用せずに、このメソッドで昇順の星を出力するために必要な情報を渡す方法がないということです。

しかし、私はまだそれについて確信が持てないので、質問です。

4

5 に答える 5

1

OPが提案したように2つのパラメータを使用する

void PrintTriangle(int iMainNumber, int iCurrNumber) {
  if (iMainNumber < 0) { // Row (use negative iMainNumber)
    printf("%c", '*');
    PrintTriangle(iMainNumber + 1, 0);
    if (iMainNumber == -1)
      printf("\n");
  } else if (iMainNumber > 0) { 
    if (iCurrNumber < iMainNumber) { // Preceding short lines
      if (iCurrNumber > 1)
        PrintTriangle(iMainNumber, iCurrNumber - 1);
      PrintTriangle(-iCurrNumber, 0);
    } else if (iCurrNumber == iMainNumber) { 
      PrintTriangle(iMainNumber, iCurrNumber - 1);  // left
      PrintTriangle(iMainNumber, iCurrNumber + 1);  // Right
    } else {                         // Subsequent short lines
      if ((iCurrNumber - iMainNumber) < iMainNumber)
        PrintTriangle(iMainNumber, iCurrNumber + 1);
      PrintTriangle(-(iCurrNumber - iMainNumber), 0);
    }
  }
}

int main() {
  PrintTriangle(3,3);
  PrintTriangle(6,6);
  return 0;
  }
于 2013-10-14T22:03:07.790 に答える
0

純粋な再帰、ループなし、呼び出しプログラム 'main()' は 1 つのパラメーターのみを渡します。

void PrintTheClms(int width, int stars) {
    printf("*");
    if stars < width then {
      PrintTheClms(width, stars+1);
    }
}

void PrintStars(int  width) {
    PrintTheClms(width, 1);
    printf("\n");
}

void PrintTheRows(int size, int indent) {
    PrintStars(indent);
    if indent < size then {
      PrintTheRows(size, indent+1);
      PrintStars(indent);
    }
}

void PrintTriangle(int size) {
    if size > 0 then {
      PrintTheRows(size, 1);
    }
}

int main() {
    PrintTriangle(6);
    PrintTriangle(11);
    // etc.
    return 0;
}

非常に単純です。else 句も、case 構文も、方向フラグもありません。ただし、多くのプロシージャと多くの呼び出しがあります。

于 2013-10-15T01:06:32.450 に答える
0

私が読んだことから、ほとんどの提案は、必要な状態で合格することをすでに指摘しています。

ただし、実際にはそれほど多くの分岐ステートメントは必要ありません。必要なもののほとんどは、算術的に導き出すことができます。再帰の総数を計算し、現在の再帰カウントから星の数を導き出すことができます。また、初期呼び出しの部分を再帰から分離することで、使用法をより簡単にすることができます。

2 つ以上の整数を必要としないことがわかりました。以下を検討して、本当にその設定を維持したいかどうかを確認してください. その場合、合計の計算を再帰部分に入れることができます。読みにくいと思います。

void _print_stars(int height, int total, int current)
{
    int stars = current <= height ? current : 2 * height - current;

    for (int i = 0; i < stars; i++) { printf("*"); }
    printf("\n");

    if (current != total)
    {
        _print_stars(height, total, current + 1);
    }
}

void print_stars(int height)
{
    int total_recursions = 2 * height - 1;
    _print_stars(height, total_recursions, 1);
}
于 2013-10-14T23:28:20.680 に答える