циклы — Использование фигурных скобок для разделения переменной, которую я хочу использовать несколько раз в переполнении стека

В приведенном ниже коде у меня есть оператор while, который используется для того, чтобы убедиться, что длина входной строки меньше 10 символов. Я объявил bool называется cont который я использую, чтобы указать циклу while остановиться, как только мои условия будут выполнены.

#include "stdafx.h"#include <iostream>
#include <string>

int main()
{
using namespace std;

cout << "Enter a string less than 10 characters long: ";

string teststring;

{
bool cont(false);

//if input is 10 or more characters, ask for input again until it is less
while (!cont)
{
getline(cin, teststring);

if (teststring.length() >= 10)
{
cout << "Too long, try again: ";
}
else
{
cout << "Thank you.\n\n";
cont = true;
}

}
}

return 0;
}

Как вы можете видеть, я использовал набор {}s, чтобы отделить код, давая cont Переменная локальная область в этих скобках. Я сделал это так, чтобы, если мне когда-нибудь захотелось снова использовать это имя переменной, я мог просто повторно объявить его, и когда я закончу с ним, он будет уничтожен.

Это приемлемая практика? Или есть лучший способ сделать то, что я сделал? Я признаю, что в этом конкретном, базовом сценарии условие достаточно простое, что вряд ли необходимо, но я, возможно, захочу сделать это для более сложных циклов в будущем.

6

Решение

Это, конечно, игрушечный кейс, но это хорошая практика, и для этой цели существуют «автономные» блоки.
Я считаю, что это лучший способ структурировать длинные функции, чем разбивать его на элементы, которые (во многих случаях) не имеют отдельной цели.

В таком случае вы можете предоставить более быструю, ясную и безопасную программу, особенно если есть комментарий (возможно, одна строка), представляющий каждый блок.

Однако в этом случае вы можете рассмотреть:

    for ( bool cont(false);!cont;)

Который имеет тот же эффект. Переменные, объявленные в for(.;.;.) заявление ограничивается рамками этого заявления.

В этом случае вы можете увернуться от всей переменной с помощью:

    for(;;) //<--- Canonical formulation for 'infinite' loop.
{
getline(cin, teststring);

if (teststring.length() >= 10)
{
cout << "Too long, try again: ";
}
else
{
cout << "Thank you.\n\n";
break; //<--- Escapes the loop.
}

}

Сноска (в ответ на комментарии):

Вы должны рассмотреть for петля как «синтаксический сахар» на while петля. Это не отличается в их производительности и т. Д. И просто выберите тот, который читает лучше всего. for(;cond;) выглядит просто смешно.

Может быть крошечное (крошечное) преимущество в производительности break но мне кажется, что во многих случаях это проще и удобочитаемее.

Если бы код был более сложным, там могло бы быть больше кода «конца цикла», поэтому он становится:

for(bool cont(false);!cont;) {

//Complex code with multiple 'exit' conditions...

if(!cont) {
//Go round again code that won't fit nicely in last term of for loop...
}
}

В то время как использование break просто облегчает понимание «быстрого выхода».
Считается, что они не имеют «плохой кармы» goto потому что они «идут» в очень четко определенную точку исполнения.

1

Другие решения

В общем? Да. Это хорошо.

В этом конкретном случае? Нет, ненужно. Вы не используя это имя снова, и в этом простом коде вы не собираетесь. Так что это просто шум.

Видите … это баланс.

Я обнаружил, что делаю это совсем немного в функциях, которые выполняют несколько связанных операторов SQL. Каждый раз, когда я мог бы создать его с std::stringstream называется ss, Конечно, я мог бы дать каждому другое имя, но это полностью предотвращает ошибки, чтобы держать каждого построителя операторов в своей области видимости.

Это также очень распространенная техника, когда вы используете такие вещи, как охранники замка.

2

Это приемлемая практика и делает именно то, что вы говорите. Однако он редко используется, потому что в небольших функциях это однозначно и поэтому приемлемо иметь cont переменная в области действия верхнего уровня. Если вам кажется, что вам нужно разделить область видимости в более крупной функции, обычно предпочтительнее создать другую функцию с явным именем.

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

Другой вариант — переписать цикл, чтобы не нуждаться в cont переменная, например:

string teststring;
do
{
cout << "Enter a string less than 10 characters long: ";
getline(cin, teststring);
} while (teststring.length() >= 10);

cout << "Thank you.\n\n";

Но это не всегда возможно, особенно если вам нужно вывести другое сообщение в зависимости от условия остановки.

2

Да, хорошо, если у вас есть веская причина для повторного использования переменной. Защитники блокировки — наиболее распространенное использование в моем собственном коде, и пример, приведенный в ответе Lightness о std::stringstream ss, По сути, делайте это каждый раз, когда выбор других имен переменных кажется более неловким. Например. если ты пишешь lock1, lock2, lock3… в вашем коде.

Однако более приемлемой практикой было бы рассматривать тела с длинными функциями как запах кода и преобразовывать их в свои собственные функции. Например.

...
string teststring;

{
bool cont(false);
//10 lines of code to handle the foo scenario
}
{
bool cont(false);
//15 lines of code to handle the bar scenario
}
...

Это лучше обрабатывается рефакторингом так:

...
string teststring;
foo(teststring);
bar(teststring);
...

void foo(string &teststring){
bool cont(false);
//10 lines of code
}

void bar(string &teststring){
bool cont(false);
//15 lines of code
}
2
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector