LINUX.ORG.RU

Цикл по всем возможным значениям

 


0

1

Как в Си перебрать все значения от a до b, где 0 <= a < b <= 255, используя 8-битный итератор?

Вопрос возник в связи с написанием конвертера кода из паскаля в Си. В самом паскале пишешь просто

var i: byte;
...
for i:= 0 to 255 do
, а прямой перевод на Си не прокатывает:
for(uint8 i = 0; i <= 255; ++i)

★★★★★
Ответ на: комментарий от qnikst

только не говорите, что a и b тут это uint8.

а вот не надо тут думать. Пусть об оптимальном размере переменной компилятор/интерпретатор думает :)

Bad_ptr ★★★★★
()
Ответ на: комментарий от Bad_ptr

а вот не надо тут думать. Пусть об оптимальном размере переменной компилятор/интерпретатор думает :)

Вы действительно читали пост ТС и поняли его проблематику?

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Вы действительно читали пост ТС и поняли его проблематику?

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

Bad_ptr ★★★★★
()

Честно прочитал все коменты

Парни, вы обкурились что ли?

uint8 i=a;
uint8 b=что-то там;
do { 
// ваш код 
if(i^255) break; 
} while (i++);

Что проще-то??? Работает при любых условиях. Если хотите, чтобы в начале было a<=b - добавьте проверку перед do-while.

p.s. Совет автору - повнимательней посмотреть утилиты. В линукс есть такие утилиты. Посмотреть исходники никто не запрещает.

Milker
()
Ответ на: комментарий от Milker

не хватило ума заменить 255 на b?

ты идиот? это ничего не изменит, твой пример все-равно нерабочий

wota ★★
()
Ответ на: комментарий от wota

Тут задача стояла не родить читаемый код, а родить транслятор в компилируемый, да так, чтобы без сюрпризов.

PolarFox ★★★★★
()

Зачем итератор обязательно 8-битный? Впрочем, даже если преобразования типов хочется избежать, то так можно:

unsigned char i=0;
for(int c=0; c<256; c++, i++)

Кстати, что интересно, оптимизатор это дело разворачивает до одной переменной цикла.

KRoN73 ★★★★★
()
Ответ на: комментарий от wota

LOL, ты хотел незаметно исправить, но все-равно сделал не так, слейся

Сам сливайся умник. Я исправил свою ошибку. Код рабочий. Если хочешь могу и без этой конструкции сделать. Будет еще короче, но читаемость при этом снизиться.

uint8 i=a;
uint8 b=что-то там;
do { 
// ваш код 
} while (i++ ^ b);
Milker
()
Ответ на: комментарий от KRoN73

Собственно, это именно Си и приучил к тому, что i — обычно int.

До этого в Basic'е в FOR I=1 TO 255 : ... I обычно был вообще плавучим :)

KRoN73 ★★★★★
()
Ответ на: комментарий от geekless

При чем тут названия переменных, если я про тип.

Думаю, тебя сбила именно аналогия c == char. Иначе бы ты увидел определение типа в for и перед ним.

KRoN73 ★★★★★
()
Ответ на: комментарий от Milker

Я исправил свою ошибку. Код рабочий

не а, не рабочий, ты явно не знаешь даже основ С, думай дальше, можешь также подумать почему твой код был и быдлокодерским

wota ★★
()
Ответ на: комментарий от Milker

p2c - 93й год. Проще самому налабать конвертер под свои нужды, чем разгребать и править чужие исходники на си.

PtoC ещё более древний, даже поддержка TP7.0 не заявлена.

Свой же вариант уложился в 2000 строк быдлокода на хаскеле. Отдельно препроцессор, отдельно парсер и отдельно конвертер-рендерер в си.

unC0Rr ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Зачем итератор обязательно 8-битный?

Чтобы прделагали решение, а не обход. Ровно та же ситуация может приключиться и с 16-, и с 32-битными итераторами.

unC0Rr ★★★★★
() автор топика
Ответ на: комментарий от unC0Rr

даже поддержка TP7.0 не заявлена.
Свой же вариант уложился в 2000 строк быдлокода на хаскеле

если говорить про полную поддержку TP7.0 - гарантированно не уложится

wota ★★
()
Ответ на: комментарий от wota

не а, не рабочий, ты явно не знаешь даже основ С, думай дальше, можешь также подумать почему твой код был и быдлокодерским

/home/temp/pogramming$ cat proba.c
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
    unsigned char i, a, b;
    a = 250;
    b = 255;
    i = a;
    do {
	printf("%d\n", i);
    } while (i++^b);
    
}

/home/temp/pogramming$ gcc -o proba proba.c
/home/temp/pogramming$ ./proba
250
251
252
253
254
255

В чем выражается нерабочесть кода и быдлокодерство? Можно и экстремальный случай взять.

/home/temp/pogramming$ cat proba.c
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
    unsigned char i, a, b;
    a = 254;
    b = 3;
    i = a;
    do {
	printf("%d\n", i);
    } while (i++^b);
    
}

/home/temp/pogramming$ gcc -o proba proba.c
/home/temp/pogramming$ ./proba
254
255
0
1
2
3

Ну-ка покажи конкретно, где я не знаю основ С? Может я с тобой и соглашусь. Я прислушиваюсь к мнению знатоков, а не пустозвонов.

Milker
()
Ответ на: комментарий от Milker

мои искренние поздравления - твой третий вариант наконец-то рабочий, две предыдущие попытки сделать цикл от a до b провалились, но ты все-равно крут, так держать!

wota ★★
()
Ответ на: комментарий от unC0Rr

Ровно та же ситуация может приключиться и с 16-, и с 32-битными итераторами.

Я с трудом представляю себе на современных машинах проблему с 64-х битным итератором :) Даже при 4Млрд циклов в секунду потребуется 150 лет на переполнение :)

KRoN73 ★★★★★
()
Ответ на: комментарий от wota

wota

если говорить про полную поддержку TP7.0 - гарантированно не уложится

Конечно, нет. Но мне конвертер нужен для одной конкретной программы в которой не используются большинство возможностей даже TP7.0, хотя есть и некоторые современные элементы языка из фрипаскаля.

unC0Rr ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

Дело не в переборе полного диапазона, а в том, что заранее a и b неизвестны, и они могут попадать на экстремальные значения целого.

unC0Rr ★★★★★
() автор топика
Ответ на: комментарий от wota

мои искренние поздравления - твой третий вариант наконец-то рабочий, две предыдущие попытки сделать цикл от a до b провалились, но ты все-равно крут, так держать!

Ты неправ. Мой вариант с

if(!(i^b)) break;
тоже рабочий.

Насчет основ С. Цикл do....while выполняется пока истинно условие, записанное после while. В языке С все что не 0 - это истина, соответственно 0 это ложь. Исходя из этого, код

 do {
...........
} while (i++);
будет работать пока i>=0. Почему включая 0, я думаю вы догадались? Исходя из условия, что a < b, это не принципиально. Но если вы эстет, можете поставить ++i, тогда цикл будет работать пока i != 0.

Milker
()
Ответ на: комментарий от Milker

тоже рабочий.

while (i++)

конечно, рабочий на все 100%

wota ★★
()
Ответ на: комментарий от Milker

Почему включая 0, я думаю вы догадались?

потому-что, если i == 0, то цикл не пойдет дальше первой итерации? ;)

wota ★★
()
Ответ на: комментарий от wota

Вы отчасти правы ))) Я с вами согласен. Еще одна ошибка, ибо писалось ночью со слипшимися глазами.

Но кроме того. Конструкция while (i++) сначала проверяет условие и только потом делает инкремент. В нашем случае, происходит следующее:

1. На предыдущем цикле итерации i==255. Выполняется код в блоке do...while.

2. Проверяется условие, которое дает истину, так как i != 0.

3. Делается инкрементация. Сейчас i==0

4. Выполняется код в блоке do...while

5. Проверяется условие. И только сейчас происходит выход их цикла, так как условие дает ложь.

В нашем случае это не принципиально, так как a < b. Хотя с учетов того, что изначально a и b неизвестны, то попадание i==0 вполне возможно.

p.s. Советую вам изучить основы С, прежде чем советовать это другим.

Milker
()
Ответ на: комментарий от Milker

p.s. Советую вам изучить основы С, прежде чем советовать это другим.

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

wota ★★
()
Ответ на: комментарий от wota

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

Давайте не будем, согласен. Это были опечатки, а не ошибки. Что я и собственно говоря признал, так как внес исправления. И еще если бы это были ошибки и я не знал основ, то мой последний вариант был бы, наверное, совсем другим.

Кроме того, я объяснил свой код. А вы так и не удосужились объяснить, где тут быдлокодерство и ошибки. Кстати, в алгоритме я ошибки не делал, были опечатки в набивании кода.

Milker
()
Ответ на: комментарий от Milker

А вы так и не удосужились объяснить, где тут быдлокодерство и ошибки
были опечатки в набивании кода.

ну как скажешь, только согласись - не очень убедительно заявлять «вы обкурились что ли?», при том дав совершенно нерабочий пример, я конечно тоже зря перестарался с выражениями, давай прикрывать наш ненужный флуд

wota ★★
()
Ответ на: комментарий от wota

я конечно тоже зря перестарался с выражениями, давай прикрывать наш ненужный флуд

Согласен. Флуд закрыт :) Насчет «обкурились». Это была реакция на код

 for (c=a;(cnt-=!c)&&(c<=b);++c) 

:) Если парни решили поприкалываться, то ладно. Но писать такое в простейшей задачке....

Milker
()
Ответ на: комментарий от wota

при том дав совершенно нерабочий пример

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

Milker
()
Ответ на: комментарий от unC0Rr

они могут попадать на экстремальные значения целого

Осталось придумать, как ввести целое большее, чем машинная разрядность и не заметить этого.

KRoN73 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.