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)

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

Да какая разница, как обозван тип, главное идея, а твой (i++ <= 255) всегда true

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

Это я просто частный случай рассматриваю. Бывают похожие ситуации и с максимально возможным размером целого.

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

Я просто объявляю b тем же типом, что и a, и заранее присваиваю ему значение на 1 больше.

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

Чем окончание цикла. Т.о. если мне нужно от 0 до 255, то a = 0 и b = 255 + 1, т.е. b == 0, и всё океюшки.

unC0Rr ★★★★★
() автор топика

магия чисел:

    
    char volatile c;
    char cnt = 255;
    for (c=0;cnt ^= c;c++) {
        printf("%i\n",c);
    }

я естесвенно наврал, но всё равно весело

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)
Ответ на: комментарий от zurg

зацикливается при b ==255

Зацикливается, потому что я забыл тип скастовать. Сам алгоритм рабочий. Вот правильный вариант:

#include <stdio.h>

int main()
{
        unsigned char a = 250;
        unsigned char b = 255;

        unsigned char i = a; 
        do {
                printf("%u\n", (unsigned)i);
                i++;
        } while (i != (unsigned char)(b + 1));
}
geekless ★★
()
Ответ на: комментарий от zurg

i = 0, ++i, сравниваем с b. Всё ок тут, и без зацикливаний. Если b == 254 + 1, то i, естественно, через 255 итераций станет равен 255 перед сравнением с b, и цикл завершится.

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

Он не запрещает и b < a, но это менее интересно, чем заданный вопрос.

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

С ума сойти можно, но начальное число и конечное заранее не фиксированы. Или можно будет сравнивать с a?

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

Так, или заранее прибавить эту единичку к b (как я и сделал)

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

код с a и b

 
    unsigned int a=(unsigned int)atoi(argv[1]),
                 b=(unsigned int)atoi(argv[2]);
    unsigned char cnt = 1+(a==0);
    for (c=a;(cnt-=!c)&&(c<=b);++c) {
        printf("%i\n",c);
    }

тесты:

tmp % ./a.out 0 1 
0
1

tmp % ./a.out 253 255
253
254
255

tmp % ./a.out 0 255 | wc -l
256

вобще c-=!a, счётчик того сколько раз a==0 т.е. переполнилось, соотв c=разрешённоекол-во раз + является ли нулём первое значение

qnikst ★★★★★
()

Это не прямой перевод в си.

Прямым будет с использованием if и goto, потому как сишный for не равен паскалевскому.

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

Да, естественно, не равен, оттого и проблемы :)

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

маловероятно.. действий лишних многовато

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

Нет, но чем чёрт не шутит. Дело в том, что сишный код компилится в байткод llvm, который затем компилится в js

unC0Rr ★★★★★
() автор топика
Последнее исправление: unC0Rr (всего исправлений: 1)
Ответ на: комментарий от unC0Rr

чем чёрт не шутит

В этом коде содержатся ПРИСВАИВАНИЕ, ТРИ СРАВНЕНИЯ и ДВА ВЕТВЛЕНИЯ.

Нет, ТАК даже черт не шутит. :)

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

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

PolarFox ★★★★★
()
#include <stdio.h>
#include <stdint.h>

int
main (void)
{
  uint8_t a = 4,
          b = 4,
          c = 0;

  c = a;
  do
    {
      printf ("%d,", c);
    }
  while (++c != (uint8_t) (b + 1));

  return 0;
}

Но компилятор, вероятно, под выражение (uint8_t) (b + 1) выделит всё-равно ещё один байт.

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

PolarFox

имитация побитового дрочева на js

Насколько я знаю, там встроенные побитовые операции, а не эмуляция.

PolarFox

лучше бы написали ллвмный компилятор паскаля.

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

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

0 <= a < b <= 255

Если хочется 0 <= a <= b <= 255, то

// unsigned char a,b;
if(a > b) return;
unsigned char i = 0;
b++; 
do{
  …
  }while(++i != b); 
«Плохие точки»:

  1. a = b = 0
    unsigned char i = 0;
    b++; // b == 1
    do{
      …
      }while(++i != b); // 1 == 1 -> выходим
    
  2. a = b = 255
    unsigned char i = 255;
    b++; // b == 0
    do{
      …
      }while(++i != b); // 0 == 0 -> выходим
    
  3. другие варианты
    // a!=b
    unsigned char i = a;
    b++; // b == b+1, если b!=255, иначе b == 0
    do{
      …
      }while(++i != b); 
    
    если a == 0, b == 255, то первый while даст 1 != 0 когда i == 255, последний While даст 0 == 0 -> выход
Eddy_Em ☆☆☆☆☆
()
Последнее исправление: Eddy_Em (всего исправлений: 2)
Ответ на: комментарий от backbone

Хрень какую-то написал, так надо:

#include <stdio.h>
#include <stdint.h>

int
main (void)
{
  uint8_t a = 0,
          b = 255,
          c;

  c = a;
  do
    {
      printf ("%d,", c);
    }
  while (c++ != b);

  return 0;
}

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

Не понимаю пока что.

cc uint8.c && ./a.out
255,
(там постинкремент)

backbone ★★★★★
()
Последнее исправление: backbone (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.