【问题标题】:Standard idiom for executing a while loop one more time再次执行 while 循环的标准习惯用法
【发布时间】:2015-06-11 02:01:31
【问题描述】:

C 中是否有一种模式可以再执行一次 while 循环。 目前我正在使用

while(condition) {
    condition = process();
    // process() could be multiple lines instead of a function call
    // so while(process());process(); is not an option
}
process();

如果进程是多行而不是单个函数调用,那就太可怕了。

另一种选择是

bool run_once_more = 1;
while(condition || run_once_more) {
    if (!condition) {
        run_once_more = 0;
    }
    condition = process();
    condition = condition && run_once_more;
}

有没有更好的办法?


注意:do while 循环不是解决方案,因为它等同于

process();
while(condition){condition=process();}

我想要

while(condition){condition=process();}
process();

根据请求,更具体的代码。 我想从 another_buffer 填充缓冲区并获取 (indexof(next_set_bit) + 1) 到 MSB,同时保持掩码和指针。

uint16t buffer;
...
while((buffer & (1 << (8*sizeof(buffer) - 1))) == 0) { // get msb as 1
    buffer <<= 1;
    // fill LSB from another buffer
    buffer |= (uint16_t) (other_buffer[i] & other_buffer_mask);
    // maintain other_buffer pointers and masks
    other_buffer_mask >>= 1;
    if(!(other_buffer_mask)) { 
        other_buffer_mask = (1 << 8*sizeof(other_buffer[0]) -1)
        ++i;
    }
}
// Throw away the set MSB
buffer <<= 1;
buffer |= (uint16_t) (other_buffer[i] & other_buffer_mask);
other_buffer_mask >>= 1;
if(!(other_buffer_mask)) { 
    other_buffer_mask = (1 << 8*sizeof(other_buffer[0]) -1)
    ++i;
}
use_this_buffer(buffer);

【问题讨论】:

  • process is of multiple lines and not a single function call 然后进行(可能是内联的)函数调用。
  • do ... while (condition); 在某些情况下还可以提供额外的迭代。
  • @chux 如果在最后一次调用中也修改了条件就可以了。尽管如此,do while 循环会NOT 进行额外的迭代 条件为假。看我的笔记。
  • 你能告诉用户更多关于condition的信息吗?是数字还是什么?
  • @black 添加了更多信息。

标签: c while-loop idioms


【解决方案1】:

因为这不是一件非常典型的事情,所以不太可能有一个标准的习惯用法来做这件事。但是,我会这样编写代码:

for (bool last = 0; condition || last; last = !(condition || last)) {
    condition = process();
}

只要condition 为真,循环就会执行,然后再执行一次,或者如果condition 在循环开始时为假,则执行零次。我将您的问题解释为这意味着这是所需的行为。如果不是,并且您总是希望循环至少执行一次,那么do...while 就是您要寻找的成语。

【讨论】:

  • ++0,这感觉是迄今为止最优雅的解决方案。
【解决方案2】:

这个呢:

int done, condition = 1;
for (;;) {
    ...
    done = !condition;
    condition = process();
    if (done) break;
    ...
}

我并不是说这是一个标准的成语,只是一个临时的 hack。

【讨论】:

    【解决方案3】:

    我会用这个:

    bool done = false;
    do {
      if (!condition) done = true;
      condition = process();
    } while (!done);
    

    假设condition 未预定义,则可读性要差得多:

    for (bool condition=true, done=false;
         !done && (condition || done = true);
        ) {
      condition = process();
    }
    

    【讨论】:

    • condition 必须定义为非 0 且在 do/while 条件结束后缺少分号。
    • @chqrlie:在 OP 中,condition 是预先存在的。我假设它来自以前的一些计算。如果不是这样,那么它必须定义,是的。
    【解决方案4】:

    我也遇到了同样的问题,我的解决方案是:

    仅当您确定要运行 process() 至少一次时:

    while(1){
        process();
        if(!condition()) break;
        /*The loop breaks before bad things happen*/
        things_you_want_to_happen_only_while_condition_is_true();
    }
    

    如果您不确定:

    if(condition()){ /*Same as before, but it checks first*/
        while(1){
            process();
            if(!condition()) break;
            /*The loop breaks before bad things happen*/
            things_you_want_to_happen_only_while_condition_is_true();
        }
    }
    

    例如:

    /*A pointer that goes over the string T from right to left.
    It prints "Yes" when pointing at the character 'O' and "No" when not*/
    char T[] = {'O', 'V', 'E', 'R', 'F', 'L', 'O', 'W', 0};
    char *P = &T[strlen(T)-1]; /*We want the pointer to start at the last character of T*/
    while(1){
        if(*P=='O') printf("Yes\n");
        else printf("No\n");
        if(P==&T[0]) break; /*When it reaches the beginning of T, it stops*/
        /*We only want the pointer to go further back if it is not in the beginning of T.
        That's because we don't know what's before in the memory.*/
        P--;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-08-12
      • 1970-01-01
      • 1970-01-01
      • 2019-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      相关资源
      最近更新 更多