Unsigned int odwraca iterację za pomocą pętli for

Chcę, aby zmienna iteratora w pętli for odwróciła iterację do 0 jako unsigned int, i nie mogę wymyślić podobnego porównania do i > -1, jak zrobiłbyś, gdyby była to signed int.

for (unsigned int i = 10; i <= 10; --i) { ... }

Wydaje się to jednak bardzo niejasne, ponieważ opiera się na liczbowym przepełnieniu niepodpisanej liczby całkowitej powyżej 10.

Może po prostu nie mam jasnego umysłu, ale jaki jest lepszy sposób, aby to zrobić...

Zastrzeżenie: jest to tylko prosty przypadek użycia, górna granica 10 jest trywialne, może to być cokolwiek, a i musi być unsigned int.

Author: deceleratedcaviar, 2011-03-28

14 answers

Możesz użyć

for( unsigned int j = n; j-- > 0; ) { /*...*/ }

Iterates from n-1 down To 0.

 45
Author: Serge Dundich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-26 18:27:31

Następująca robi to, co chcesz:

for (unsigned i = 10; i != static_cast<unsigned>(-1); --i)
{
    // ...
}

To jest doskonale zdefiniowane i faktycznie działa. Arytmetyka na typach podpisanych jest dokładnie określona przez standard. Rzeczywiście:

Od 4.7/2 (w odniesieniu do odlewania do typu niepodpisanego):

Jeśli typ docelowy jest niepodpisany, wartość wynikowa jest najmniejszą niepodpisaną liczbą całkowitą zgodną ze źródłową liczbą całkowitą (modulo 2^n, gdzie n jest liczbą bitów używanych do reprezentowania niepodpisanej typ)

Oraz 3.9.1/4

Niepodpisane liczby całkowite, zadeklarowane niepodpisane, spełniają prawa arytmetyki modulo 2^n, gdzie n jest liczbą bitów w reprezentacji wartości tego konkretnego rozmiaru liczby całkowitej

 24
Author: Alexandre C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 11:34:56

Mój wzór na to jest zazwyczaj...

for( unsigned int i_plus_one = n; i_plus_one > 0; --i_plus_one )
{
    const unsigned int i = i_plus_one - 1;
    // ...
}
 3
Author: Adam Bowen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 12:05:38

Czy naprawdę iterujesz z jakiejś liczby większej niż std::numeric_limits<int>::max()? Jeśli nie, sugerowałbym użycie zwykłej int jako zmiennej pętli i static_cast do unsigned w miejscach w kodzie, które oczekują, że będzie niepodpisana. W ten sposób możesz użyć intuicyjnego warunku >= 0 lub > -1 i ogólnie spodziewałbym się, że będzie on bardziej czytelny niż jakakolwiek z niepodpisanych alternatyw.

static_cast byłoby po prostu powiedzieć kompilatorowi jak operować na zmiennej i nie mieć wydajności implikacje w ogóle.

 3
Author: Mark B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-06 15:22:44

Myślę, że dwie opcje są albo rzucone lub pojedyncze liczby (można to zrobić domyślnie porównując do -1, na przykład) lub użyć warunku pętli, aby sprawdzić przepełnienie w ten sposób:

for(unsigned i=10;i>i-1;--i){ } // i = 10, 9, ... , 1
for(unsigned i=10;i+1>i;--i){ } // i = 10, 9, ... , 1,0

Ta pętla będzie kontynuowana, dopóki nie przepełnię się (co oznacza, że osiągnął zero). Zauważ, że ważne jest, aby i iterował przez 1, lub możesz skończyć z nieskończoną pętlą.

 2
Author: Noam Weiss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 11:36:22

Unikanie niedociągnięć

unsigned int i = n;
while (i !=0){
--i;
...
}
 2
Author: halcon_cxx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-04 03:57:43

Użyłbym dwóch zmiennych:

unsigned int start = 10;
for (unsigned int j = 0, i = start; j <= start; ++ j, -- i) {
    // ...
}

Możesz również użyć pętli while:

unsigned int start = 10;
unsigned int i = start + 1;
while (i --) {
    // ...
}
 1
Author: Sylvain Defresne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 11:35:54
for(unsigned i = x ; i != 0 ; i--){ ...

I jeśli chcesz wykonać ciało pętli, Gdy i = = 0 i zatrzymać po tym. Zacznij od i = x+1;

BTW, dlaczego muszę być niepodpisany ?

 0
Author: BenjaminB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 11:29:04

Możesz spróbować zdefiniować następujące makro:

#define for_range(_type, _param, _A1, _B1) \
    for (_type _param = _A1, _finish = _B1,\
    _step = static_cast<_type>(2*(((int)_finish)>(int)_param)-1),\
    _stop = static_cast<_type>(((int)_finish)+(int)_step); _param != _stop; \
_param = static_cast<_type>(((int)_param)+(int)_step))

Teraz możesz go użyć:

for_range (unsigned, i, 10,0)
{
    cout << "backwards i: " << i << endl;
}
Może być używany do iteracji do tyłu i do przodu poprzez unsigned, integers, enums i chars:
for_range (char, c, 'z','a')
{
    cout << c << endl;
}

enum Count { zero, one, two, three }; 

for_range (Count, c, zero, three)
{
    cout << "forward: " << c << endl;
}

Pomimo niezręcznej definicji jest bardzo dobrze zoptymalizowany. Patrzyłem na disassembler w VC++. Kod jest niezwykle wydajny. Nie zniechęcaj się, ale trzy instrukcje for: kompilator wytworzy tylko jedną pętlę po optymalizacji! Można nawet zdefiniować zamknięte pętle:

unsigned p[4][5];

for_range (Count, i, zero,three)
    for_range(unsigned int, j, 4, 0)
    {   
        p[i][j] = static_cast<unsigned>(i)+j;
    }

Oczywiście nie można iterować przez typy wyliczone z lukami.

 0
Author: Mikhail Semenov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-20 12:52:04

Jestem nowy w c++, moja odpowiedź może być naprawdę głupia, ale robię to dla tego rodzaju pętli odwrotnych;

size_t count = 3;
size_t newCount = 0;
if (count > 0)
    for (size_t i = count - 1; i >= newCount; i--)
    {
        //do your work here

        //and at the end
        if (i == 0)
            break;
    }
I działa. ponieważ część" i-- " w pętli wykonanej w następnym kroku, break powinien działać poprawnie. jak myślisz, czy ta droga jest Bezpieczna ?
 0
Author: Ibrahim Ozdemir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-13 05:11:23

Oto prosty trik na przepełnienie jajowodu, jeśli i powtarza się przez 1:

for(unsigned int i = n-1; i+1 >= 1; i--) {;}

If you want i to iterate for more than 1:

unsigned int d = 2;
for(unsigned int i = n-1; i+d >= d; i-=d) {;}
 0
Author: hmofrad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-15 02:09:02
for (unsigned int i = 10; i <= 10; --i)
Masz to w jednym.

Nie chcę ci dać odpowiedzi na twoje dziesięcioletnie pytanie, ale próba uniknięcia niedopełnienia spowoduje zaciemnienie tego, co próbujesz ostatecznie zrobić.

Unsigned integer jest dobrze zdefiniowanym zachowaniem, na którym można polegać i oczekiwać, że inni programiści zrozumieją. Wszelkie obejście sprawi, że zakres, na którym próbujesz działać, będzie trudniejszy do przeanalizowania i prawdopodobnie będzie tak samo mylący dla początkującego, przekazując nie jest to dobry przykład, jeśli powinni go odebrać jako" lekcję " w odwrotnej kolejności dla pętli

 0
Author: Anne Quinn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-06 06:58:31

Po Prostu:

int start = 10;
for(unsigned int iPlus1 = start + 1 ; iPlus1 > 0 ; iPlus1--) {
  // use iPlus1 - 1 if you need (say) an array index
  a[iPlus1 - 1] = 123; // ...
}
Nie?
 -1
Author: Ash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 14:08:02

Jeszcze jedna droga:

for(unsigned i = n-1; i < n ; --i) 
{       
    // Iterates from n-1 to 0
}

Simillarly for size_t (unsigned integer type) użyj tej samej sztuczki

for(std::size_t i = n-1; i < n ; --i) 
{       
    // Iterates from n-1 to 0
}
 -1
Author: SridharKritha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-26 15:20:12