Страницы

Поиск по вопросам

Показаны сообщения с ярлыком цикл. Показать все сообщения
Показаны сообщения с ярлыком цикл. Показать все сообщения

четверг, 30 мая 2019 г.

Логический оператор с бесконечным количеством итераций

Скажите пожалуйста, есть ли такой оператор, который будет выполнять какую либо итерацию, до того момента, пока логическое условие не будет выполнено? Это не for ведь в нем надо указывать кол-во итераций, а мне нужно немного другое то, что я описывал выше. Спасибо.


Ответ

Начать исполнять и продолжать пока условие верно:
boolean someBoolean = true; while(someBoolean) { //тут можно присвоить false для someBoolean для завершения бесконечного цикла }

Либо можно и через цикл for вот так
boolean someBoolean = true; //в цикле for сперва идёт инициализация переменной-чсётчика, в конце действие с ней (инкрементация, например), //а по середине - условие - пока оно верно, цикл будет продолжаться for (;someBoolean;) { //тут можно присвоить false для someBoolean для завершения бесконечного цикла }

Если же хотя б одну итерацию надо сделать вне зависимости от начального значения someBoolean, то можно написать так:
boolean someBoolean = false; do { //хотя бы раз, но выполнится } while(someBoolean);

понедельник, 29 апреля 2019 г.

Удалить дубликаты в массиве без использования коллекций. Java

Необходимо удалить дубликаты в массиве без использования коллекций.
C ArrayList или HashSet все понятно, тут делать не чего, но мне задание дали удалить дубликаты не используя ничего, кроме массивов. При чем метод должен работать, даже если дубликатов больше двух.
Исходный массив {1 ,1, 1, 2, 1, 3, 3} Искомый результат {1, 2, 3}
В общем уже голову сломал, может кто поможет?
Спасибо.


Ответ

Как я полагаю, ваше задание на использование циклов при работе с массивами. Если так, то прямолинейный подход с использованием циклов может выглядеть следующим образом
import java.util.*; import java.lang.*; import java.io.*;
class Ideone { public static void main (String[] args) throws java.lang.Exception { int[] a = { 1, 1, 1, 2, 1, 3, 3 };
int n = a.length;
for ( int i = 0, m = 0; i != n; i++, n = m ) { for ( int j = m = i + 1; j != n; j++ ) { if ( a[j] != a[i] ) { if ( m != j ) a[m] = a[j]; m++; } } }
if ( n != a.length ) { int[] b = new int[n]; for ( int i = 0; i < n; i++ ) b[i] = a[i];
a = b; }
for ( int x : a ) System.out.print( x + " " ); System.out.println(); } }
Вывод программы
1 2 3

четверг, 25 апреля 2019 г.

Почему ready() всегда выдает true?

Имеется такой код:
public static void main(String[] args) throws IOException { StringReader reader = new StringReader("Khoor Dpljr"); System.out.println(decode(reader, -3)); //Hello Amigo }
public static String decode(StringReader reader, int key) throws IOException { BufferedReader br = new BufferedReader(reader); while (br.ready()) { int b = br.read(); b = b + key; char c = (char) b; System.out.println(c); } return null; }
Почему ready() всегда выдает true?


Ответ

Потому что так написано в документации к этому методу
True if the next read() is guaranteed not to block for input, false otherwise
Перевод:
true, если гарантируется, что следующий вызов метода read() будет неблокирующим
Так как при достижении конца потока метод read сразу возвращает -1, то и ready() возвращает true

Чтобы код заработал, можно переписать его так:
int c; while ((c = bufferedReader.read()) != -1) { // ... }

Частичный перевод ответа @StephenC

четверг, 4 апреля 2019 г.

Несколько init-expression в for

#include #include #include #include
using namespace std;
int Search(string* Array, int Size, string* Words) { ifstream *Read = new ifstream[Size];
for (int I = 0; I < Size; I++) { Read[I].open(Array[I]); if (!Read[I]) { cout << "Файл с именем: " << Array[I] << "не может быть открыт
"; } // В следующей строке в возникает ошибка I должно иметь константное значение //Ошибки нет, если "string Value" вынести из цикла //Почему возникает ошибка ? for (string Value, Read[I] >> Value; !Read[I].eof(); Read[I] >> Value) { // Что-то делающий код }
}
for (int I = 0; I < Size; I++) { Read[I].close(); } }


Ответ

В синтаксисе for
    for ( init-statement conditionopt ; expressionopt ) statement
первая часть - init-statement - является либо выражением, либо объявлением.
Вы изначально использовали синтаксис string Value, [...], который явно говорит, что в вашем случае в качестве init-statement вы хотите использовать именно объявление, а не выражение. Однако дальнейший синтаксис [...], Read[I] >> Value не является корректным синтаксисом объявления. Отсюда и ошибка.
(Странно, что вы в своем вопросе называете эту часть синтаксиса for "init-expression", хотя в вашем же примере это никакой не expression.)
Выбирайте: либо выражение, либо объявление. Перемешать выражение с объявлением вот так вот в лоб, как у вас, не получится.

понедельник, 1 апреля 2019 г.

Какой из вариантов циклов быстрее?

Есть блоки кода вычислений блок1, блок2, блок3, блок4,...блок 10, скажем. Скажите, как поступить при использовании их в цикле: for (i = 0; i <= n; i++) { блок1; блок2; блок3; блок4; ... блок10; } Или же так оптимально: for (i = 0; i <= n; i++) { блок1; }
for (i = 0; i <= n; i++) { блок2; }
.............
for (i = 0; i <= n; i++) { блок10; } Можете объяснить почему? Мне лично кажется, что первый вариант быстрый и правильный.


Ответ

Ответ скорее не ТС, а @IronVbuf. Начало развернутого комментирования его ответа. Копия моего комментария: @IronVbif, рассуждения красивые. Время позднее, не хочу (сейчас) все разбирать. Если правильно понял, в пунктах 4, 5 и 6 Вы склоняетесь к тому, что несколько маленьких циклов (особенно если их тела маленькие) будут производительней одного. Практический замер (gcc -O3 MinGW (32-bit) Windows 7 64-bit I5-2500 3.3GHz) показал обратное (причем аж в 3 раза для 6 циклов и 10^9 повторов маленьких вычислений (преобразование int->double, double умножение и сложение) Примерчик (нисколько не претендует на полноту, 5 минут на коленке). gcc -O3 MinGW (32-bit) Windows 7 64-bit I5-2500 3.3GHz #include
#define incvar(x,y) {x = x + i*y;} main (int ac, char *av[]) { double a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; int i; if (av[1]) { printf ("one loop
"); for (i = 0; i < 1000000000; i++) { incvar(a,1.234); incvar(b,7.234); incvar(c,11.234); incvar(d,111.234); incvar(e,51.234); incvar(f,21.234); } } else { printf ("six loops
"); for (i = 0; i < 1000000000; i++) incvar(a,1.234); for (i = 0; i < 1000000000; i++) incvar(b,7.234); for (i = 0; i < 1000000000; i++) incvar(c,11.234); for (i = 0; i < 1000000000; i++) incvar(d,111.234); for (i = 0; i < 1000000000; i++) incvar(e,51.234); for (i = 0; i < 1000000000; i++) incvar(f,21.234); }
printf ("%e %e %e %e %e %e
",a,b,c,d,e,f); }
c:/Users/avp/src/cc/hashcode $ gcc -O3 bloloops.c c:/Users/avp/src/cc/hashcode $ date; ./a; date Mon Aug 13 23:55:42 2012 six loops 6.170000e+017 3.617000e+018 5.617000e+018 5.561700e+019 2.561700e+019 1.061700e+019 Mon Aug 13 23:56:00 2012 c:/Users/avp/src/cc/hashcode $ date; ./a 1; date Mon Aug 13 23:56:17 2012 one loop 6.170000e+017 3.617000e+018 5.617000e+018 5.561700e+019 2.561700e+019 1.061700e+019 Mon Aug 13 23:56:23 2012 c:/Users/avp/src/cc/hashcode $ Все желающие приглашаются к экспериментированию (вместо теоретизирования на основе прочитанной литературы) с последующим обсуждением результатов. UPDATE Для замера времени исполнения фрагментов программы удобно использовать функцию: /* avp
время в миллисекундах */
#include #include
long long mtime() { struct timeval t;
gettimeofday(&t, NULL); long long mt = (long long)t.tv_sec * 1000 + t.tv_usec / 1000; return mt; } Меряем так: ... long long mtime(void); ... long long start = mtime(); // измеряемый код ... printf ("duration: %lld msec
",mtime()-start); ...

воскресенье, 31 марта 2019 г.

Некорректная фильтрация строки

Имеется код:
#include #include using namespace std;
int main() { string str = "Hallow, world"; int i = 0; for (i; i < str.length(); i++) { if (str[i] == ',') { str.erase(i); }; }; cout << str; return 0; }
Цикл завершается тогда, когда условие впервые принимает значение "истина", хотя цикл должен продолжаться до конечного символа строки. Почему так происходит?


Ответ

Правильно удалять так:
for (; i < str.length();) { if (str[i] == ',') str.erase(i, 1); else i++; };
Таким образом вы удаляете каждый раз по одному символу. Кроме того, при удалении символы сдвигаются, так что вам нужно перепроверить текущий индекс. Поэтому i++ ушло в else. (Кроме того, в таком виде for можно заменить на while.)
Более идиоматический метод удаления из строки в C++ — использование и идиомы erase/remove:
str.erase(std::remove(str.begin(), str.end(), ','), str.end());
или, если хочется более сложного условия,
str.erase(std::remove_if(str.begin(), str.end(), [](char x){ return x == ','; }), str.end());
(Спасибо @Vlad from Moscow за уточнение!)

пятница, 8 февраля 2019 г.

Как определить,в каких случаях эффективнее использовать рекурсию,а когда цикл?

Вопрос достаточно поверхностного характера.Интересно как в принципе на практике определить, что эффективнее в решении какой-либо задачи рекурсия или цикл?Заранее благодарю за внимание.


Ответ

По-своему опыту могу порекомендовать следующее:
Ответьте себе на вопрос: знаете ли вы уровень вложенности?
Если да, и уровень вложенности небольшой (например 3 цикла) - то смысла заморачиваться с рекурсией нет.
Если нет, и уровень вложенности может быть динамическим, то ответ очевиден - без рекурсии не обойтись
В любом случае,
Начинайте писать код без рекурсии, просто используйте вложенные циклы. Не обязательно с полной вложенностью, достаточно 2-3 вложенных цикла, отшлифуйте их, чтобы они работали корректно. Как только Вы это сделаете, переделать их в рекурсию или продолжить работать во вложенных циклах не вызовет никаких проблем в обоих случаях.
Начиная писать нерекурсивно, Вы с самого начала лучше разберетесь, как работает код, а впоследствие и сама рекурсия.

пятница, 14 декабря 2018 г.

Использование переменных объявленных в for

Почему недопустим такой вариант?
int sum=0; for(int j=0; jА такой компилируется:
int sum=0; int j=0; for( ; j(mas уже инициализирован)


Ответ

Я думаю, оба варианта компилируются, только первый выдаёт предупреждение из-за того, что этот код содержит undefined behaviour.
Переменную sum инициализировать за вас компилятор не будет. А использование неинициализировнной переменной есть даже не unspecified, а undefined behaviour. Это значит, что не только «начальное значение переменной может быть любым», но «при выполнении программы может произойти всё, что угодно, включая форматирование жёсткого диска».

Окей, вопрос отредактирован, теперь обе переменные инициализированы, ищем дальше.
Но я не заметил ещё одну ошибку. У вас написано for(int j=0; jВ результате в первом случае переменная j локальна в блоке и не видна за его пределами: этот код можно равносильно записать так:
for(int j=0; j{ sum+=mas[0][j]; sum+=mas[n-1][j]; }

пятница, 7 декабря 2018 г.

Случаи указания типа данных в условии цикла

Добрый вечер. Пришел с вопросом. Читал тут книгу, в одном фрагменте было написано, что если я укажу тип данных у переменной в условии функции, то значение переменной будет иметь большую область видимости, чем если бы я указал переменную без типа. То есть без типа переменная будет действовать, пока активен цикл, но с типом данных она будет действовать и на еще одни скобки.
Решил проверить. Написал с int'ом-все сработало. Убрал int-и программа стала использовать значение переменной в цикле во всей программе и по какому-то принципу компилятор его даже изменил, по какому-я не понимаю.
Вопрос: Я некорректно понял инфу из учебника? Да, то как все должно быть на самом деле?
#include using namespace std;
int main() { int done=5; int howmany=3;
for( done=1; done cout<Вывод:
7 7 3


Ответ

Рассмотрим следующую программу
#include
int main() { int done = 5; int howmany = 3;
for ( done = 1; done < howmany; done++ ) { std::cout << done << std::endl; }
std::cout << done << std::endl;
return 0; }
Ее вывод на консоль
1 2 3
В этой программе в блоке кода функции main объявлена переменная done. Сначала эта переменная инициализируется значением 5
int done = 5;
а затем в предложении for ей присваивается значение 1
for ( done = 1; done < howmany; done++ ) ^^^^^^^^
После выхода из цикла эта переменная будет иметь значение 3.
Теперь рассмотрим следующую программу
#include
int main() { int done = 5; int howmany = 3;
for ( int done = 1; done < howmany; done++ ) { std::cout << done << std::endl; }
std::cout << done << std::endl;
return 0; }
Ее вывод на консоль
1 2 5
В этой программе в предложении for объявляется переменная с именем done, совпадающем с именем переменной, объявленной в блоке кода main.
for ( int done = 1; done < howmany; done++ ) ^^^^^^^^^^^^
Эта переменная в предложении for скрывает одноименную переменную с таким же именем, объявленную во внешнем блоке кода. Ее область определения - это тело цикла for. После выхода из цикла данная переменная прекращает свое существование.
Из стандарта C++ (6.5.3 The for statement)
3 If the for-init-statement is a declaration, the scope of the name(s) declared extends to the end of the for statement.
Поэтому последняя строка вывода программы
5
уже выводит на консоль значение переменной done, которая была объявлена до цикла в блоке кода функции main
В общем случае имя, объявленное во внутренней области объявления скрывает такое же имя, объявленное во внешней области объявления
Из стандарта C++ (3.3.10 Name hiding)
1 A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).
Обратите внимание, что есть важное отличие в определении предложения for между C++ и C.
В C++ во второй части предложения for, где записывается условие, также может быть объявление.
Рассмотрите следующую демонстрационную программу
#include
int main() { int done = 5; int howmany = 3;
for ( ; int howmany = done; done-- ) { std::cout << done << std::endl; }
std::cout << '
' << howmany << std::endl;
return 0; }
Ее вывод на консоль
5 4 3 2 1
3

При каждой итерации данного цикла for
for ( ; int howmany = done; done-- ) ^^^^^^^^^^^^^^^^^^
объявляется переменная howmany, которая скрывает переменную с таким же именем, объявленную в функции main. Значение, присвоенное этой переменной, преобразуется к булевскому типу. Если оно равно 0, то условие будет ложным и произойдет выход из цикла.
После цикла выводится уже значение переменной howmany, объявленной в main
Ну, и напоследок пример, когда в предложении for сразу в двух его частях объявляются переменные, которые скрывают одноименные переменные с теми же именами, объявленные в main. После выхода из цикла эти переменные прекращают свое существование, и становятся видимыми переменные, объявленные в main
#include
int main() { int done = 10; int howmany = 20;
for ( int done = 5; int howmany = done; done-- ) { std::cout << done << std::endl; }
std::cout << '
' << done << std::endl; std::cout << howmany << std::endl;
return 0; }
Вывод этой программы на консоль
5 4 3 2 1
10 20

Предложение for в этой программе логически может быть представлено как
{ int done = 5;
Label_repeat: { int howmany = done;
if ( howmany != 0 ) { std::cout << done << std::endl; done--; goto Label_repeat; } else { goto Label_exit; } } } Label_exit: //...

вторник, 9 октября 2018 г.

Бесконечный цикл for в java

Почему при таком построение цикла for, получается бесконечные вывод нулей?
int i; for (i = 0; i < 10; i = i++) { System.out.println(i); }


Ответ

Ваше выражение: i = i++. Что здесь происходит по шагам:
Сначала i = 0 Вычисляется значение после знака равно. Это ноль: result = i = 0 Вычисляется постфиксный инкремент. Теперь i = i+1 = 1 Результат выражения записывается в i. В итоге: i = result = 0

Можно заменить на: i = ++i. Тогда:
Сначала i = 0 Вычисляется префиксный инкремент. Теперь i = i+1 = 1 Вычисляется значение после знака равно: result = i = 1 Результат выражения записывается в i. В итоге: i = result = 1

В общем, постфиксный инкремент в операторе присваивания над той же переменной ничего полезного не делает. Отсюда и Ваш бесконечный цикл.