Что значит конструкция if (mas[i] - !!a != a[i])

380
06 июня 2017, 00:32

Недавно начал изучать C++, столкнулся со странной конструкцией условного оператора и не могу понять что он с чем сравнивает

у нас два массива с типом char одинаковой длины, далее он как-то сравнивает символы этих массивов. И главный вопрос: какие символы должны быть в mas[], чтобы длина строки осталась той же, но условие не выполнилось

char mas[] = "qwerty";
char a[] = "J@RODQ";
for (int i = 0; i < sizeof(a)-1; i++) {   
        if (mas[i] - !!a != a[i]) {     // что с чем сравнивается?
            puts("WRONG!");
            return -1;
        }
    }
Answer 1

Конструкция верная, но бессмысленная с практической точки зрения. Подвыражение !!a - это применение двух операторов ! к массиву a. В этом контексте массив неявно приводится к типу "указатель" (получается ненулевой указатель), а затем к типу bool (ненулевой указатель превращается в true). Двойное применение логического отрицания ! к значению true снова дает true. Таким образом значение выражения !!a - просто true. В арифметическом контексте true ведет себя эквивалентно значению 1, то есть ваше условие эквивалентно

if (mas[i] - 1 != a[i])

Вот и все. Остальной код никакими особенностями не обладает. Почему автор написал !!a вместо просто 1 - неизвестно. Скорее всего просто для обфускации кода.

Чтобы условие ни разу не выполнилось, надо поместить в строку mas символы, коды которых на единицу больше соответствующих кодов символов строки a

char mas[] = "23456";
char a[] = "12345";

Как будет выглядеть строка mas для вашего исходного варианта a - формально зависит от платформы. Можно записать ее так

char a[] = "J@RODQ";
char mas[] = { a[0]+1, a[1]+1, a[2]+1, a[3]+1, a[4]+1, a[5]+1, 0 };
Answer 2

Char это числовая переменная.

a - указатель. В C ++ значение nullptr определено как недопустимый указатель. ! Pointer превращает указатель nullptr в true и указатель non nullptr в false. ! Boolean превращает true в false и false в true. Он всегда будет работать.

Не думайте, что это «двойной восклицательный знак», думайте об этом как о двух отдельных операторах, один из которых работает на результат другого. !(!a)

Answer 3

Взлом простым перебором:

#include <string>
#include <iostream>

void check(const char* mas){
    char a[] = "J@RODQ";
    for (int i = 0; i < sizeof(a)-1; i++) {   
        if (mas[i] - !!a != a[i]) {
            puts("WRONG!");
            return;
        }
    }
    puts(mas);
}

int main(){
    std::string answer = "";
    char a[] = "J@RODQ";
    for (int i = 0; i < sizeof(a)-1; i++) {
        for(int c=0;c < 1000;c++){
            if (c - !!a != a[i]) {
            } else {
                answer += c;
                break;
            }
       }
    }
    check(answer.c_str());
}

P.S. Онлайн компилятор: https://repl.it/I4y0/4 Ответ: "KASPER"

READ ALSO
Получить данные с модального окна

Получить данные с модального окна

У меня есть класс основного окна MainWindowС него я запускаю (допустим, при авторизации) модальное окно авторизации с полями "Логин", "Пароль" (lineLogin,...

258
Взятие объекта по адресу в конструторе копирования

Взятие объекта по адресу в конструторе копирования

Всем добрый деньСтандартный конструктор копирования в классе выглядит так: SomeClass(const SomeClass &obj) Как я понимаю, const отвечают за то, что в процессе...

260
Оператор присваивания и swap

Оператор присваивания и swap

Добрый деньЕсть такая реализация Оператора присваивания

243