Неожиданный результат в C ++ - PullRequest
0 голосов
/ 07 мая 2020

Это проблема не с соревнованиями по программированию, а с языком C ++.

На codeforces есть старая проблема программирования. Решение - на C ++. Я уже решил в Python, но я не понимаю такого поведения C ++. На моем компьютере и в компиляторе C ++ onlinegdb я получаю ожидаемый результат, но, по мнению codeforces, я получаю другой результат.

Если вас интересует проблема: http://codeforces.com/contest/8/problem/A Это очень просто и небольшое чтение. Хотя Чтение не требуется для вопроса.

Краткое задание:

Печать («вперед»), если строка a найдена в строке s и строка b также встречается в s

Печать («назад»), если строка a находится в обратном порядке строки s и строки b также находится в обратном порядке s

Печать («оба»), если оба приведенных выше значения - true

Печать («фантазия»), если оба вышеуказанных значения равны false

#include<bits/stdc++.h>
using namespace std;
#define int long long

//initializing all vars because blogs said uninitialized vars sometimes give unexpected result
string s="", a="", b="";
bool fw = false;
bool bw = false;
string now="";
string won="";
int pa=-1, pb=-1, ra=-1, rb=-1;

signed main()
{
    //following 2 lines can be ignored
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    //taking main input string s and then two strings we need to find in s are a & b
    cin >> s >> a >> b;
    //need reverse string of s to solve the problem
    string r = s;
    reverse(r.begin(), r.end());
    //pa is index of a if a is found in s else pa = -1 if not found
    pa = s.find(a);

    //if a was a substring of s
    if (pa != -1) {
        //now is substring of s from the next letter where string a was found i.e. we remove the prefix of string till last letter of a
        now = s.substr(pa + a.size(), s.size() - (pa + a.size()));
        //pb stores index of b in remaining part s i.e. now
        pb = now.find(b);

        //if b is also in now then fw is true
        if (pb != -1) {
            fw = true;
        }
    }
    //same thing done for the reverse of string s i.e. finding if a and b exist in reverse of s
    ra = r.find(a);
    if (ra != -1) {
        won = r.substr(ra + a.size(), r.size() - (ra + a.size()));
        rb = won.find(b);
        if (rb != -1) {
            bw = true;
        }
    }
    if (fw && bw) {
        cout << "both" << endl;
    }
    else if (fw && !bw) {
        cout << "forward" << endl;
    }
    else if (!fw && bw) {
        cout << "backward" << endl;
    }
    else {
        cout << "fantasy" << endl;
    }
    return 0;
}

Для ввода

atob
a
b

s = «atob», a = «a», b = "b"

Здесь обратное atob - bota.

a находится в atob.

Итак, строка now = tob.

b находится в tob, поэтому fw равно true.

Теперь a находится в bota.

Итак, строка won = "" (пустая, потому что после a ничего нет). Итак, b отсутствует в won.

Итак, rw это false.

Здесь нужно напечатать forward, а в C ++ 14 на моем P C и onlinegdb результат будет forward но судья codeforces, это both.

Я выполнил много вариантов кода, но безрезультатно.

Наконец, я заметил, что если я запускаю свою программу на P C, не вводя никаких данных и завершаю программу в терминале с Ctrl- C он печатает both, что странно, так как оба должны печататься только тогда, когда оба fw и rw истинны.

Что такое поведение C ++?

Ответы [ 2 ]

4 голосов
/ 07 мая 2020

Давайте проанализируем этот код и посмотрим, какие проблемы мы сможем найти. Это своего рода подсказка при проверке кода, но есть множественные проблемы в дополнение к ближайшей причине сбоя.

#include<bits/stdc++.h>

Никогда не делайте этого . Если вы видите это в примере, вы знаете, что это плохой пример, которому нужно следовать.

using namespace std;

Хорошо, мы не в заголовке, и краткость в образце кода является разумной целью .

#define int long long

О нет, зачем кому-то это делать? Первая проблема заключается в том, что замена препроцессора в любом случае запрещена для замены ключевых слов (например, int).

Даже без этого запрета эта более поздняя строка

int pa=-1, pb=-1, ra=-1, rb=-1;

является теперь намеренно l ie, как будто вы запутываете код. Если бы вы имели в виду именно это, ничего не стоило бы просто написать long long pa ..., и это не будет вводить в заблуждение.

//initializing all vars because blogs said uninitialized vars sometimes give unexpected result
string s="", a="", b="";

Но std::string - это тип класса с конструктором по умолчанию, поэтому он может не быть неинициализированным (он будет инициализирован по умолчанию, и это нормально, а запись ="" - просто лишний шум).

Блоги предупреждают вас о инициализации по умолчанию не- типы классов (что оставляет их с неопределенными значениями), поэтому

bool fw = false;

по-прежнему разумно.

NB. это глобальные переменные, которые в любом случае инициализированы нулем ( cf ).

signed main()

Здесь - допустимые грани main - вы никогда не должны ничего вводить иначе, под угрозой неопределенного поведения

int main() { ... }
int main(int argc, char *argv[]) { ... }

Далее, эти позиции строки являются (потенциально) неправильным типом и по сравнению с неправильным значением:

ra = r.find(a);
if (ra != -1) {

может быть просто

auto ra = r.find(a);
if (ra != std::string::npos) {

(вы могли бы написать std::string::size_type вместо auto, но я не вижу здесь большой пользы - в любом случае интерфейс, тип возврата и возвращаемые значения std::string::find хорошо документированы).

Единственное оставшееся возражение состоит в том, что ни один из запросов now, won или конечных подстрок не соответствует чему-либо в вашей формулировке проблемы.

1 голос
/ 07 мая 2020

Приведенного выше ответа и комментариев более полно для вашего вопроса. Я пока не могу комментировать, поэтому я хотел бы добавить здесь упрощенный ответ, так как я сам учусь.

Из разных выходных данных разных компиляторов вы можете отследить logi c и найти поток кода отличается в этой строке:

if (rb != -1) {

Просто добавив журнал перед этой строкой или используя отладчик:

cout << "rb:" << rb << endl;

Вы можете увидеть это на своем P C: rb: -1

Но на codeforces: rb: 4294967295

won.find (b) return npos, что означает, что у вас есть задание: rb = npos;

Это мой предположение, но возможный сценарий:

На вашем P C rb компилируется как int (ключевое слово), которое не может содержать 4294967295, и присваивается -1.

Но на codeforces , rb компилируется до тех пор, пока не будет следовать определению, и вместо него было присвоено 4294967295.

Поскольку вы переопределяете ключевое слово int, что снова рекомендуется стандартом языка программирования C ++, другой компилятор будет обрабатывать эту строку кода иначе.

...