【问题标题】:Cant seem to find reason for infinite loop似乎无法找到无限循环的原因
【发布时间】:2011-03-18 03:24:30
【问题描述】:

我正在编写一个程序来帮助为 4 年制大学安排课程。出于某种原因,我陷入了 while 循环。

/*
some info:
"course" is a class i created
   some of the member function are:
      bool fall()           // does the class run in the fall?
      bool spring()         // does the class run in the spring?
      string name()         // name of this course
      ...                   // plenty of irrelevant stuff


"classes" is a vector of courses
"vector <vector <course> > out" has n (generally 8) elements

"vector <string> taken" records the names of the courses that have been taken

bool prereq_taken(course C, vector <string> & taken) checks if all the 
prerequisites of the course are taken

even semesters are fall and odd are spring

*/


int x = 0, semester = 0;
while ((classes.size() > 0)){
    x %= classes.size();

if (prereq_taken(classes[x], taken)){                                            // checks if all of the prerequisites in the course have already been taken

    // my test condition
    //if ((semester % 2 == 0) && classes[x].fall() && (!classes[x].spring())){

    // Ben's condtion
    if ((semester & 1)? classes[x].spring(): classes[x].fall()){

    // my retardedly long all-in-one condition
    /*if (
        (((!(semester % 2)) && classes[x].fall() && (!classes[x].spring()))    // if fall and is only fall class or
        || ((semester % 2) && (!classes[x].fall()) && classes[x].spring())     // if spring and is only spring class
        || (classes[x].fall() && classes[x].spring())                          // if any semester class

        )                                                                      // and there is class space and enough credit space
        && (((out[semester].size() + 1) < classes_per_semester) && ((credits[semester] + classes[x].credits()) < credits_per_semester))) {
    */
        taken.push_back(classes[x].name());                                      // put class name into vector of takens
        out[semester].push_back(classes[x]);                                     // put class into final output
        classes.erase(classes.begin() + x);                                      // remove from class list
    }
    else
        x++;

 }
    else
        x++;                                                                         // else go to next class

    if ((out[semester].size() + 1) > classes_per_semester)
        semester++;
}

我正在尝试遍历所有数据(并循环),直到所有课程都已正确放置

由于某种原因,当我添加带有星号的 if 语句时,循环将永远继续。然而,没有它和else 的东西(但内部的东西仍在代码中),代码将完成。为什么? c++ 布尔数学与 python 的(对这段代码很重要)有些不同吗?

如果我有任何含糊之处,请告诉我要澄清什么

【问题讨论】:

  • 尝试编写正式的循环不变量。然后单步执行代码,看看不变量是否被破坏。或者写几行代码来测试不变量。
  • while 中的第一个 if 是不必要的,因为 while 只在 classes.size() > 0 时取值,所以 while 循环中的 class.size() 将始终不为 0 . 也许你需要休息一下,然后再看一下这段代码,因为你已经在 cmets 中更正了其他一些不一致的地方。问候。
  • 另外,如果在出现问题的情况下键入 !(classes[x].spring()) 而不是 (!classes[x].spring()) 会发生什么?跨度>
  • @Emmanuel:将 ! 移到括号外不会改变任何事情,优先规则会导致它已经按该顺序完成。
  • @Emmanuel: 没有特别的区别,但话又说回来,我不知道哪里出了问题,所以任何事情都可能是正确的,我只关心

标签: c++ sorting loops infinite-loop


【解决方案1】:

你认为这有什么作用?

if ((x == classes.size()))
    x %= classes.size();

赋值同:

   x = x % classes.size();

但是你才发现x == classes.size()所以

   x = classes.size() % classes.size();

对于任何NN%N 为零,这意味着

if ((x == classes.size()))
    x = 0;

这是你想要的吗?


有问题的if 只能处理仅在秋季提供的课程。也许你想要:

if ((semester & 1)? classes[x].spring(): classes[x].fall()) { ... }

也许这行得通?

int x = 0, semester = 0, scheduled = 0;
vector<string> completed;
while ((classes.size() > 0)) {
    if (classes.size() == x) {
        x = 0;
        cout << "Checked all classes and scheduled " << scheduled << endl;
        if (0 == scheduled) {
            ++semester;
            completed = taken;
        }
        scheduled = 0;
    }

    if (prereq_taken(classes[x], completed)) {
        if ((semester & 1)? classes[x].spring(): classes[x].fall()) {
            if (credits[semester] + classes[x].credits() <= credits_per_semester) {
                taken.push_back(classes[x].name());
                out[semester].push_back(classes[x]);
                credits[semester] += classes[x].credits();
                cout << classes[x].name() << " will be taken in semester " << semester << " for " << classes[x].credits() << " credits" << endl;
                classes.erase(classes.begin() + x);
                scheduled++;
            }
            else {
               cout << classes[x].name() << " can't be taken in semester " << semester << " : overload on credits" << endl;
               x++;
            }
        }
        else {
            cout << classes[x].name() << " can't be taken in semester " << semester << " : not offered" << endl;
            x++;
        }    
     }
     else {
        cout << classes[x].name() << " can't be taken in semester " << semester << " : not offered" << endl;
        x++;                                                                         // 
     }

     if (out[semester].size() >= classes_per_semester || credits[semester] >= credits_per_semester) {
        cout << "Full load reached for semester " << semester << endl;
        semester++;
        completed = taken;
     }
}

【讨论】:

  • 我将增加 if 语句以包括 spring 类。我只是想先弄清楚其中的一部分。现在...弄清楚该代码的含义...此外,它仍在循环中。但是,现在它甚至没有通过条件
  • @calccrypto:如果您有一些仅限 spring 的课程,并且没有决定何时使用它们的逻辑,那么您将有一个无限循环。您最终会得到 classes 向量,其中包含一些仅限春季的课程,并且可能有些课程具有仅限春季的课程先决条件。
  • 大声笑我怎么忘记了???但是,即使通过 ive couted 循环内的数据,它仍然无法正常工作
  • @calccrypto:我认为您对第一个错误的“修复”是错误的。实际上,在这种情况下,x = 0; 看起来并不是一件坏事。
  • @calccrypto:请注意,我很确定我可以设计一个课程目录来破坏您的算法(这是一个贪心算法,不一定是最优的)。并不是任何真正的大学都会做这样的事情,毕竟它只是强迫学生支付额外学期的学费。
【解决方案2】:

我认为问题在于您永远无法满足所有课程的要求。加星标代码

if ((semester % 2 == 0) && classes[x].fall() && (!classes[x].spring())){

只允许您参加秋季课程。如果必修课程仅在春季可用,您的代码将尝试分配课程,因为由于缺少要求而无法添加新课程。

现在,假设您修复了 if 并允许满足课程要求。您仍将依赖于正确的数据(即没有循环过程依赖)。我建议阅读topological sorting,以防您不熟悉它。处理无限循环可能性的一种简单(尽管效率低下)的方法是使用以下观察:在整个课程列表的每一步中,应该至少从列表中删除一门课程。所以你可以这样写:

int x = 0, semester = 0, prev_size = classes.size();
while ((classes.size() > 0)){
    if (x == classes.size()){
        x = 0;
        if( classes.size() == prev_size ) { // no courses removed in the last cycle
            // signal error
            break;
        }
        else
            prev_size = classes.size();
    }
    ...
}

【讨论】:

    【解决方案3】:

    &amp; 本身就是一个位与。你想要一个&amp;&amp;。 if 语句中的那部分可能永远不会到达,所以大小不会改变。

    【讨论】:

    • 我不认为他想要&amp;&amp;semester &amp;&amp; 1?
    • 我不希望它是按位的吗?我想看看int semester 是偶数还是奇数
    • @calccrypto:检查奇数偶数的正确方法是:i % 2 == 0 /* even */。按位 hack 没有偶数或奇数的定义,从技术上讲不能保证总是有效。
    • semester % 2 == 0 使用模数。 & 1 位读者不清楚。
    • @calccrypto:编译器会将semester &amp; 1semester % 2 转换为完全相同的指令。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 2018-05-06
    • 2019-10-11
    • 2023-04-05
    • 2021-12-16
    • 1970-01-01
    • 2014-07-09
    相关资源
    最近更新 更多