Задача:
Переменная, содержит в конце $$ $ a='SYS_$$' $ echo $a SYS_$$
Тут разворачивает $$ в конце строки как номер процесса, а надо отобразить строку "SYS_$$", передаваемую как параметр. $ echo "echo \$1" | ssh another_host "/bin/sh -s $a" SYS_18992
Ответ
Попробуйте так: $ a='SYS_$$'
$ echo 'echo $1' | ssh another_host "/bin/sh -s '$a'" SYS_$$
При вызове ssh, внутри двойных кавычек одиночные кавычки тетряют своё специальное назначение и переменная $а будет замещена её значением, т.е. $SYS_$$
Далее, при вызове sh на удалённом хосте, одиночные кавычки вновь приобретают своё специальное назначение и препятствуют замещению $$ текущим pid.
В какой момент времени во время исполнения произойдет присвоение int a = 5? class B {
private:
int a = 5;
public:
B();
~B();
}
Ответ
Это никакое не "присвоение". Это инициализатор и использоваться он будет для инициализации B::a, а не для присваивания. Альтернативной (и эквивалентной) формой записи будет class B {
...
int a{ 5 };
...
};
Этот инициализатор будет использован для инициализации по умолчанию этого члена класса в конструкторах этого класса. Если вы "забудете" явно проинициализировать B::a в списке инициализации конструктора класса B B::B() // Инициализация для `a` отсутствует
{}
то B::a будет неявно проинициализировано значением 5. Как будто кто-то за вас тихонько написал B::B() : a(5)
{}
Если же вы сами явно проинициализируете B::a в конструкторе B::B() : a(42)
{}
то указанный вами выше инициализатор 5 будет просто проигнорирован. У вас в классе B может быть много разных конструкторов. Какие-то из них могут явно инициализировать B::a, а какие-то - не делать явной инициализации для B::a. В последнем случае в дело будет вступать ваше 5 class B
{
private:
int a = 5;
public:
B(int) : a(42) // Здесь есть явная инициализация `a`
{
// Здесь `a` равно 42
} B(double) // Здесь нет явной инициализации `a`
{
// Здесь `a` равно 5
}
};
Функциональность таких инициализаторов не сводится только к конструкторам. Они учитываются и в "бесконструкторных" формах инициализации. Например, если класс является агрегатом и инициализируется при помощи агрегатной инициализации, то такие инициализаторы тоже принимаются во внимание компилятором struct S
{
int x;
int y = 42;
int z;
};
...
S s = { 5 }; // Агрегатная инициализация
// Здесь `s.x` равно 5, `s.y` равно 42, `s.z` равно 0
Собственно хочу понять механизм того что происходит с компилятором в C и C++ если объявить символ вот так 'a' и вот так "a".
Весь смысл изложен в этой программе #include int main()
{
printf("This is %s ", (sizeof('a') == sizeof(char)) ? "C++" : "C");
return 0;
}
в принципе понятно что происходит по факту, но не всовсем понятно как это работает изнутри.
Ответ
Пример в коде - классический пример различия между с и с++. В с++ символ в кавычках - это char. И размер его - 1. В си все приводится к int и размер 4. А различие между одинарными и двойными кавычками просто - в одинарных - символ, в двойных - строка (массив char). Самое интересное, что об этом даже в википедии написано:) И почитать у Alena cpp
Сегодня состоялся следующий спор с коллегами. Они утверждали, что в таком коде нет никаких проблем, и все будет работать везде одинаково: #include struct S{
int a;
void foo(){
std::cout << "hello";
}
}; int main(){
S *p = nullptr;
p->foo(); //hello
}
Мол к данным мы не обращаемся => В память по адресу 0 не лезем => Проблем нет.
Я им с пеной у рта доказывал что если вызывать любой не статический метод у nullptr это сразу неопределенное поведение, и не важно что там в этом методе происходит. Вопросы:
Кто прав?
Где в стандарте об этом написано?
Есть ли в стандарте что-то о том, как должен быть реализован this?
Ответ
В "классическом" С++ (C++98) ситуация однозначная - разыменование нулевого указателя приводит к неопределенному поведению. Соответственно вызов нестатического метода объекта через нулевой указатель приводит к неопределенному поведению. Не имеет никакого значения, выполняет ли этот метод доступ к членам класса или не выполняет. Такова позиция спецификации языка. С этой точки зрения вы совершенно правы, а аргументы ваших оппонентов на тему "все везде будет работать" - не более чем следствие "уличного образования" из разряда "смотрю в книгу ассемблер, вижу фигу". В то же время уже довольно давно делаются попытки формирования более гибкой/тонкой спецификации в этом вопросе. В частности DR#232: Is indirection through a null pointer undefined behavior? Однако работа в этом направлении перманентно зависла в состоянии drafting с 2005 года. Честно говоря, создается впечатление, что какого-то внятного толкования текста нынешнего стандарта на эту тему никто дать не может, возможно именно потому, что тема до сих пор является "подвешенной". Как вы сами понимаете, стандарт не будет заводить отдельную спецификацию на именно ваш частный случай. А как только мы переходим к более общему случаю, то сразу возникают такие ситуации, как преобразование указателя this при вызове метода в условиях [множественного] наследования. struct A
{
int a;
}; struct B {
int b; void foo()
{
// К данным мы не обращаемся
// Но чему здесь равно `this`???
if (this == nullptr)
; // ???
}
}; struct C : A, B
{
}; int main()
{
C *c = nullptr;
c->foo();
}
Не ясно, должен ли компилятор при преобразованиях указателя this в процессе вызова метода базового класса придерживаться правила "null преобразовывается в null"? Вот именно из-за таких тонкостей изначально было принято решение запретить вызовы нестатических методов через нулевой указатель. Что же будет (и есть) сейчас и каковы намерения авторов языка - надо ждать и разбираться. Обратите внимание, кстати, что 8.5.1.2/4 требует, чтобы скрытый параметр this при вызове метода класса инициализировался при помощи explicit type conversion. То есть в вышеприведенном примере с множественным наследованием в вызове c->foo() указатель this типа B должен инициализироваться как (B *) c. Такое преобразование работает по правилу null-в-null и результат (B *) c тоже будет нулевым указателем. Однако в GCC и Clang this внутри foo во время вызова будет иметь значение 0x4. То есть эти компиляторы не выполнили требований 8.5.1.2/4. Это сразу говорит о том, что GCC и Clang по-прежнему трактуют такой вызов как неопределенное поведение. P.S. При этом в языке С разыменование нулевого указателя строжайше запрещено.
Корректно ли выносить цепочку Switch в отдельный метод, если цепочка довольно большая? Или можно оставить ее в том же методе? Какой вариант выглядит лучше/красивее/чаще используется?
Ответ
Вы подходите не совсем правильно. Разбивать функцию на части нужно не по формальным признакам («длинный switch»), а по логическим. Вы должны задать себе вопрос: имеет ли ваш кусок кода самостоятельный смысл? (Например: можно ли сказать несколькими словами, что именно этот кусок делает?) Если ответ на этот вопрос положительный, вынесите этот кусок в функцию, и назовите её этими самыми словами. Если отрицательный — оставляйте всё как было.
Небольшое дополнение. Кодировать switch можно по-разному. Можно оставить его как switch. Если это отображение одного объекта на другой, можно закодировать его как выборку из std::unordered_map. А возможно, ваш switch лучше представить в виде вызова виртуальной функции. Когда именно и как правильно — снова-таки зависит от смысла. Пример: string text;
switch (code)
{
case 100:
text = "Continue";
break;
case 101:
text = "Switching protocols";
break;
case 200:
text = "OK";
break;
case 301:
text = "Moved permanently";
break;
case 404:
text = "Not found";
break;
}
по идее лучше закодировать так: unordered_map message_text
{
{ 100, "Continue" },
{ 101, "Switching protocols" },
{ 200, "OK" },
{ 301, "Moved permanently" },
{ 404, "Not found" }
};
и в коде string s = message_text[200];
или там string s;
auto it = message_text.find(200);
if (it != message_text.end())
s = it->second;
(и выделить в отдельную функцию GetHttpMessageByCode).
Пример того, когда switch разумно заменить на иерархию классов: switch (employee_kind)
{
case EmployeeKind::regular:
salary = get_base_salary();
bonus = total_profit * bonus_ratio / number_of_employees;
break;
case EmployeeKind::external:
salary = get_work_hours * get_hourly_rate(employee_id);
bonus = 0;
break;
case EmployeeKind::manager:
salary = get_base_salary();
bonus = bonus_fund / number_of_managers;
if (salary < 100)
bonus += 100 - salary;
break;
}
Такой код можно заменить на иерархию классов: class employee
{
protected:
int get_base_salary() { return 0; }
public:
virtual void compute_salary_and_bonus() = 0;
}; class regular_employee : public employee
{
public:
virtual void compute_salary_and_bonus()
{
salary = get_base_salary();
bonus = total_profit * bonus_ratio / number_of_employees;
}
}; class expernal_employee : public employee
{
public:
virtual void compute_salary_and_bonus()
{
salary = get_work_hours() * get_hourly_rate();
bonus = 0;
}
}; class manager : public employee
{
public:
virtual void compute_salary_and_bonus()
{
salary = get_base_salary();
bonus = bonus_fund / number_of_managers;
if (salary < 100)
bonus += 100 - salary;
}
};
Как с помощью библиотеки jinja2 при нажатии кнопки можно вызвать функцию в python, передав параметр id этой кнопки? Долго просматривал документацию и искал похожие вопросы, но так и не нашел ничего схожего. Имеется следующие части кода: main.py def json_load(num):
with open('db/pub_keys.json', 'r', encoding='utf-8') as file:
file_dumps = json.load(file)
for elem in file_dumps:
if elem.get('id') == num:
print(f' PK user with num {num}:')
print(elem.get('meta').get('pub_key'))
file.html
Нужно, чтобы при нажатии на кнопку вызывалась функция json_load() с передачей в ней аргумента id нажатой кнопки. пытался использовать {{ }} внутри onclick и action, но это не помогло. Возможно ли реализовать это по средствам jinja2?
Ответ
Jinja2 – это всего лишь библиотека для упрощения генерации HTML страниц. А нужная Вам задача решается средствами простых HTTP запросов, которые можно сделать и с помощью чистого HTML, и с помощью более управляемого JavaScript'a.
1.1. Чистый HTML + скрытые параметры В обоих случаях нужен обработчик запросов на стороне сервера. Однако чистым HTML'ем можно передать только обычный HTTP запрос, без JSON'а. На странице нужно сделать такие формы:
А на серваке ловить эти действия и параметры: @app.route('/process_data/', methods=['POST'])
def doit():
index = request.form['index']
# ... обработать данные ...
1.2. Чистый HTML + параметры в адресе Фласк позволяет легко обрабатывать аргументы как часть пути:
А на серваке так: @app.route('/process_data//', methods=['POST'])
def doit(index):
# ... обработать данные ...
1.3. Чистый HTML + JSON форма Форме можно поставить тип формата, тогда поддерживающие этот JSON браузеры отправят данные в нужном формате, а не поддерживающие вернутся к классическому form url encoded
Больше подробностей и реально интересных примеров с формой JSON доступны внизу по ссылке №5. На сервере ловить JSON тоже достаточно легко: @app.route('/process_data/', methods=['POST'])
def doit():
data = request.get_json(silent=True)
index = data["index"]
# ... обработать данные ...
2. HTML + JavaScript Очевидно, что способы выше предполагают много повторяющегося HTML кода, что явно не удобно, особенно если захочется что-то поменять. JavaScript может значительно упростить код предоставив большую гибкость, а также позволит не перезагружать страницу при отправке данных:
Теперь конкретный формат запроса будет определён лишь в одном месте. В самом скрипте можно поступить по-разному. 2.1. Вариант для сервера из 1.1, где данные передаём HTTP аргументами: function process(index) {
$.post("/process_data/", {'index': index}, function (data, status) {
alert("Data: " + data + " Status: " + status);
});
}
2.2. Вариант для сервера из 1.2, где данные передаём как часть пути: function process(index) {
$.post("/process_data/" + index + "/", {}, function (data, status) {
alert("Data: " + data + " Status: " + status);
});
}
2.3. И, наконец, вариант для сервера из 1.3, c JSON на борту: function process(index) {
$.ajax({
url: "/process_data/",
type: "post",
dataType: "json",
success: function (data) {
alert(data);
},
data: {"index": index}
});
}
Для простоты здесь используется JS в связке с библиотекой jQuery.
Полезные и использованные ссылки
Документация Flask (в которой, вообще-то, есть всё необходимое)
jQuery AJAX get and post
Пример AJAX с JSON
Про использование JSON во Flask'e
Отправка JSON формы чистым HTML