我的代码在一些(未知)情况下出现运行时错误,而在其他情况下运行良好。我的代码有什么问题吗? [已关闭]

问题描述 投票:0回答:1

这是著名逻辑学家走在酒吧谜语中的代码(问题 - https://www.codechef.com/problems/LOGICIAN) 这是我的代码:

#include <iostream>
using namespace std;

int main() {
    // your code goes here
    int T;
    cin >> T;
    for(int i=0;i<T;i++){
        int N;
        cin >> N;
        char beer[N];
        cin >> beer;
        int idk=1;
        for(int j=0;j<(N-1);j++){
            if(beer[j]=='1' && idk==1){cout << "IDK" << endl;}
            if(beer[j]=='1' && idk!=1){cout << "NO" << endl;}
            if(beer[j]=='0'){cout << "NO" << endl;idk=0;}
           
        }
        if(beer[N-1]=='1' && idk==1){cout << "YES" << endl;}
        if(beer[N-1]=='1' && idk!=1){cout << "NO" << endl;}
        if(beer[N-1]=='0' ){cout << "NO" << endl;}
    }
    return 0;
}

我的测试用例出现运行时错误,否则它工作正常。

c++ runtime-error
1个回答
0
投票

所以,这真是一个谜。 据我所知,您的代码存在一些风格问题,但是正确的。它应该有效。我将在接下来的几行中证明这一点。

让我们开始研究内循环:

if(beer[j]=='1' && idk==1){cout << "IDK" << endl;}
if(beer[j]=='1' && idk!=1){cout << "NO" << endl;}
if(beer[j]=='0'){cout << "NO" << endl;idk=0;}

由于

idk
被视为布尔值,我宁愿选择:

if (idk == 1) {
    if (beer[j]=='1') {
        cout << "IDK" << endl;
    } else {
        cout << "NO" << endl;
        idk = 0;
    }
} else {
    cout << "NO" << endl;
}

让我们证明它与您的代码完全等效。如果提取出四种可能的执行路径(假设

beer[j]
只能是
'0'
'1'
),你会得到:

if (idk == 1 && beer[j]=='1') { cout << "IDK" << endl; }
if (idk == 1 && beer[j]=='0') { cout << "NO" << endl; idk=0; }
if (idk != 1 && beer[j]=='1') { cout << "NO" << endl; }
if (idk != 1 && beer[j]=='0')) { cout << "NO" << endl; }

与之前有一个细微的差别:第一次之后,

idk
没有在
0
上设置为
beer[j]=='0'
- 但这当然在逻辑上不相关:我们可以在所有分支中将
idk
设置为
0
,其中已经是
!=1
,对结果没有影响。让我们来做吧:

if (idk == 1 && beer[j]=='1') { cout << "IDK" << endl; }
if (idk == 1 && beer[j]=='0') { cout << "NO" << endl; idk=0; }
if (idk != 1 && beer[j]=='1') { cout << "NO" << endl; idk=0; } // idk=0; does nothing
if (idk != 1 && beer[j]=='0')) { cout << "NO" << endl; idk=0; } // idk=0; does nothing

您现在可以将第二行和最后一行折叠为一个条件:

if (idk == 1 && beer[j]=='1') { cout << "IDK" << endl; }
if (idk != 1 && beer[j]=='1') { cout << "NO" << endl; idk=0; }
if (beer[j]=='0') { cout << "NO" << endl; idk=0; } // collapsed 2nd and 4th lines

现在,再次将

idk
设置为
0
,它已经是
!=1
不会产生任何效果...所以我们可以在第二行停止这样做。

if (idk == 1 && beer[j]=='1') { cout << "IDK" << endl; }
if (idk != 1 && beer[j]=='1') { cout << "NO" << endl; } // removed useless statement
if (beer[j]=='0') { cout << "NO" << endl; idk=0; }

对于

&&
运算符的交换性,这与代码中的内容相同。

现在,让我们在外部进行相同的重构,这将导致我们得到这个完整的解决方案:

#include <iostream>
using namespace std;

int main() {
    // your code goes here
    int T;
    cin >> T;
    for(int i=0;i<T;i++){
        int N;
        cin >> N;
        char beer[N];
        cin >> beer;
        int idk=1;
        for(int j=0;j<(N-1);j++){
            if (idk==1) {
                if (beer[j] == '1') {
                    cout << "IDK" << endl;
                } else {
                    cout << "NO" << endl;
                    idk = 0;
                }
            } else {
                cout << "NO" << endl;
            }
           
        }
        if (idk==1) {
            if (beer[N-1] == '1') {
                cout << "YES" << endl;
            } else {
                cout << "NO" << endl;
            }
        } else {
            cout << "NO" << endl;
        }
    }
    return 0;
}

好吧,如果你现在运行它......它就会通过!

就我所见,要么存在一些我没有得到的细微差别(在编译/执行方式方面,而不是在逻辑方面),并且它与特定测试用例相关……要么在某处存在错误。这可能是第一个,因为我有根据的猜测是他们在后端使用经过验证的编译器。

由于我们看不到运行时错误、测试设置和测试结果,因此我们无法进一步挖掘。

现在我们来谈谈风格。

我的第一个工作解决方案如下:

#include <iostream>
using namespace std;

int main() {
    int T; // number of tests
    cin >> T;
    for (int i = 0; i < T; i++) {
        int N; // number of logicians        
        string logiciansWill; // "binary" string, should contain '0's and '1's; other chacters are treated as "IDK"

        cin >> N >> logiciansWill;
        
        bool foundNo = false;
        
        for (int j = 0; j < N; j++){
            // we're assuming logiciansWill[j] can only be '0' or '1'
            bool logicianWantsBeer = logiciansWill[j] == '1';
            
            if (foundNo) {
                cout << "NO" << endl;
            } else if (logicianWantsBeer) {
                cout << ((j == N-1) ? "YES" : "IDK") << endl;
            } else {
                foundNo = true;
                cout << "NO" << endl;
            }
        }
    }
}

请注意,我使用了具有更好思想名称的变量:

  • logiciansWill
    传达出它包含了所有逻辑学家的意志
  • logicianWantsBeer
    表示该变量告诉您特定逻辑学家是否想要啤酒。它具有无可争议的
    bool
    优势,因此编写
    if
    语句肯定更容易
  • foundNo
    表示我要么找到了一位能够回应
    "NO"
    的逻辑学家,要么没有。再次强调,最好将其设为
    bool
    ,因为它只能是
    true
    false

另请注意,我将最后一个循环与其余循环之间的唯一区别合并到了

for
循环体内。这会导致代码少得多,而不会影响可读性。

© www.soinside.com 2019 - 2024. All rights reserved.