不使用goto语句重写程序

Mis*_*ker 1 c++ algorithm

我不得不使用goto语句编写类似的问题.现在我们被要求在不使用goto语句的情况下重写代码.我不知道如何开始这个程序.我使用goto粘贴以前的程序代码.

// Eight Queens problem using one dimesional array and goto statement

#include "stdafx.h"
#include <iostream>
using namespace std;


int main()
{
    int q[8];
    q[0] = 0;
    int c = 0;
    int count = 0;

NC: //cout  << "Next column\n" << "Column = " << c << endl;
    c++;
    if (c == 8) goto print;
    q[c] = -1;

NR: //cout << "Next row\n" << "Row = " << q[c] << "\nColumn = " << c << endl;
    q[c]++;
    if (q[c] == 8) goto backtrack; 
    for(int i = 0; i < c; i++){
        if(q[i] == q[c] || abs(q[c] - q[i]) == (c - i))
            goto NR;
    }
    goto NC;

backtrack:
    //cout << "Backtrack" << endl;
    //cout <<"Column = " << c << endl;
    c--;
    if(c == -1) return 0;
    goto NR;

print:
    //cout << "print" << endl;
    ++count;
    cout << count << endl;
    for(int i = 0; i <= 7; i++){
            cout << q[i];
    }
    cout << endl;
    goto backtrack;


    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这个程序是教授为课程发布的一个提示.

 #include <iostream>
    #include<cstdlib>
    #include <cmath>
    using namespace std;

    bool ok(int q[], int col){
    if the configuration is “bad” return false;
    else
    return true;
    }

    void backtrack(int &col){
    col--;
    if(col==-1) exit(1);
    }

    void print(int q[]){
    static int count =0;
    print the array q
    }

    int main(){
    int q[8]; q[0]=0;
    int c=1;
    // from_backtrack keeps track if we need to reset the row to the
    // top of the current colum or not.

    bool from_backtrack=false;
    // The outer loop keeps looking for solutions
    // The program terminates from function backtrack
    // when we are forced to backtack into column -1
    while(1){
    while(c<8){ //this loop goes across columns
    // if we just returned from backtrack, use current value of row
    // otherwise get ready to start at the top of this column
    if(!from_backtrack) // we did not just return from backtrack
    Code goes here
    from_backtrack=false;
    while(q[c]<8){ // place queen in this column
    q[c]++;
    // if row=8, there is no valid square in this column
    // so backtrack and continue the loop in the previous column
    Code goes here
    //if this position is ok, place the queen
    // and move on (break) to the next column,
    // otherwise keep looking in this column
    Code goes here
    }
    c++; // placed ok, move to the next column
    }
    // one complete solution found, print it.
    print(q); // board completed, print it out
    backtrack(c);
    from_backtrack=true;
    }
    }
Run Code Online (Sandbox Code Playgroud)

这是我为完成该计划所做的尝试

// NoGoto.cpp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;



bool attack(int q[], int col){
    if(q[i] == q[c] || abs(q[c] - q[i]) == (c - i)) return false;
    else
        return true;
} // Attack

void backtrack(int & col){
    col--;
    if(col == -1) exit(1);
} // Backtrack

void print(int q[]){
    static int count = 0;
    ++count;
    cout << count << endl;
    for(int i = 0; i < 8; i++)
        cout << q[i];
    cout << endl;
}
int main()
{
    int q[8];
    q[0] = 0;
    int c = 1;

    bool from_backtrack = false;

    while(1){
        while(c < 8){ // this loops across columns

            if(!from_backtrack)
                attack(q[c],c)

            from_backtrack = false;

            while(q[c] < 8){ // place queen in this column
                q[c]++;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

"我在编写代码时遇到了问题.如何[我可以]调用每个函数以使其正确找到解决方案?"

Pot*_*ter 6

首先,只需通过剥离其他所有内容并添加显式gotos来执行,通过直线执行到达标签来查看控制流.

NC: if (…) goto print;
    goto NR;

NR: if (…) goto backtrack;
    if (…) goto NR;
    goto NC;

backtrack:
    if (…) return;
    goto NR;

print:
    goto backtrack;
Run Code Online (Sandbox Code Playgroud)

现在,采取无条件的getos并尝试移动块,使它们代表直线执行.

NR: if (…) goto backtrack;
    if (…) goto NR;
    goto NC;

NC: if (…) goto print;
    goto NR;

print:
    goto backtrack;

backtrack:
    if (…) return;
    goto NR;
Run Code Online (Sandbox Code Playgroud)

现在消除直线的结果

NR: if (…) goto backtrack;
    if (…) goto NR;

NC: if (…) goto print;
    goto NR;

print:

backtrack:
    if (…) return;
    goto NR;
Run Code Online (Sandbox Code Playgroud)

请注意,包含所有后向gotos的标签是一个循环:

for (;;) {
NR: if (…) goto backtrack;
    if (…) continue;

NC: if (…) goto print;
    continue;

print:

backtrack:
    if (…) return;
}
Run Code Online (Sandbox Code Playgroud)

嗯,我们可以扭转NC: if()和消除的感觉goto print.而goto backtrack刚刚跳过某些语句,这相当于另一逆转if.

for (;;) {
NR: if (! …) {
        if (…) continue;
NC:     if (! …) continue;
print:
    }
backtrack:
    if (…) return;
}
Run Code Online (Sandbox Code Playgroud)

循环没有条件,但backtrack: … if(…) return;只是退出它,所以将该块和条件移动到循环中.

for (;…; /* backtrack */ …) {
NR: if (! …) {
        if (…) continue;
NC:     if (! …) continue;
print:
    }
}
Run Code Online (Sandbox Code Playgroud)

看起来很不错,没有更多的东西,没有"可疑"的结构!但是,NC应该是切入点.

这是盲目,机械,编译器转换失败的地方.我看到三种选择:

  1. 引入变量以强制执行第一次循环迭代.goto在我看来,这比这更丑陋.
  2. 将a goto NC;作为a switch(0)和call标签伪装NC:case 0:.老师可能不会接受这种妥协.
  3. 将块复制NC到循环的末尾并粘贴到循环的开头上方.然后,您可以将它们分解为函数.实际上,这是一种盲目的机械转型.万岁.我也代表NRbacktrack作为统一的功能.

.

NC();
if (…) {
    print();
}

while ( backtrack(), … ) { // <- note comma operator
    NR();
    if (! …) {
        if (…) continue;
        NC();
        if (! …) continue;
        print();
    }
}
Run Code Online (Sandbox Code Playgroud)

可能有一个更优雅的解决方案,包括查看代码的内容,但这需要较少的思考.