Google Kickstart - 如果不使用 cout.clear() 则答案错误

Google Kickstart - Wrong answer if cout.clear() is not used

我觉得这个问题很愚蠢,但我一直在尝试 Google Kickstart(A 轮,2021 年)的问题。
现在,首先,我想澄清一下,我确实不需要 问题本身的帮助,但我遇到了一个似乎是 compiler-related 的奇怪问题。 这个问题只出现在某些编译器上。

我正在发布问题 link,然后是问题陈述,如果有人不想使用 link,那么我面临的问题以及有效的代码和代码那行不通。


问题标题:K-Goodness 字符串,A 轮(2021)
问题 Link:https://codingcompetitions.withgoogle.com/kickstart/round/0000000000436140/000000000068cca3

Problem
Charles defines the goodness score of a string as the number of indices i such that Si ≠ SN−i+1 where 1≤i≤N/2 (1-indexed). For example, the string CABABC has a goodness score of 2 since S2 ≠ S5 and S3 ≠ S4.

Charles gave Ada a string S of length N, consisting of uppercase letters and asked her to convert it into a string with a goodness score of K. In one operation, Ada can change any character in the string to any uppercase letter. Could you help Ada find the minimum number of operations required to transform the given string into a string with goodness score equal to K?

Input
The first line of the input gives the number of test cases, T. T test cases follow.

The first line of each test case contains two integers N and K. The second line of each test case contains a string S of length N, consisting of uppercase letters.

Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the minimum number of operations required to transform the given string S into a string with goodness score equal to K.

Sample Input:
2
5 1
ABCAA
4 2
ABAA

Sample Output:
Case #1: 0
Case #2: 1

Explanation:
In Sample Case #1, the given string already has a goodness score of 1. Therefore the minimum number of operations required is 0.

In Sample Case #2, one option is to change the character at index 1 to B in order to have a goodness score of 2. Therefore, the minimum number of operations required is 1.


问题:
这个问题相当简单,但是,我似乎在非常具体的情况下得到了错误的答案,这个问题只出现在某些编译器上,有些编译器给出了正确的答案完全相同的代码和测试用例。
具体测试用例:

2
96 10
KVSNDVJFYBNRQPKTHPMMTZBHQPZYQHEEEQFQWOJHPHFBFXGFFGXFBFHPHJOWQFQEEEHQYZPQHBZTMMPHTKPQRNBYFFVDNXIX
95 7
CNMYPKORAUTSYETNXAZQZGBFSJJNMOMINYKNTMHTARUMDXAJAXDMURATHMTNKYNIMOMNJJSFBGZQZAXNTEYSTUAROKPKJCD

预期输出:

Case #1: 6
Case #2: 3

当我在我的代码中的一个非常特定的地方没有使用 std::cout.clear() 时,问题就出现了。仅打印任何随机变量的值似乎也可以解决此问题,不一定非得是 cout.clear()。我正在粘贴下面的代码。


**原始代码(给出错误答案):**
//
//  main.cpp
//  Google Kickstart - Round A (2021)
//
//  Created by Harshit Jindal on 10/07/21.
//

#include <iostream>
#define endl "\n"
using namespace std;

int main() {
    int num_test_cases;
    cin >> num_test_cases;
    
    for (int test_case = 1; test_case <= num_test_cases; test_case++) {
        int answer = 0;
        
        int N, K;
        cin >> N >> K;
        
        char s[N];
        cin >> s;
        
        int current_goodness = 0;
        for (int i = 0; i < N/2; i++) {
            if (s[i] != s[N-1-i]) { current_goodness++; }
        } 
        
        answer = abs(current_goodness - K);
        cout << "Case #" << test_case << ": " << answer << endl;
        
    }
    return 0;
}

原始代码的错误结果:

Case #1: 6
Case #2: 6

修改后的代码(使用 cout.clear() 给出正确答案):

//
//  main.cpp
//  Google Kickstart - Round A (2021)
//
//  Created by Harshit Jindal on 10/07/21.
//

#include <iostream>
#define endl "\n"
using namespace std;

int main() {
    int num_test_cases;
    cin >> num_test_cases;
    
    for (int test_case = 1; test_case <= num_test_cases; test_case++) {
        int answer = 0;
        
        int N, K;
        cin >> N >> K;
        
        char s[N];
        cin >> s;
        
        int current_goodness = 0;
        for (int i = 0; i < N/2; i++) {
            if (s[i] != s[N-1-i]) { 
                current_goodness++; 
            }
            cout.clear();
        } 
        
        answer = abs(current_goodness - K);
        cout << "Case #" << test_case << ": " << answer << endl;
        
    }
    return 0;
}

修改代码的正确结果:

Case #1: 6
Case #2: 3

一些额外的细节:

我知道这是一个很长的问题,但考虑到问题只出现在某些机器上,我认为需要深入了解 c++ 才能理解为什么会发生这种情况,因此将其发布在这里.我很想知道这种事情背后的原因。
感谢您的帮助。

正如 Paddy、Sam 和 Igor 在评论中所指出的,这是我理解的解决方案:

出现问题是因为 char s[N] 不是 C++ 标准,任何可变长度数组。这可能会导致缓冲区溢出,并且会覆盖数组外的内存,从而导致各种奇怪的行为。

The best way to avoid these kinds of bugs is to make it logically impossible for them to happen. – Sam Varshavchik

在这种情况下,使用 string s 解决了问题 不必调用 cout.clear().

此外,在将输出重定向到文件时,使用 #define endl "\n" 可能会更快,但由于我们正在导入整个 std 命名空间,因此任何使用 std::cout 的人都会收到错误消息因为它基本上会被翻译成 std::"\n" 这没有意义。