Запрос помощи со встроенными циклами for в C ++ - PullRequest
2 голосов
/ 25 января 2020

Я сейчас работаю над проектом для класса CS, и мне было поручено распечатать ASCII-модель здания. Цель этого проекта - дать пользователю возможность ввести целое число, и это целое число будет равным количеству «разделов» здания. Ниже я разбил приведенный мне пример на разделы. Любая помощь будет принята с благодарностью, спасибо всем, кто нашел время, чтобы прочитать это.

Шаблон выглядит следующим образом. Сечение x = ((x * 2) + 2) = количество строк кода и «ширина» здания. (x = любое целочисленное значение)

  |\/|
  |/\|                //section 0      ((section * 2) + 2)
  /--\                                   0 + 2 = 2


 |\::/|
 |:\/:|               //section 1      ((section * 2) + 2)
 |:/\:|                                  2 + 2 = 4
 |/::\|
 /----\


|\::::/|
|:\::/:|
|::\/::|              //section 2       ((section * 2) + 2)
|::/\::|                                  4 + 2 = 6
|:/::\:|
|/::::\|
/------\

Мне удалось выяснить шаблон, но мне действительно тяжело внедрить несколько циклов друг в друга. Наилучшее изображение этого здания, которое у меня есть на данный момент, таково:

int i = 0;
int j = 0;
int size = 2;
int sizeAdj = (size * 2) + 2;
int leftMost = sizeAdj;


for(i = 0; i <= size; i++){
        for(j = 0; j < 1; j++){
            cout<<setw(leftMost + 1)<<"|";
            cout<<"\\";
            cout<<"/";
            cout<<"|";
            cout<<endl;
            for(j = 0; j < 1; j++){
                cout<<setw(leftMost + 1)<<"|";
                cout<<"/";
                cout<<"\\";
                cout<<"|";
     }
     leftMost = leftMost - 1;
    }
    cout<<endl;
}

И это распечатывает следующее.

  |\/|
  |/\|
 |\/|
 |/\|
|\/|
|/\|

Еще раз спасибо.

Ответы [ 3 ]

1 голос
/ 25 января 2020

, но мне действительно тяжело встраивать несколько циклов друг в друга.

Судя по всему, вам трудно писать эффективные циклы и просто не обратите внимание, пока вы не попытались их вложить. Посмотрите на ваши циклы, используя j в качестве управляющей переменной l oop:

for(j = 0; j < 1; j++)

Технически, это оператор цикла. Однако он устанавливает j в 0, запускает l oop один раз , затем увеличивает j до 1 и выходит из l oop. Трудно считать это реальным l oop, когда всегда есть только одна итерация. Если бы вы пропустили оператор for и просто задали j = 0.

, у вас было бы меньше работы, но все же есть проблема с тем, как вы вложили циклы. Ваши циклические структуры (игнорируя другие операторы в телах l oop) следующие:

for(i = 0; i <= size; i++){
    for(j = 0; j < 1; j++){
        for(j = 0; j < 1; j++){

Обратите внимание, что в среднем и самом внутреннем циклах используется j? Это катастрофа, ожидающая случиться. Не используйте вложенную переменную l oop с управляющей переменной l oop, содержащей l oop.


Еще лучше, старайтесь избегать циклов вложенности. Подумайте о том, что вы хотите, чтобы происходило с каждой итерацией al oop, а затем передайте эту функцию другой функции. Например, ваш самый внешний l oop может выглядеть так:

for(i = 0; i <= size; i++)
    printSection(i, size);

Тогда вы могли бы написать функцию printSection для обработки каждой секции здания. Это было бы намерением вашего среднего l oop, верно? (Если нет, измените детали в соответствии с вашими намерениями. Смысл в том, чтобы не путать много шагов в один кусок кода.) Вы можете легко протестировать эту функцию самостоятельно. Пусть ваша основная функция, например, вызовет printSection(1,2); вместо использования al oop, и убедитесь, что вывод соответствует тому, что в описании вашей проблемы. Повторите эти действия для printSection(2,2); и для других примеров, чтобы убедиться, что эта функция работает должным образом.

// Print section number `section` for a building with `size` sections.
void printSection(int section, int size)
{
    for(int i = 0; i <= section; i++) {
        // Handle the indent here, since it is the same throughout the section.
        cout << setw(size - section) << ' ';
        // Delegate the floor details to another function.
        printFloor(i, section);
        // End the line. Alternatively, this could be delegated to printFloor.
        cout << '\n';
    }
}

Вы можете заметить, что я использовал i в обоих циклах. Разве я не говорил, что это проблема? Это было бы, если бы петли были непосредственно вложенными. Однако они находятся в отдельных функциях, поэтому проблем нет.

Далее вы должны написать функцию printFloor. Я бы начал просто; у printFloor(int floor, int section) изначально просто пишется символ канала ('|'), за которым следуют 2*section + 2 двоеточия, за которым следует еще один символ канала. Как только вы это заработаете, вы можете беспокоиться о Х через здание. Начните с малого, разделяйте и властвуйте, и убедитесь, что каждый кусок работает, прежде чем объединять вещи.

1 голос
/ 25 января 2020

Если честно, я не вижу шаблон в вашем коде.

Начните проще. Во-первых, не беспокойтесь о месте спереди:

|\/|
|/\|                //section 0      ((section * 2) + 2)
/--\                                   0 + 2 = 2


|\::/|
|:\/:|               //section 1      ((section * 2) + 2)
|:/\:|                                  2 + 2 = 4
|/::\|
/----\


|\::::/|
|:\::/:|
|::\/::|              //section 2       ((section * 2) + 2)
|::/\::|                                  4 + 2 = 6
|:/::\:|
|/::::\|
/------\

, если у вас есть, вам просто нужно добавить x пробелов впереди.

Далее, симметрия становится более очевидной, когда мы добавляем «поддельную» линию:

\----/
|\::/|
|:\/:|               //section 1      ((section * 2) + 2)
|:/\:|                                  2 + 2 = 4
|/::\|
/----\ 

Теперь ширина и высота одинаковы, и мы можем использовать

int width(int x) { return (x*2)+2; }

Напишите функцию, которая возвращает правильный символ для данной позиции

char get_simple_pattern(int x,int row,int col) {
     if (row == col) return '\\';
     // ...
     return ':';
}

Используйте две петли, чтобы напечатать ее

void print_simple_pattern(int x) {
   for (int row=0; row < width(x); ++row) {
       for (int col=0; col < width(x); ++col) {
           std::cout << get_simple_pattern(x,row,col);
       }
       std::cout << "\n";
   }
}

После того, как вы это исправите, вы должны

  • добавьте x пробелов перед каждым рядом: std::cout << std::string(x,' ');
  • пропустите первый ряд
  • добавьте oop сверх x
0 голосов
/ 25 января 2020

Я сделал это в C для удовольствия .... для чего бы это ни стоило:

#include <stdio.h>
#include <string.h>

void print_section(int n, int z)
{
    char dots[2*n+1];
    memset(dots,':',2*n+1);
    dots[2*n+1]=0;
    for(int r=0;r<n+1;++r)
    {
        printf("%*.s|%.*s\\%.*s/%.*s|\n",z-n,"",r,dots,2*(n-r),dots,r,dots);
    }

    for(int r=n;r>=0;--r)
    {
        printf("%*.s|%.*s/%.*s\\%.*s|\n",z-n,"",r,dots,2*(n-r),dots,r,dots);
    }
    memset(dots,'-',2*(n+1));
    printf("%*.s/%.*s\\\n",z-n,"",2*(n+1),dots);
}

int main(void) {
    int sections;
    printf("Please enter number of sections: \n");
    scanf("%d", &sections);

    for(int s=0; s<sections; ++s)
    {
        print_section(s, sections);
    }

    return 0;
}

Вывод

для 5 секций

Success #stdin #stdout 0s 4276KB
Please enter number of sections:  5
     |\/|
     |/\|
     /--\
    |\::/|
    |:\/:|
    |:/\:|
    |/::\|
    /----\
   |\::::/|
   |:\::/:|
   |::\/::|
   |::/\::|
   |:/::\:|
   |/::::\|
   /------\
  |\::::::/|
  |:\::::/:|
  |::\::/::|
  |:::\/:::|
  |:::/\:::|
  |::/::\::|
  |:/::::\:|
  |/::::::\|
  /--------\
 |\::::::::/|
 |:\::::::/:|
 |::\::::/::|
 |:::\::/:::|
 |::::\/::::|
 |::::/\::::|
 |:::/::\:::|
 |::/::::\::|
 |:/::::::\:|
 |/::::::::\|
 /----------\
...