Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 27, средняя оценка - 4.89
Гость
Сообщений: n/a
#1

не использовать do/while ? бред ! - C++

27.08.2007, 13:12. Просмотров 3279. Ответов 3
Метки нет (Все метки)

меня возмутила статья
http://www.cyberguru.ru/programming/...es-page67.html
в которой автор рекомендует вместо do {} while (); использовать while () {};
давайте же разберёмся что происходит на самом деле

do { действия } while ( условие );
если это разложить по косточкам выходит следующее
Код
метка:
действия
if (!условие) goto метка
итак на цикл одна метка и на каждую итерацию один прыжок

while ( условие ) { действия };
разложим и это
Код
метка1:
if (!условие) goto метка2
действия
goto метка1
метка2:
две метки и на 1 больше прыжок, чем в do {} while ();
p.s. если кто сомневается что он устроен именно так вспомните, что возможно while (действие перед каждой проверкой, проверка) { действие };

и ещё разсмотрим конструкцию if (условие) { do { } while (); }; которая особо не понравилась автору, что меня вообще добило хех
Код
if (!условие) goto метка1
метка2:
действия
if (условие) goto метка2
метка1:
хорошо теперь возьмём массив major размером 4 и заполним его единицами

для do { } while ( ) ;
Код
int major[4], it (0);
do {
	major[it] = 1;
	++it;
} while (it < 4);
прошли при it == 0, проверили, прыгнули
прошли при it == 1, проверили, прыгнули
прошли при it == 2, проверили, прыгнули
прошли при it == 3, проверили
всё
действий 4
проверок 4
прыжков 3






для while ( ) { };
Код
int major[4], it (0);
while (it < 4) {
	major[it] = 1;
++it;
};
проверили, прошли при it == 0, прыгнули
проверили, прошли при it == 1 прыгнули
проверили, прошли при it == 2 прыгнули
проверили, прошли при it == 3 прыгнули
проверили, прыгнули
всё
действий 4
проверок 5
прыжков 6

конструкция if (условие) { do { } while (); };
Код
int major[4], it(0);
if (it < 4) {
	do {
		major[it] = 1;
		++it;
	} while (it < 4);
};
проверили
прошли при it == 0, проверили, прыгнули
прошли при it == 1, проверили, прыгнули
прошли при it == 2, проверили, прыгнули
прошли при it == 3, проверили
всё
действий 4
проверок 5
прыжков 3

я считаю исходя из выше перечисленного что
if (условие) { do { } while (); }; эффективнее while ( ) { }; и именно по этому заявление автора статьи меня так возмутило, он хоть бы попытался чем-то это аргументировать ...
если я где-то ошибся прошу это указать, может я в чём-то и не прав
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.08.2007, 13:12     не использовать do/while ? бред !
Посмотрите здесь:

какой то бред! - C++
не могу понять что за цирк.. #include &lt;math.h&gt; #include &lt;iostream.h&gt; #include &lt;iomanip.h&gt; main() { double a,d,n; ...

бред в результате - C++
ничего не могу понять! нужно посчитать v, для этого просим ввести пользователя h и s, в результате получается какой-то бред!!! ввожу 3 и 2,...

Бред со счетом - C++
С начало грешил на свой компилятор, но после попробовал на Visual Studio 2010 и тот же результат. Какого черта в коде ниже, 264.088/11...

Почему выводит бред - C++
Имеется следующий код #include &lt;iostream&gt; #include &lt;locale&gt; using namespace std; const char* rename() {

Бред при декомпиляции - C++
Всем привет!У меня такая проблема, при дэкомпиляции у меня получается всякий бред типо jddvb:56/df;v:j/:u19vghj незнаю что делать и из за...

проверка на IF что за бред - C++
/* Вариант 12 В одномерном массиве, состоящем из п вещественных элементов, вычислить: 1) номер максимального по модулю элемента...

Бред в крестиках ноликах - C++
Проблема. Написал цикдические крестики нолики ( в конце игры спрашивает хотите сыгарть еще или нет?) и после этого происходит какой то...

Программа считает бред какой-то - C++
#include &lt;stdio.h&gt; int main() { int t,y,v,x,n=0; scanf(&quot;%d %d&quot;, &amp;x, &amp;y); while (x&lt;y) {...

Какой то бред с передачей указателя в функцию :-) - C++
Привет! Толи бред какой - то :D Толи у меня пробел в азах :rofl: Вот например: void MegaFunction( BYTE *data ); int...

Программа при выводе доп.информации выдает бред - C++
Блин сохраняет в файл только последний введенные в цикле данные Помогите,что может быть не так: #include &lt;iostream&gt; #include...

_getch() в цикле выводит бред вместо русских букв - C++
Извращался тут с getch(), возникла небольшая, но странная (для меня) проблема. В программе такого рода char x; x=_getch(); cout&lt;&lt;x;...

С# и бред на С++ - C#
Ребят, гляньте задачку. Нашел вариант решения её на С++(походу не правильный), но не получается сделать её на С#, помогите пожалуйста, а...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
igor_nf
118 / 12 / 1
Регистрация: 21.08.2007
Сообщений: 222
27.08.2007, 19:02     не использовать do/while ? бред ! #2
it (0)
По всей видимости опечатка, т.к. нужно it = 0

Теперь к делу:
C++
1
2
3
4
5
int major[4], it (0);
do {
    major[it] = 1;
    ++it;
} while ( it < 4 );
Плохой код. Для таких дел есть цикл for():
C++
1
for( it = 0; it < 4 && (major[it] = 1); ++it );
Результат тот же, но повышается удобочитаемость, т.к. все операторы инициализации и вся управляющая информация локализована в одном месте. Конечно, код, инициализирующий четыре элемента массива достаточно удобочитаем и при использовании цикла do - while, ну а если он разрастётся в что-то серьёзное? Проблема цикла do в том, что программист, увидев блок операторов цикла, не знает условий, при которых цикл должен закончиться(ну если цикл не 4 строчки, как в нашем случае). Это затрудняет читаемость кода.

Теперь конкретно ко времени исполнения программы(ну, предварительно, заставим исполняться этот код 10000000 раз):
C++
1
2
3
4
5
6
7
8
9
10
11
12
int main( void ) {
 
int i = 0;
int major[4];
int j = 0;
do {
 
do {
    major[i++] = 1;
        } while ( i < 4 );
++j;
        } while( j < 10000000 );
Такой код исполняется у меня на системе 0.200 сек

Теперь мой вариант(результат тот же):
C++
1
2
3
4
5
6
7
8
9
10
int main( void ) {
 
int j = 0;
int major[4], i = 0;
 
for( ; j < 10000000; ++j ) {
 
    for( ; i < 4 && ( major[i] = 1 ); ++i );
        
}
Такой код исполняется 0.040сек, т.е. в 5 раз быстрее. (Надо сказать, что если инициализацию переменных поместить в заголовки for(), код выполняется 0.250сек - что вполне логично - в цикле лишние присваивания). Тест проводился на компиляторе gcc-4.1.2 с уровнем оптимизации 0.

Что, касается цикла while, то всё вышесказанное применимо и к нему, т.к. его отличие лишь в том, что условие проверяется сразу => цикл может быть не выполнен ни разу.

Что касается if () do {} while() - вообще глупо и неоптимально, т.к. сразу в таком коде
C++
1
2
3
4
5
6
if ( it < 4 ) {
    do {
        major[it] = 1;
        ++it;
    } while ( it < 4 );
};
налицо избыточность - двойная проверка.

Резюмируя вышесказанное, применение цикла for() выгоднее в данных случаях и с точки зрения быстродействия, и с точки зрения удобочитаемости.

Что касается статьи, то автор скорее всего хотел сказать, что в программировании нечасто встречаются ситуации, в которых использование циклов do-while является самым оптимальным решением. Но это не значит, что их нельзя использовать!

P.S. Ну всё, что я тут нагородил, конечно, результат моих собственных изысканий и не является аксиомой.
Гость
Сообщений: n/a
28.08.2007, 00:11     не использовать do/while ? бред ! #3
да этот ответ меня действительно поразил на некоторое время, а именно проверка указанных тестов, спасибо
кстати it (0) это выполнение конструктора при инициализации, раз Вы пользуетесь компилятором gcc, то я могу сделать предположение что в C нету конструкторов из за отсутствия классов (если я не ошибаюсь) - далее я использую компилятор g++ 4.1.2 и чтож пусть будет it = 0, теперь к делу )

меня действительно поразило то, что указанные времена почти совпали, но я не мог понять как такое может быть, если цикл for это тот же while только с другим синтаксисом

сразу замечу что зачастую я выбираю цикл while если ситуация того требует, а не if { do { } while (); }; , но если я пишу программу не спеша я её маниакально пытаюсь ускорить во времени но в любом случае в первую очередь - выше скорости стоит чёткая и стабильная робота программы, и я никогда бы не написал бы так
C++
1
for( it = 0; [b]it < 4 && (major[it] = 1)[/b]; ++it );
что выполниться первым ? 4 И то что в скобках или сравнение с it ? несмотря на что, что якобы это можно определить по приоритетам операций я всегда стараюсь такого избегать после всех испытанных различий компиляторов в таких тонких моментах

и ещё - в первом варианте инкремент i постфиксный, в другом префиксный, по моему мнению префиксный инкремент лучше - он быстрее и возвращает указатель, потому использую его

затем мне бросилось в глаза вот что - после итераций в внутреннем цикле Вы не онуляете переменную i - ведь далее с её помощью будет попытка доступа к несуществующим элементам 5, 6, 7 .. 39999999

таким образом я внёс некоторые правки в код - я добавил скобки к (it < 4) а также добавил онуление i, изменил i++ на ++i и как - то более структурно записал всё, иначе для меня код просто нечитабельный
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main( void ) {
   int i = 0, j = 0, major[4];
#ifdef TEST
   do {
      i = 0;
      do {
         major[i] = 1;
     ++i;
      } while ( i < 4 );
      ++j;
   } while( j < 10000000 );
#else
   for( ; j < 10000000; ++j ) {
      for( i = 0; (i < 4) && ( major[i] = 1 ); ++i );
   };
#endif
   return 0;
};
пробую теперь
g++ sol.cpp -o sol && time ./sol = 0.23s
g++ sol.cpp -o sol -D TEST && time ./sol = 0.20s

хм...
всётаки for медленнее ...
чтоже так затормозило его ? скобки или онуление i ?

ах да насчёт двойной проверки - это да, я просто хотел показать что условие копируется в обе части кода и работает структура так же как while

я конечно не спорю что это всё не актуально при олимпиадном программировании, или при написании курсовых робот, но для больших проектов ... написанный код будет выполняться миллионы раз и экономия миллисекунды даст ведь о себе знать
хехе снять розовые очки ?
igor_nf
118 / 12 / 1
Регистрация: 21.08.2007
Сообщений: 222
28.08.2007, 16:02     не использовать do/while ? бред ! #4
g++ sol.cpp -o sol && time ./sol = 0.23s
g++ sol.cpp -o sol -D TEST && time ./sol = 0.20s
Ну да, я забыл обнулять переменную, вследствие чего и получил результат 0.040сек - внутренний for() исполнялся всего один раз.

for() действительно медленнее - но засчёт чего, мне стало очевидно только после анализа асемблерного листинга.

Вся работа for( i = 0; i < 4 && (major[i] = 1); ++i) заключается в семи машинных командах:
Assembler
1
2
3
4
5
6
7
8
    movl    $0, -12(%ebp)                    
.L4
    cmpl    $3, -12(%ebp)                    
    [B]jg   .L5[/B]                              
    movl    -12(%ebp), %eax                
    movl    $1, -28(%ebp,%eax,4)
    incl    -12(%ebp)
    jmp .L4
Вся работа do { major[i++] = 1} while( i < 4 )заключается в шести машинных командах:
Assembler
1
2
3
4
5
6
7
           movl      $0, -12(%ebp)
.L3:
    movl    -12(%ebp), %eax
    movl    $1, -28(%ebp,%eax,4)
    incl    -12(%ebp)
    cmpl    $3, -12(%ebp)    
    jle .L3
Выводы делаем сами...
Yandex
Объявления
28.08.2007, 16:02     не использовать do/while ? бред !
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru