Страницы

Поиск по вопросам

среда, 1 января 2020 г.

бесконечный цикл (scanf), не понимаю почему

#c


#include 

int main(void)
{
    int num;

    do
    {
        scanf("%d", &num);

        if (num >= 1 && num <= 2000)
        {
            // Ниже тело цикла --------------------------
            if (num <= 4)
            {
                printf("few\n");
            }
            else if (num <= 9)
            {
                printf("several\n");
            }
            else if (num <= 19)
            {
                printf("pack\n");
            }
            else if (num <= 49)
            {
                printf("lots\n");
            }
            else if (num <= 99)
            {
                printf("horde\n");
            }
            else if (num <= 249)
            {
                printf("throng\n");
            }
            else if (num <= 499)
            {
                printf("swarm\n");
            }
            else if (num <= 999)
            {
                printf("zounds\n");
            }
            else
            {
                printf("legion\n");
            }
        } // закрывает "if (num >= 1 && num <= 2000)"
    } // закрывает "DO"

    while ((num < 1) || (num > 2000));
}




Как-то по-уродски код вставился...

Задача: На вход программа просит число. Если число в диапазоне от 1 до 2000, то следует
выполнить тело цикла. И повторять это до тех пор, пока число меньше 1 или больше 2000.

В целом все работает. Проблемы возникают тогда, когда я ввожу не число. К примеру
"q". Тогда программа будет бесконечно просить меня ввести что-то, и ей уже все ровно,
что я ввожу нужные значения. Не понимаю, почему не работает. Мой взгляд на вещи:


Обьявляем переменную num
Запускаем цикл DO
Программа запрашивает данные (scanf)
Допустим я ввожу "q"
Т.к num - переменная типа int, я думаю до цикла if даже не дойдет
Проверка на завершения цикла while, но т.к условию num явно не удовлетворяет, то
цикл идет заного
у меня опять запрашивают данные (scanf) и я ввожу "21"
На этом этапе значение num должно пройти в цикл if и цикл while должен завершиться
т.к соблюдаются условия по выходу из цикла
вместо этого я получают цикл из бесконечных scanf....


и еще вопрос: почему я не получаю ошибку, когда пытаюсь ввести что-то, отличное от
типа int? разве "&num" - это ни есть присвоение? всё уже должно было взорваться, когда
я попытался впихнуть туда "q". 
    


Ответы

Ответ 1



Нужно проверять, что возвращает scanf. Сделайте так: if (scanf("%d", &num) != 1) { while(fgetc(stdin) != '\n'); continue; } Т.е. пока не считано нормальное число - игнорировать введеннуюю строку и начать цикл заново... У вас, встретив не цифру, scanf оставляет ее в буфере, и при повторении цикла опять встречает ее же...

Ответ 2



Вам следует проверять результат работы функции scanf, и если было введено не число, то пропускать введенные символы. Это можно сделать следующим образом int num; do { int result = scanf( "%d", &num ); if (result == EOF) break; if (result != 1) { scanf("%*[^\n]"); num == 0; } if (num >= 1 && num <= 2000) { // Ниже тело цикла -------------------------- if (num <= 4) { printf("few\n"); } else if (num <= 9) { printf("several\n"); } else if (num <= 19) { printf("pack\n"); } else if (num <= 49) { printf("lots\n"); } else if (num <= 99) { printf("horde\n"); } else if (num <= 249) { printf("throng\n"); } else if (num <= 499) { printf("swarm\n"); } else if (num <= 999) { printf("zounds\n"); } else { printf("legion\n"); } } // закрывает "if (num >= 1 && num <= 2000)" } while ((num < 1) || (num > 2000)); // закрывает "DO" В этом фрагменте кода, если было введено не число, то функция scanf Ничего не считает, а потому лна возвратит значение 0. В этом случае данное if предложение пропустит все неправильно введенные символы if (result != 1) { scanf("%*[^\n]"); num == 0; } и вы сможете повторить итерацию цикла.

Ответ 3



scanf("%d", &num); Если мы уверены, что никаких EOF пользователь не введёт, то нам надо дождаться ввода числа (scanf вернёт 1) выкидывая нечисловые значения (ведь мусор, лежащий в потоке, сколько не пытайся его читать, числом-то не становится): while (scanf("%d", &num) != 1) scanf("%*s"); Если мы хотим ещё и EOF проверять (который -1), то можно немного переписать условие: while (scanf("%d", &num) == 0) scanf("%*s"); или while (!scanf("%d", &num)) scanf("%*s"); Если хочется порпускать всю строку целиком, то можно использовать while (!scanf("%d", &num)) scanf("%*[^\r\n]"); Как-то так.

Ответ 4



Да эта беда всегда была в scanf и им поэтому никто не пользуется, он выпихивает назад что ему не нравится по ungetc, короче надо строчку через gets ввести, а потом её в sscanf

В чем различия между “одним запросом” и “одним обращением” к базе в PostgresSQL?

#java #postgresql


Начав работать с PostgresSQL я столкнулся с непониманием разницы между понятиями
один запрос, и одно обращение к серверу.

Раньше я думал что если я в конце каждого скрипта ставлю ; то автоматически получаю
два обращения и два запроса, и вообще думал что это синонимы. На пример:

INSERT INTO table_01 (...) VALUES (...);

INSERT INTO table_02 (...) VALUES (...);


Но тут старшие товарищи подсказали мне что это не синонимы, а разные вещи.

Если я ввожу два разных скрипта за один раз я всегда делаю два обращения? Или нет?
Помогите пожалуйста разобраться как это работает?


Что понимать под запросом?
Что понимать под обращением?
В чем главные различия учет которых принципиален при подключении приложения к базе?

    


Ответы

Ответ 1



1) 2) Если сделать вот так: connection.execute( "INSERT INTO table_01 (...) VALUES (...);" ); connection.execute( "INSERT INTO table_02 (...) VALUES (...);" ); это два запроса и два обращения. А если так: connection.execute( "INSERT INTO table_01 (...) VALUES (...);INSERT INTO table_02 (...) VALUES (...);" ); то запросов всё равно два, а обращение одно. 3) В первом случае после каждого execute ты получишь один ответ. Т.е. всего 2 ответа, и в каждом одно "значение". Во втором случае ты получишь один массив (ну не совсем массив, но в данном случае это неважно) из ответов, где их (ответов) будет 2 штуки по одному значению в каждом ответе. Разница - в том, как получить ответы (например, как понять, оба запроса выполнены без ошибок, один - опять же какой именно,- или ни одного). А принципиально - надо начинать с проверки, может ли вообще коннектор обслужить мультизапросы.

Ответ 2



Мне кажется, что запрос- это когда ты шлешь на сервер свои инструкции. Соответственно, если ты шлешь пакет запросов из 2-ух инструкций(как в примере), то ты говоришь серверу "выполни вот это"=> это одно обращение на сервер. Сервер же раскрывает данный пакет на своей стороне и выполняет 2 запроса.

Ответ 3



Общее понятие Давайте посмотрим общий смысл слова запрос: запрос это: 1) Обращение с требованием, просьбой дать какие-л. сведения, объяснения и т.п по какому-н. делу. Если мы будем углубляться в употребление этого слова, то вероятно придем к выводу, что в одном обращении к чему-то либо, может быть несколько запросов, если есть такая возможность. Хотя по сути, в общем употреблении это практический синонимы. Аналогия в реальной жизни Приведем аналогию с человеком, предположим, вы хотите побеспокоить кого-либо со своим вопросом. Подходите к человеку и говорите: Подскажите пожалуйста, где я могу найти ближайшую кофейню? Сколько здесь обращений и запросов? Правильно одно! Вы же один раз обратились к человеку. Подскажите пожалуйста, где я могу найти ближайшую кофейню? А еще меня интересует где здесь есть музей? Ага, до сих пор одно обращение к человеку, но запросов уже два. Тогда рассмотрим ситуацию с другого плана: Подскажите, где я могу найти ближайшую кофейню? Ближайшая кофейня находится в конце данной улицы Спасибо! Подскажите еще, где я могу найти продуктовый магазин? Сколько обращений и запросов вы сделали к человеку? По два. Все верно. База данных Так же это работает в базе данных, вы обращаетесь к базе, но можете отправить одновременно несколько запросов за одно обращение, чтобы сократить издержки на передачу данных, если для этого есть возможность в драйвере, если от выполнения этого запроса не зависят дальнейшие действия в коде. Если запросов много на INSERT, то вероятно лучше их уместить в одну конструкцию, чтобы ускорить вставку. INSERT INTO table VALUES (1,2,3,4), (1,2,3,4); Если конечно это поддерживается синтаксисом базы данных, тогда будет один запрос и одно обращение.

Для чего нужен Timer? Если есть Handler и Executor?

#java #android


Для чего нужен Timer? Если есть Handler и Executor?

С Таймером всегда какие то траблы. То не в основном потоке, то не запускается потому
что timer не успел запуститься на 10 милисекунд. Короче просто ужас.

А Handler чем то на Event похож.
    


Ответы

Ответ 1



Handler - это фишка только для Android-а. С его помощью можно выполнять блоки кода, завёрнутые в Runnable, отложено, а также отложено на заданное время в Looper потоках, таких как UI-поток в Android. Executor - это лишь интерфейс, который по-разному используется классами расширяющими его. Например выполнить метод через execute сразу же, отложено или в соседнем потоке, на усмотрение разработчика и того, как он реализует класс, расширяющий этот интерфейс. Timer - класс, изначально предназначенный для выполнения блока кода, оборачиваемого в TimerTask, который кстати расширяет Runnable, в фоновом потоке. У него достаточно функционала, для решения исторически накопившихся, часто возникающих задач, связанных с выполнением кода в фоновом потоке, уJava-разработчиков. И эти задачи до Timer нельзя было решить быстро и удобно в пару строк кода, в виду отсутствия среди стандартных компонентов Java удобного Handler, который существует благодаря Looper-архитектуре UI-потока в Android. Это лишь интерпретация событий, которая возникла при прочтении описаний к этим классам и интерфейсу. UDP: Моё личное мнение таково, что с помощью Handler можно решить множество задач не прибегая к Timer. Пример отложенного запуска и его отмены в ответе тут. Пример повтора блока кода множество раз с заданным интервалом по времени в ответе тут. Пример повтора блока кода до определенного события в ответе тут. Пример когда это может понадобиться в ответе тут. Если в указанных примерах возник вопрос, то не забывайте, что вызвать отложенный запуск с помощью Handler можно и через обращение к View, например так mView.post(...); и mView.postDelayed(...); Но могут возникнуть проблемы с Handler при необходимости выполнять тяжелые задачи в фоновом потоке, ведь использование Handler требует Looper потока. В некоторых случаях для решения подобных задач использование Timer может оказаться более удобным. Но всегда можно создать собственный Looper поток, например HandlerThread, который содержит в себе Looper. В конечном итоге удобство использования компонентов, будь то Handler или Timer, собственный AsyncTask или сторонние компоненты, зависит от поставленной задачи.

Закрашивание границы объекта по часовой стрелке с помощью css

#css #css3 #анимация #css_animation


Где-то здесь я раньше видел следующее решение анимации на чистом css: при наведении
на какой-либо объект, граница этого объекта border с радиусом 100% закрашивалась по
часовой стрелке. 
    


Ответы

Ответ 1



Пример * { padding: 0; margin: 0; box-sizing: border-box; } .circle { position: relative; width: 200px; height: 200px; background: #ccc; border-radius: 100%; } .circle__item { width: 50%; height: 100%; right: 0px; position: absolute; overflow: hidden; transform-origin: left center; } .circle:hover .circle__item { animation: anim1 6s 1; transform: rotate(180deg); } @keyframes anim1 { 0% { transform: rotate(0deg); } 50% { transform: rotate(0deg); } 50.01% { transform: rotate(180deg); } 100% { transform: rotate(180deg); } } .circle__half { height: 100%; right: 0px; position: absolute; border: solid 10px transparent; border-top-color: green; border-left-color: green; border-radius: 50%; } .circle__half--clipped { width: 200%; transform: rotate(-45deg); } .circle:hover .circle__half--clipped { transform: rotate(135deg); animation: anim2 3s linear 2; } @keyframes anim2 { 0% { transform: rotate(-45deg); } 100% { transform: rotate(135deg); } } .circle__half--fix { width: 100%; transform: rotate(135deg); opacity: 0; } .circle:hover .circle__half--fix { opacity: 1; animation: anim3 6s 1; } @keyframes anim3 { 0% { opacity: 0; } 49.99% { opacity: 0; } 50% { opacity: 1; } 100% { opacity: 1; } }


dataset возвращает undefined

#javascript


У меня в браузерах не работает dataset. Что в firefox, что в хроме. Код беру прям
из учебных примеров. Вот код:



var div = document.getElementById('widget');
var widgetName = div.dataset.widgetName;
 alert( widgetName );
Выберите жанр


Ответы

Ответ 1



У вас в названии атрибута data-widget-name вместо дефиса используется юникодный символ HYPHEN (e2 80 90). Это можно увидеть, если скопировать ваш HTML код в какой-нибудь HEX-редактор. Сотрите то, что маскируется под дефис, и введите руками с клавиатуры: var div = document.getElementById('widget'); var widgetName = div.dataset.widgetName; alert( widgetName );
Выберите жанр
Полагаю, что HYPHEN там взялся при копировании кода в какой-нибудь Google Docs или другой умный текстовые редактор.

Symfony 3, разный редирект после авторизации для разных ролей

#php #symfony #symfony3


У меня есть две роли

role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: ROLE_ADMIN


Мне нужно чтобы для пользователейпосле после авторизации с ролью ADMIN был редирект
в /admin
А для пользователей с ролью USER был редирект на /user
Сейчас в файле security у меня так:

firewalls:
    main:
        pattern: ^/
        form_login:
            provider: fos_userbundle
            csrf_token_generator: security.csrf.token_manager
            login_path: /login
            check_path: /login_check
            always_use_default_target_path: false
            default_target_path:            /admin

        logout:       true
        anonymous:    true


Как мне нужно модифицировать security или ещё что-то добавить, чтобы решить задачу?
    


Ответы

Ответ 1



В разделе firewalls вы должны иметь 2 подраздела. Один для обычных клиентов а второй для менеджеров. И вы можете дать группу страниц которые должны быть доступны для конкретной группе клинентов с помощью pattern. Например pattern: /admin(.*) В итоге у вас должно получиться такой config firewalls: main: pattern: ^/ form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager login_path: /login check_path: /login_check always_use_default_target_path: false default_target_path: /user logout: true anonymous: true admin: pattern: /admin(.*) form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager login_path: /login check_path: /admin/login_check always_use_default_target_path: false default_target_path: /admin logout: true anonymous: true

Ответ 2



Если нужно использовать один firewall (например, чтобы авторизованный админ на фронте тоже был авторизован), то можно использовать success_handler в firewall SecurityBundle Configuration security.yml main: pattern: ^/ form_login: provider: fos_userbundle csrf_token_generator: security.csrf.token_manager login_path: /login check_path: fos_user_security_check failure_handler: user.authentication.failure_handler success_handler: user.authentication.success_handler services.yml services: user.authentication.success_handler: class: UserBundle\Security\AuthenticationSuccessHandler arguments: ["@router"] AuthenticationSuccessHandler.php class AuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface { /** @var I18nRouter */ protected $router; public function __construct(I18nRouter $router) { $this->router = $router; } /** * {@inheritdoc} */ public function onAuthenticationSuccess(Request $request, TokenInterface $token) { /** @var User $user */ $user = $token->getUser(); // Проверяем роль пользователя, генерим url через router, возвращаем ответ с редиректом return $response; } }

Вывести обьекты с ArrayList

#java #arraylist


ArrayList human = new ArrayList<>();
for (int i = 0; i < 100; i++)
{
    human.add(new Human(HumanName, lastName, middle_name, date, id));
}
human.forEach(System.out::println);


место полей мне выводит 100 хешкод объектов. Как сделать чтобы поля выводились объекта?
    


Ответы

Ответ 1



Нужно переопределить метод toString() в классе Human, в нем вернуть строку, которую вы ходите получить. IntelliJ IDEA умеет генерировать toString() автоматически, для этого нужно нажать Alt + Insert -> toString() и выбрать нужные поля.

Ответ 2



@katso правильно отметил что нужно для объекта переопределить метод toString(). Но удобнее использовать не автогенерацию кода intelij, а библиотеку lombok. В ней есть много аннотаций для генерации шаблоного кода(геттеры, сеттеры, конструкторы, toString, equalsAndHashCode и т.д.). Например генерация метода toString. Плюс ломбока в том, что дополнительный код он создает на этапе компиляции, то есть при добавлении новых полей в классах, ничего не нужно дополнительно приписывать.

Передача аргумента типа-перечисления в метод на C#

#c_sharp #enum


Как сделать что-то типа класса идентификатора?
Я даже не знаю как правильно это назвать и класс ли это вообще. 

Проблема такая. Пишу логи для программы. Логи бывают 2 типов: сообщение и ошибка.
Есть метод, который нужно вызвать и передать туда информацию о том сообщение ли это
или ошибка.

public void Log(LogType type)
{

}


Проблема заключается именно в LogType. Я не знаю как его правильно реализовать, чтобы
можно было при передаче сделать следующее:

Log(LogType.Error); 


или 

Log(LogType.Message); 


Заранее спасибо.
Передача через переменную int 0-сообщение 1-ошибка и т.п. не катит
    


Ответы

Ответ 1



Используйте перечисление enum: public enum LogType { Message, Error }

Ответ 2



Вам подойдет вариант с enum public enum LogType { Error = 0, Message = 1 }

Проскролить в самый низ в чате

#javascript #jquery


Здравствуйте такая проблема есть блок с сообщениями высотой 400px в него добавлено
css свойство overflow-y: scroll; и блок прокручивается вниз только на 400px а как сделать
чтобы прокручивался в самый низ
вот сам код 



$('.message-block').animate({
  scrollTop: $('.message-block').height()
});
.message-block {
    position: sticky;
    background-color: #eef2f4;
    height: 400px;
    overflow-y: scroll;
    padding-top: 10px;
    border-radius: 10px;
}
.text-sender-read {
    background-color: #8bda84;
    width: 60%;
    padding: 5%;
    border-radius: 30px;
}
.text-sender-unread {
    box-shadow: 0px 0px 14px 2px #3675d8;
 }
.sender{
	position: relative;
}

.incoming {
position: relative;
}

.text-incoming {
    background-color:rgba(173, 164, 172, 0.31);
    width: 60%;
    padding: 5%;
    border-radius: 30px;
    float: right;
}

.page_square_photo {
        position: relative;
    display: inline-block;
    height: 82%;
    border-radius: 50%;
    border: 3px solid #b6cada;
    width: 70px;
    /* margin-left: 6px; */
    background-size: cover;
    background-repeat: no-repeat;
    background-position: 50% 50%;
}
.page_photos_module {
    padding: 5px 0px 20px;
    height: 110px;
    
}
.inline-message {
        display: table-row-group;
}

tyhrgedwsqa uyjthgr4fewq

yhtrgeythrgfe

rbtefdw

yhtg4rfew

tyhrge

rtgefw

ytyhrgwe tyhrgew

yhtrg4e

yuujthrge

hrtgefw

y4tre

jtyhr4e

ytehrg4ew

trew

rthgweqq

rgefwq

yujthtr4e

y54r

trgedw

jyhtg4re

yutjhrg4e

yujthgr4e

gfbvrweqq

y5t4re

jyhtgrteww

tyhrgew

ymtnhrgeww

оноеркп4

yt4r

nrtberewfdqq

tjyhrgf4e

jyhty4r

ujy4tr

yhtg4re

jhy4gtre

trhgfew

jyh5g4re

jythrg4fe

tyrhge

hrtgewww

hngrtgrwe

hgrgtewqw

trhgweq


Ответы

Ответ 1



Вот как я сделал, добавил еще один контейнер в ваших сообщениях теперь они в контейнере с классом message-block-inner. и у него высота автоматически ровно высоты его содержимого. И изменил прокрутку и сделал прокрутку до конца этого блока с классом (message-block-inner). $('.message-block').animate({ scrollTop: $('.message-block-inner').height() }); .message-block { position: sticky; background-color: #eef2f4; height: 400px; overflow-y: scroll; padding-top: 10px; border-radius: 10px; } .text-sender-read { background-color: #8bda84; width: 60%; padding: 5%; border-radius: 30px; } .text-sender-unread { box-shadow: 0px 0px 14px 2px #3675d8; } .sender{ position: relative; } .incoming { position: relative; } .text-incoming { background-color:rgba(173, 164, 172, 0.31); width: 60%; padding: 5%; border-radius: 30px; float: right; } .page_square_photo { position: relative; display: inline-block; height: 82%; border-radius: 50%; border: 3px solid #b6cada; width: 70px; /* margin-left: 6px; */ background-size: cover; background-repeat: no-repeat; background-position: 50% 50%; } .page_photos_module { padding: 5px 0px 20px; height: 110px; } .inline-message { display: table-row-group; }

tyhrgedwsqa uyjthgr4fewq

yhtrgeythrgfe

rbtefdw

yhtg4rfew

tyhrge

rtgefw

ytyhrgwe tyhrgew

yhtrg4e

yuujthrge

hrtgefw

y4tre

jtyhr4e

ytehrg4ew

trew

rthgweqq

rgefwq

yujthtr4e

y54r

trgedw

jyhtg4re

yutjhrg4e

yujthgr4e

gfbvrweqq

y5t4re

jyhtgrteww

tyhrgew

ymtnhrgeww

оноеркп4

yt4r

nrtberewfdqq

tjyhrgf4e

jyhty4r

ujy4tr

yhtg4re

jhy4gtre

trhgfew

jyh5g4re

jythrg4fe

tyrhge

hrtgewww

hngrtgrwe

hgrgtewqw

trhgweq



Ответ 2



function animated_scroll(block, delay = 2222){ let y = block.scrollTop; // Откуда начинаем прокручивать const dest = block.scrollHeight -block.offsetHeight; // До куда надо прокрутить const interval = 1000 / 24; // 24 fps)) const delta = (dest - y) * (interval/delay); // Сколько надо прокрутить за шаг, чтобы за время delay успеть прокрутить до куда надо // Поехали (function scroll(){ if(y < dest){ y += delta; block.scrollTop = y; setTimeout(scroll, interval); }// else мы уже на месте })(); } animated_scroll(document.querySelector('.message-block')) .message-block { position: sticky; background-color: #eef2f4; height: 400px; overflow-y: scroll; padding-top: 10px; border-radius: 10px; } .text-sender-read { background-color: #8bda84; width: 60%; padding: 5%; border-radius: 30px; } .text-sender-unread { box-shadow: 0px 0px 14px 2px #3675d8; } .sender{ position: relative; } .incoming { position: relative; } .text-incoming { background-color:rgba(173, 164, 172, 0.31); width: 60%; padding: 5%; border-radius: 30px; float: right; } .page_square_photo { position: relative; display: inline-block; height: 82%; border-radius: 50%; border: 3px solid #b6cada; width: 70px; /* margin-left: 6px; */ background-size: cover; background-repeat: no-repeat; background-position: 50% 50%; } .page_photos_module { padding: 5px 0px 20px; height: 110px; } .inline-message { display: table-row-group; }

tyhrgedwsqa uyjthgr4fewq

yhtrgeythrgfe

rbtefdw

yhtg4rfew

tyhrge

rtgefw

ytyhrgwe tyhrgew

yhtrg4e

yuujthrge

hrtgefw

y4tre

jtyhr4e

ytehrg4ew

trew

rthgweqq

rgefwq

yujthtr4e

y54r

trgedw

jyhtg4re

yutjhrg4e

yujthgr4e

gfbvrweqq

y5t4re

jyhtgrteww

tyhrgew

ymtnhrgeww

оноеркп4

yt4r

nrtberewfdqq

tjyhrgf4e

jyhty4r

ujy4tr

yhtg4re

jhy4gtre

trhgfew

jyh5g4re

jythrg4fe

tyrhge

hrtgewww

hngrtgrwe

hgrgtewqw

trhgweq

P.S. jQuery не нужен

Как обновить Skype на Linux для 32bit?

#linux #debian #skype


На Debian 8 32 bit пользовался Skype:

skype -v
Skype 4.3.0.37
© 2014 Skype and/or Microsoft


Недавно пришло письмо, мол с июля прекратим поддержку версий до 4.3 включительно,
поэтому обновите версию. Иду на сайт https://www.skype.com/ru/download-skype/skype-for-linux/
вижу ссылку на deb пакет 64 bit версии, что не мой вариант. Поиск других версий на
сайте всё равно приводит на эту страницу. 

Вопрос: можно ли как-то обновить Skype для 32 bit версии?
    


Ответы

Ответ 1



если процессор поддерживает «длинные инструкции» (т.е., по-простому, «64-битный»), то можно добавить архитектуру amd64 как дополнительную (foreign arch), установить и запустить 64-битную сборку программы linux (т.е., перезагрузить компьютер), после чего можно будет устанавливать и, главное, запускать программы, собранные для 64-битной архитектуры процессора. узнать, поддерживает ли процессор «шестидесятичетырёхбитность»: $ grep -o -w 'lm' /proc/cpuinfo | sort -u если команда вернула строку lm, значит — поддерживает. если нет, дальше можно не читать. посмотреть, какая архитектура является «родной» с точки зрения программы dpkg: $ dpkg --print-architecture добавить дополнительную архитектуру: $ sudo dpkg --add-architecture amd64 посмотреть, какие архитектуры дополнительно подключены (с т.з. dpkg): $ dpkg --print-foreign-architectures обновить списки пакетов и установить 64-битную сборку программы linux: $ sudo apt-get update $ sudo apt-get install linux-image-amd64:amd64 перезагрузившись и выбрав нужный пункт в меню загрузчика, убедиться, что выполняется именно эта версия программы: $ uname -r 3.16.0-4-amd64 всё, можно устанавливать и запускать 64-битные блобы!

Ответ 2



На работе используем веб версию Skype on Linux. Решает все головные боли. https://community.skype.com/t5/Linux/Skype-5-0-for-Linux-Beta-is-here/td-p/4609846

Производится ли оптимизация вызовов функций при умножении на ноль?

#java


Пусть, есть выражение:

int result = a1*function1() + a2*function2();


Где a1,2 - это коэффициенты 0 или 1.
А function1,2 - это довольно тяжеловесные по вычислительной сложности функции.

То если a1, например, равен нулю, будет ли вычисляться function1()? Или сразу примет
значение 0?
    


Ответы

Ответ 1



То если a1, например, равен нулю, будет ли вычисляться function1()? Или сразу примет значение 0? Будет. Укороченная оценка (Short-circuit evaluation) работает только для двух логических (булевых) операторов && и ||.

Ответ 2



Простейший способ узнать это, не прибегая к помощи SO - отладочный вывод в помощь: @Test public void ttt() { int a1 = 0; int a2 = 1; int result = a1 * function1() + a2 * function2(); System.out.println(result); } private int function1() { int result = 1; for(int i = 0; i < 1000; i++) { result *= new Random().nextInt() * new Random().nextInt(); } System.out.println("func1 calculated"); return result; } private int function2() { int result = -100500; for(int i = 0; i < 1000; i++) { result += new Random().nextInt() + new Random().nextInt(); } System.out.println("func2 calculated"); return result; } func1 calculated func2 calculated -1045391715 Ответ: да, function1 будет вычисляться.

Остановить Thread при завершении основного потока скрипта

#python #python_3x #многопоточность


Например, у меня есть вот такой код:

def loop:
       while True:
             print("text")
             sleep(10)
thread = threading.Thread(target=loop)


Как мне сделать так , чтобы после завершения программы останавливался поток?
    


Ответы

Ответ 1



daemon =True import threading, time, sys def loop(): while True: print("text") time.sleep(10) threading.Thread(target=loop, daemon=True).start() sys.exit()

Ответ 2



Например так: finished = False def loop(): while not finished: print("text") sleep(10) thread = threading.Thread(target=loop) thread.start() # Программа выполняет какие-то действия finished = True

Статический класс или синглтон

#c_sharp #ооп #static #singleton


Добрый день.
Есть, например, класс:

public class ClassX 
{
    public string S1 = "s1";
    public string S2 = "s2";
    ...
}


Поля данного класса во время выполнения программы изменяются. Поля данного класса
используются различными объекты. Читал, что для изменяемых данных не следует использовать
статические классы. Как лучше реализовать? С применением синглтон паттерна? Мне показалось,
что использовать синглтон будет слишком "громоздко" для такого простого класса...
    


Ответы

Ответ 1



Лучше не использовать ни статику, ни классический синглтон. И у статики, и у синглтона есть один общий недостаток - они достаточно жёстко привязывают к себе зависящий от них код. Т.е. юнит тесты на них вы не напишете, в отдельный проект нормально не перенесёте, прорефакторить еще как-то не сможете. Выделите для "статического" класса обычный нестатический интерфейс, напишите для него обычную нестатическую реализацию. И вставьте ее в качестве зависимости в код используя любой IoC-контейнер (IServiceCollection для ASP.NET Core, Autofac, StructureMap, любой другой). И предоставьте контроль за единственностью экземпляра контейнеру.

Аналог scanner'а из java в c#

#java #c_sharp


Добрый день

Начал изучать c# вчера. Пытался создать калькулятор площади треугольника, но наткнулся
на то что не знаю есть ли в c# scanner. Прошу помощи, ибо в этом языке ничего толком
не знаю. Заранее благодрю)
    


Ответы

Ответ 1



Для ввода строк в консоли используйте метод ReadLine() статического класса Console из пространства имен System Для преобразования строки в число используйте статические методы xxx.Parse(), имеющиеся у всех стандартных типов-значений: int.Parse(), double.Parse() и т.д.

Логические операторы || vs &&

#javascript


Подскажите, пожалуйста, почему выводит в консоль 1,2,3,4?
В моем понимании, должны быть только 3 и 4 (первым срабатывает && где выполняется
последний false(3). Далее на проверке || срабатывает последний true(4)). Что не так?
Спасибо!!



function zfalse(arg) {
  console.log(arg);
  return false;
}

function ztrue(arg) {
  console.log(arg);
  return true;
}

zfalse(1) || ztrue(2) && zfalse(3) || ztrue(4)



    


Ответы

Ответ 1



Выполняется все слева направо, если расставить скобки будет понятнее: zfalse(1) || (ztrue(2) && zfalse(3)) || ztrue(4) Условия разделенные 'ИЛИ'(||) будут проверяться, пока хотя бы одно из них не вернет true Условия разделенные 'И'(&&) будут проверяться, пока хотя бы одно из них не вернет false Т.е. zfalse(1) - печатает 1, возвращает false, поэтому идет следующая проверка ztrue(2) && zfalse(3) ztrue(2) - печатает 2, возвращает true, поэтому идет следующая проверка zfalse(3) - печатает 3, возвращает false, общее значение выражения - false ztrue(4) - печатает 4, возвращает true, общее значение выражения - true В итоге выполнились все функции, следовательно вывелись все числа.

Растянуть div на всю свободную (максимальную) ширину

#html #css


Есть два блока. Первый блок имеет динамическую ширину, т.е. ширина зависит от содержимого.
Второй блок должен быть растянут на всю остальную (свободную) ширину.



.parent {
  border: 2px solid red;
  height: 30px;
  line-height: 26px;
}
.child {
  display: inline-block;
  border: 2px solid blue;
}
Содержимое
Второе содержимое
Как можно с помощью CSS растянуть второй блок на всю свободную ширину?


Ответы

Ответ 1



Знаю два хороших метода, как растянуть второй блок на всю свободную (максимальную) ширину: Современный метод ― с помощью flexbox. .parent { display: flex; border: 2px solid red; height: 30px; line-height: 26px; } .child { display: block; border: 2px solid blue; } /* Растягиваем второй блок на максимальнуцю ширину */ .child.max { flex: 1; }
Содержимое
Второе содержимое
Один из необычных методов ― использовать float и overflow. Overflow создаёт отдельный контекст форматирования для выбранного элемента, тем самым локализуя действие свойства float внутри элемента к которому применён. Подробнее... .parent { border: 2px solid red; line-height: 26px; overflow: auto; /* Это чтобы родитель не терял высоту */ } .child { display: block; float: left; border: 2px solid blue; } /* Растягиваем второй блок на максимальнуцю ширину */ .child.max { float: none; overflow: auto; }
Содержимое
Второе содержимое
Уточнение: overflow должен быть единственным в родителе и находится после всех float.

Как изменить текущую позицию (текущий кадр) CSS-анимации через JavaScript?

#javascript #css #анимация


Как известно, CSS-анимации создаются через @keyframes, и ключевые кадры там задаются
в процентах. Так вот, как установить элементу конкретный процент, который должен отображаться?
Сама анимация при этом должна быть приостановлена, просто должен отображаться выбранный
скриптом кадр.

Зачем это нужно: например, пользователь возюкает пальцем по экрану своего айфончика,
и в зависимости от положения пальца нужно изменить положение и вид какого-нибудь элемента
(свайп со сложной анимацией, например). Ну или произвольная анимация перелистывания
слайдов в слайдере тем же пальцем.
    


Ответы

Ответ 1



Проценты установить нельзя, но, если знать длительность анимации (animation-duration), можно пересчитать проценты в секунды и установить отрицательный animation-delay, так, чтобы анимация как бы начиналась с указанной секунды. Например, если длина анимации 3s и нам нужен кадр 50%, то ставим animation-delay: -1.5s (середина анимации). Чтобы это нормально работало, нужно соблюсти ещё несколько условий: animation-iteration-count: 1 и animation-fill-mode: forwards — это нужно для того, чтобы при >=100% отображался последний кадр анимации (если это не указать, то при 100% отобразится первый кадр) animation-play-state: paused, чтобы анимация полностью контролировалась скриптом и не воспроизводилась сама по себе. Всё это можно объединить в одном CSS-свойстве animation для краткости. Пример: var anim = document.getElementById('anim'); var rng = document.getElementById('rng'); function setAnimPercent(percent) { var duration = 2; // длительность знаем заранее var frac = parseFloat(percent) / 100.0; var seconds = duration * frac; anim.style.animationDelay = '-' + seconds + 's'; }; rng.onchange = rng.oninput = function() { setAnimPercent(rng.value); }; @keyframes anim { from { background: green; transform: translateX(0px) rotate(0deg); border-radius: 0%; } to { background: red; transform: translateX(300px) rotate(45deg); border-radius: 50%; } } #anim { display: inline-block; width: 50px; height: 50px; animation: anim 2s paused forwards linear; } #rng { width: 310px; margin: 0 20px; }

Укажите процент:


Проблема с шифрованием XOR

#cpp #c #шифрование


Помогите найти ошибку в коде, текст из файла шифруется, а вот с дешифровкой проблемы

#include 
#include 
#include 
#include 

char XORing(char key, char input);

int main(int argc, char* argv[]){
    setlocale(LC_ALL, "rus");
    if(argv[1][0] == '1'){ //шифровка

        FILE *input;
        FILE *shifr;
        input = fopen("input.txt", "r");
        shifr = fopen("shifr.txt", "w");

        //Ввод ключа с клавиатуры
         char key[30];
        printf("Введите ключ: ");
        gets(key);
        int k = strlen(key);
        //перевод в нижний регистр
        for (int i = 0; i < k; i++){
            key[i] = tolower(key[i]);
        }

        //подсчет кол-ва символов в input
        int inp = 0; //счетчик
        while(fgetc(input) != EOF){
            inp++;
        }

        //шифрование input посимвольно
        for(int i = 0; i < inp; i++){
            char c = fgetc(input);
            c = tolower(c);
            fputc(XORing(key[i%k], c), shifr);
        }

        fclose(input);
        fclose(shifr);

    }
    else if(argv[1][0] == '2'){ //дешифровка

        FILE *key;
        FILE *shifr;
        FILE *deshifr;
        key = fopen("key.txt", "r");
        shifr = fopen("shifr.txt", "r");
        deshifr = fopen("deshifr.txt", "w");

        //создаем массив символов для ключа
        char KeyArr[30];
        fgets(KeyArr, 30, key);
        int k = strlen(KeyArr);
        //перевод в нижний регистр
        for (int i = 0; i < k; i++){
            KeyArr[i] = tolower(KeyArr[i]);
        }

        //подсчет кол-ва символов в shifr
        int sh = 0; //счетчик
        while(fgetc(shifr) != EOF){
            sh++;
        }

        //дешифровка
        for(int i = 0; i < sh; i++){
             char c = fgetc(shifr);
            fputc(XORing(KeyArr[i%k], c), deshifr);
        }

        fclose(key);
        fclose(shifr);
        fclose(deshifr);
    }

    else{
        printf("Error: faulse value");
    }

    return 0;
}

char XORing(char key, char input){
    char c = input ^ key;
    return c;
}

    


Ответы

Ответ 1



Во-первых, вы что-то выдумываете. Никакой шифровки текста из файла ваш код не выполняет и выполнять не может. У вас цикл подсчета количества входных символов упирается в конец файла и там навсегда и остается. Сам цикл шифрования, разумеется, читать файл не будет и шифровать ничего не будет. Чтобы этот код мог что-то шифровать, необходимо как минимум сделать rewind(input) между циклами чтения. Или избавиться совсем от этого ненужного предварительного вычисления размера файла. (Зачем понадобился этот лишний проход по файлу?) Во-вторых, функция gets не включает символ '\n' в прочитанную строку. Функция fgets включает символ '\n' в прочитанную строку, если он наличествует во входе. Это может быть причиной того, почему внешне одинаковые ключи шифровки/дешифровки на самом деле отличаются. Если файл с ключом у вас содержит перевод строки после собственно значения ключа, то этот перевод строки прочитается как часть ключа. Символ '\n' в ключе будет активно участвовать в процессе расшифровки, в то время как на этапе шифровки его там не было. Понятно, что из-за этого все поедет вкривь и вкось. Не забываете "убивать" ненужный '\n' в конце строки char KeyArr[30]; fgets(KeyArr, sizeof KeyArr, key); KeyArr[strcspn(KeyArr, "\n")] = 0; В-третьих, использование типа char, который может быть знаковым, для выполнения побитовых операций - не самая лучшая идея. P.S. Функция gets официально исключена из состава стандартной библиотеки. Пользуйтесь scanf или fgets и там, и там.

Как закрасить svg?

#css #svg


Подскажите, как закрасить svg? т.е. чтобы синим были закрашены не только края, но
и внутри.
Можно ли это сделать только с помощью css? 









    


Ответы

Ответ 1



Ваш svg внутри никак не закрасить, т.к. обрамление сердца в нем и есть вся фигура. Для того, чтобы добиться нужного вам результата, сохраните svg вот так: svg { fill: #f00; stroke: black; // для демонстрации stroke-width: 30px; // для демонстрации } Чтобы это сделать, откройте ваш исходный в AI , наведите на контур фигуры, нажмите ПКМ и выберите "Расформировать составной контур". В итоге у вас получится 2 фигуры, которые можете в дальнейшем использовать. UPDATE с учетом комментария про наведение на svg: svg { fill: none; stroke:#f00; stroke-width:30px; } svg:hover { fill: #f00; }

Ответ 2



SVG анимация заливки Анимация реализуется с использованием фильтра У feOffset анимируется атрибут dy от 1 - незакрашен, до 0 - полностью закрашен Начало анимации при наведении курсора на контур сердца begin="ph.mouseover", где ph ID контура сердца.

Взвешенное среднее двух списков, используя LINQ-выражение

#c_sharp #linq


У меня есть два списка, например:

List1 = new List{4, 6, 9},  
List2 = new List{12,3, 7}


Как найти взвешенное среднее этих списков, используя лямбда-выражение? (без циклов).

Результат должен получится такой:

weightedAverage = (4*12+6*3+9*7)/(12+3+7).

    


Ответы

Ответ 1



Давайте решать задачу по частям. Чтобы найти сумму элементов списка, проще всего воспользоваться LINQ-функцией Sum. Знаменатель у нас получается List2.Sum(). Теперь, в числителе нам нужно подсчитать попарные произведения (а суммировать мы умеем уже). Для того, чтобы подсчитать попарные чтобы-то-ни-было, используется Zip, в который вторым аргументом передаётся лямбда-функция, которая будет применена к парам элементов. Числитель получается List1.Zip(List2, (x, y) => x * y). Не забываем добавить в конец .Sum(), чтобы получить сумму этих самых попарных произведений. Выходит: var weightedAverage = List1.Zip(List2, (x, y) => x * y).Sum() / List2.Sum(); Ещё один момент: когда вы считаете средневзвешенное 1 и 2 с весами 1, вы ведь хотите получить 1.5, верно? Значит, при делении неплохо бы преобразовать к double, иначе получим целочисленное деление. Итого, окончательный ответ var weightedAverage = (double)List1.Zip(List2, (x, y) => x * y).Sum() / List2.Sum();

Как правильно оформлять try / catch в коде?

#c_sharp #исключения #форматирование


Начал очень часто сталкиваться с конструкциями try / catch, обычно оформляю их так:

try
{
     //Много кода
}
catch (Exception e)
{
    //Много кода
}


Теперь, скажем у меня что-то вроде:

try
{
     double.Parse("a"); //Тут только одна строчка
}
catch (ArgumentException e)
{
     //Ничего не делать
}


Будет ли плохо, если я напишу это так:

try
    { double.Parse("a"); }
catch (ArgumentException e) { }


Или так:

try { double.Parse("a"); }
catch (ArgumentException e) { }


Ну или например, вместо:

try
{
    return Convert.ToDouble(input);
}
catch (Exception e)
{ 
    return default(int);
}


Написать: 

try
    { return Convert.ToDouble(input); }
catch
    { return default(int); }


Просто заметил, что очень часто try / catch проверяющий одну - две строки занимает
по факту целых 8 - 9 и захотелось узнать, как можно в таких случаях поступить?
    


Ответы

Ответ 1



Да, обработка ошибок — это очень сложная часть программирования. Да, она часто требует большого объёма кода, и это нормально. Вы не должны пытаться уменьшить объём кода, ухудшая качество кода и экономя на обработке ошибок. Целью написания кода является правильный код, а не маленький код по объёму. По поводу оформления кода отступами/переносами строк, придерживайтесь стиля, принятого в вашей команде. Никаких рекомендаций по этому поводу нет. Я бы не экономил строчки путём втискивания кода в одну строку, но это вопрос личных предпочтений. А вот от игнорирования ошибок я бы вас предостерёг. Код наподобие try { double.Parse("a"); //Тут только одна строчка } catch (ArgumentException e) { //Ничего не делать } который просто проглатывает ошибку, скорее всего написан плохо: вместо того, чтобы выявить ошибку в другой части программы, мы просто закрываем на неё глаза, не думая о том, как же будет вести себя программа в исключительном случае. (Ну и в случае, когда исключение имеет хорошие шансы возникнуть и ошибки стоит ожидать, предпочтительно пользоваться функциями наподобие TryParse. Оставьте исключения для исключительных ситуаций.)

Ответ 2



В любой подобной ситуации с вопросом форматирования: В главную очередь смотрим стандарты, принятые в команде разработчиков вашего проекта. Если там не решения нашли — обращаемся к Сode conventions. P.S. Мартин Роберт советует: если вы пишите блок try-catch, это повод задуматься о том, не нужно ли что-то здесь выделить в новый метод.

Ответ 3



Исключения должны использоваться для обработки внештатного(исключительной) поведения, связанного с неожиданной ошибкой. Они не должны служить заменой проверкам выполнения условий. Если исключения можно избежать, просто проверив какое-то условие перед выполнением действия, то стоит так и сделать. Исключения следует приберечь для настоящих ошибок. Например есть такой метод public double getValueForPeriod(int periodNumber) { try { return values[periodNumber]; } catch(ArrayIndexOutOfBoundsException e) { return 0; } } Заменим выбрасывание исключения проверкой условия public double getValueForPeriod(int periodNumber) { if (periodNumber >= values.length) { return 0; } return values[periodNumber]; } Простой условный оператор работает быстрее чем проверка исключения и иногда может быть очевиднее блока обработки исключения.Этот процесс называется рефакторинг кода. Порядок рефакторинга Создайте условный оператор для граничного случая и поместите его перед try/catch блоком Переместите код из catch-секции внутрь этого условного оператора. В catch-секции поставьте код выбрасывания обычного безымянного исключения и запустите все тесты. Если никаких исключений не было выброшено во время тестов, избавьтесь от оператора try/catch. В вашем примере можно double.Parse("a") заменить таким образом double result; string st="а"; bool retVal= double.TryParse(st,result); if(retVal) { //ваш код } Про обработке исключений можете читать здесь

получить значение тега <input> JS

#javascript


Привет.

Как ни странно, но не получается получить значение тега .



var getNum = document.getElementById('get_num').value;
var addTime = document.getElementById('add');

addTime.addEventListener('click', getN);

function getN() {
  console.log(getNum);
}
Write time:
Add
Заранее спасибо!


Ответы

Ответ 1



Потому что получать значение нужно непосредственно в обработчике. Сейчас же ты выводишь то, что было сохранено при загрузке страницы. var addTime = document.getElementById('add'); addTime.addEventListener('click', getN); function getN() { var getNum = document.getElementById('get_num').value; console.log(getNum); }
Write time:
Add


Правильно ли я понимаю концепцию инъекции зависимостей?

#php #dependency_injection


Моё понимание сути depency injection. Тезисно.

Все классы вызываются через метод класса DI.
Атрибут класса DI содержит список зависимостей классов.
Внутри DI, классы чьи зависимости описаны, вызываются так же - через DI, реализуя их все.

DI работает по принципу ленивой загрузки. То есть, создает объекты только при необходимости,
все остальное время только хранит соответствия интерфейсов реализациям и свои внутренние
настройки.

Пример работы DI.


Составляю список (массив) соответствия классов и их зависимостей.
При попытке создания объекта через DI (условно $DI->create('\namespace\ClassName')
вместо new \namespace\ClassName), проверяю наличие зависимостей в массиве для вызываемого
класса и если необходимо, подменяю определенные аргументы, необходимыми классами в
соответствии с правилами из массива. После этого возвращаю созданный объект.


Правильно ли я понял алгоритм работы depency injection?

Если есть конструктивные замечания, поправьте (желательно с ссылками).

p.s. понимание принципа работы составил после прочтения этого
    


Ответы

Ответ 1



DI не обязательно работает по принципу ленивой загрузки. Ленивая загрузка - это оптимизация уже сверх того, что призвано делать внедрение зависимостей. Внедрение зависимостей - это прежде всего абстрактная идея, которая не имеет какой-то единственно правильной реализации в коде. Суть идеи в отказе от управлении зависимостями самими объектами. То есть, обычно, в отказе от создания самим объектом экземпляров каких-то классов, которые нужны этому объекту для работы. Если ваш объект сам создаёт какие-то классы, а не получает их извне готовыми, то это уже не внедрение зависимостей. Например, у вас есть объект корзины, которому необходимо что-то сохранять в БД. Если не использовать DI, то объекту корзины самому нужно будет получить откуда-то объект DAO чтобы сохранить что-то в БД. Тут вы сразу сталкиваетесь с необходимостью использовать какой-то синглтон, и с очевидными проблемами при тестировании объекта корзины в отвязке от какой-то БД. Объекту корзины придётся знать что за такие объекты DAO, с которыми он работает. В случае использования DI объект корзины по умолчанию не пытается создать объект, а ожидает (и предоставляет методы) что ему укажут извне, при или сразу после инициализации, куда и к какому объекту нужно обращаться для добавления записей в БД. Такой подход даёт много преимуществ как упрощая сами классы, так и упрощая тестирования и изменение. Если вам когда-нибудь захочется использовать совсем другой объект DAO, то для этого вам не нужно будет менять объект корзины, при условии, конечно, что тот ждёт на вход интерфейс, а не конкретный объект. Конечно, всё имеет свою цену. Программы, использующие DI, становятся более сложными для понимания, так как та логика, которая раньше была в одном месте, оказывается раскидана по всей программе. Стоит ли платить эту цену, и так ли вам нужны все достоинства этого подхода - решать нужно взвешенно по фактической ситуации. Для каких-то простых программ можно обойтись без DI вообще. На стадии прототипа тоже может и не нужно никакое DI. Если же вы хотите сделать максимально усложнить понимание вашей программы, то использование DI обязательно во всех ситуациях. Родственным для DI паттерном является паттерн MVC. Идея MVC несколько более конкретная, потому что в MVC подразумеваются конкретные роли у составных частей. Базу данных вы прячете за контроллером, а корзина ничего не знает о БД, но знает к какому контроллеру её следует обращаться в случае каких-то событий. То есть, вы тоже приходите к тому что внедряете в объект корзины её зависимость в виде контроллера. Практический пример У вас есть интерфейс для получения и сохранения каких-то данных. interface DAO { public function save($data); public function load(); } У вас есть объект корзины, который ждёт что при инициализации ему сообщат куда нужно обращаться за данными, и куда сохранять. class Cart { private $dao; private $items = []; public function __construct(DAO $dao) { $this->dao = $dao; $this->items = $this->dao->load(); } public function add($item, $qty = 1) { $this->items[$item] += $qty; $this->dao->save($this->items) } public function delete($item) { $this->items[$item] = 0; $this->dao->save($this->items) } /* Другие обычные методы пропустим */ } У вас есть конкретная реализация интерфейса. class SessionDAO implements DAO { /* Методы инициализации придумайте сами */ public function save($data) { // куда-то сохраняете } public function load() { // откуда-то загружаете } } Теперь вы можете сами в правильной последовательности создать объект DAO, передав его объекту корзины при инициализации. $dao = new SessionDAO(); $dao->initWithKey(/* ... */); $cart = new Cart($dao); $cart->add('Example', 10); Как видите, в корзине нигде не инициализируются объекты, которые нужны корзине для работы. Все необходимые объекты корзина получает из внешнего мира. Нет никакой причины, которая помешала бы вам сделать ленивое DAO, которое инициализировалось только в момент использования: class LazySessionDAO implements DAO { private $dao; private function getConcreteDAO() { // отложенно инициализируем DAO при необходимости if (!$this->dao) { $this->dao = new SessionDAO(); $this->dao->initWithKey(/* ... */); } return $this->dao; } public function save($data) { $this->getConcreteDAO()->save($data); } public function load() { $this->getConcreteDAO()->load(); } } Как видите, для этого ровным счётом ничего не нужно было менять в объекте корзины. Именно потому внедрение зависимостей так любят и ценят. Теперь к упомянутому в статье Phemto. Это - dependency injection container или dependency injector, а не просто dependency injection. Один из многих.

Не могу добавить в вектор умный указатель

#cpp #vector #stl #smart_pointer


Имеется класс MyClass, разумеется с конструктором, нужно создать вектор умных указателей
на объекты этого класса. Сам указатель создается, но при попытке добавления в вектор
вылезает ошибка . Что я упустил?

#include 
#include  

using namespace std;
Int main()
{
    vector> vectorPtr;
    unique_ptr p1(new MyClass);
    // до этого момента всё в порядке
    vectorPtr.push_back(p1);
    return 0;
}

    


Ответы

Ответ 1



std::unique_ptr не имеет конструктора копирования, поэтому, чтобы поместить его в вектор, его нужно переместить туда: vectorPtr.push_back(std::move(p1)); Или так: vectorPtr.push_back(std::make_unique()) Либо же создавать прямо в векторе: vectorPtr.emplace_back(new MyClass);

Наклонная штриховка ячейки таблицы средствами css

#html #css


Необходимо выполнить наклонную штриховку ячейки (ячеек) таблицы с помощью css так,
чтобы изменение размера ячейки не влияло на возникновение некрасивых стыков между ячейками.

Аналогичная вещь реализована в Excel



Пробовал сделать так



table {
width:400px
}
.hatching-red {
    background: linear-gradient(45deg, rgba(0, 0, 0, 0) 49.9%, red 49.9%, red 60%,
rgba(0, 0, 0, 0) 60% ), linear-gradient(45deg, red 10%, rgba(0, 0, 0, 0) 10% );
    background-size: 0.5em 0.5em
}
.hatching-green {
    background: linear-gradient(45deg, rgba(0, 0, 0, 0) 49.9%, green 49.9%, green
60%, rgba(0, 0, 0, 0) 60% ), linear-gradient(45deg, green 10%, rgba(0, 0, 0, 0) 10% );
    background-size: 0.5em 0.5em
}
1 2
Выглядит хорошо Однако, при изменение масштаба можно заметить искривление линий и не стыковку между ячейками. Как решить данную проблему? Возможно существует наиболее правильный вариант. Буду рад любому примеру.


Ответы

Ответ 1



Попробуйте использовать background-attachment: fixed; Это свойство заставляет просчитывать координаты фона не от конкретного элемента, а от страницы в целом. table { width: 400px; border-spacing: 0; } .hatching-red { background: linear-gradient(45deg, rgba(0, 0, 0, 0) 49.9%, red 49.9%, red 60%, rgba(0, 0, 0, 0) 60%) fixed, linear-gradient(45deg, red 10%, rgba(0, 0, 0, 0) 10%) fixed; background-size: 0.5em 0.5em } .hatching-green { background: linear-gradient(45deg, rgba(0, 0, 0, 0) 49.9%, green 49.9%, green 60%, rgba(0, 0, 0, 0) 60%) fixed, linear-gradient(45deg, green 10%, rgba(0, 0, 0, 0) 10%) fixed; background-size: 0.5em 0.5em }
1 2


Синхронизация потоков при наращивании count += 1 глобальной переменной

#python #многопоточность


Версия Python 3.5, использую модуль threading. Нужна ли синхронизация, когда потоки
изменяют общую глобальную переменную в один момент времени? В книгах пишут, что нужно
использовать Lock(), но и без него не возникает не каких проблем. Пример кода из книги: 

import threading, time


count = 0


def adder():
    global count
    count += 1
    time.sleep(0.5)
    count += 1

threads = []
for i in range(100):
    thread = threading.Thread(target=adder, args=())
    thread.start()
    threads.append(thread)


for thread in threads:
    thread.join()

print(count)


Вот здесь, судя по книге, должно каждый раз выдавать разные числа, так как одновременно
100 потоков в один момент времени меняют переменную count. Но почему-то всё нормально
срабатывает. Это в какой-то версии было исправлено или как? Объясните, кто знает.
    


Ответы

Ответ 1



Атомарные операции. Переключение нитей происходит только между отдельными байт-код операциями. Сами же операции неделимы. Посмотреть, как выглядит байт-код можно с помощью модуля dis Вот некоторые потокобезопасные операции: чтение или изменение одного атрибута объекта чтение или изменение одной глобальной переменной выборка элемента из списка модификация списка "на месте" (т.е. с помощью метода append) выборка элемента из словаря модификация словаря "на месте" (т.е. добавление элемента, или вызов метода clear)

Ответ 2



нужна ли синхронизация когда потоки изменяют общую глобальную переменную в один момент времени? Нужна. Вот ещё пример (запускаем 100 потоков, увеличиваем глобальную переменную niters раз): #!/usr/bin/env python3 from concurrent.futures import ThreadPoolExecutor as Pool niters = 100000 count = 0 def increment(): global count count += 1 with Pool(100) as pool: for _ in range(niters): pool.submit(increment) assert count == niters, count Этот код может приводить к AssertionError: Traceback (most recent call last): File "/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main "__main__", mod_spec) File "/usr/lib/python3.5/runpy.py", line 85, in _run_code exec(code, run_globals) File "./__main__.py", line 17, in assert count == niters, count AssertionError: 99981 Код легко сделать threadsafe, добавлением lock: #!/usr/bin/env python3 import threading from concurrent.futures import ThreadPoolExecutor as Pool niters = 100000 count = 0 def increment(lock=threading.Lock()): global count with lock: count += 1 with Pool(100) as pool: for _ in range(niters): pool.submit(increment) assert count == niters, count Только одна += операция выполняется в любое время (что делает потоки бессмысленными в этом примере. См. видео Thinking about Concurrency, Raymond Hettinger, Python core developer), поэтому гарантируется, что count == niters в конце.

Обертка над realloc

#c #инспекция_кода #memory #realloc


Написал свою обертку над realloc. Все ли здесь правильно? Может быть есть какие-то
недочеты, которых я не заметил?

#define qk_realloc(p, n) qk_realloc__(p, &p, n)

/*
=================================
[TEST] The qk_realloc__ function

Функция изменяет размер блока памяти,
на который указывает old. Если операция
выполнена успешно, то old присваивается
адрес нового блока памяти. Если операция
не выполнилась, в куче выделяется НОВЫЙ
блок памяти, в него копируется содержимое
old, старые данные освобождаются и указателю
old присваевает адрес нового блока памяти.
Если память не может быть выделена и для
нового блока, функция возвращает NULL,
при этом входные данные не изменяются.
=================================
*/

void* qk_realloc__(void* old, void* const ptrToOld, const u32 n) {
    void* new = realloc(old, n);

    if (new != NULL) {
        return *((void**) ptrToOld) = new;
    }

    // Тут должно быть сообщение типа: "не удалось выполнить realloc(n)".

    new = qk_malloc(n);

    if (new != NULL) {
        memmove(new, old, n);
        free(old);
        return *((void**) ptrToOld) = new;
    }

    // И тут похожее сообщение...

    return NULL;
}

    


Ответы

Ответ 1



Логика разработчика этой оболочки совершенно не ясна Зачем в функцию передается одновременно old и указатель на old (ptrToOld)? Если уж вы хотите передавать ptrToOld, то по нему можно получить и значение old. Зачем передавать old отдельно? Почему делается безусловное memmove(new, old, n);? А если новый размер больше старого? Также стандартный realloc разрешает передавать ему на вход нулевой указатель. Ваш memmove не учитывает эту возможность. Почему ptrToOld имеет такой странный тип - void* const? Почему этот тип не является указателем на указатель? Почему вы решили, что после неудачи realloc вы сможете сделать malloc? Теоретически, неудачи у realloc могут быть разные, но мы-то понимаем, что практически всегда неудача realloc - это просто нехватка памяти. Почему вы считаете, что если realloc не смог выделить память, то malloc сможет? *((void**) ptrToOld) - переинтрепретация памяти, возможно нарушение strict-aliasing. Почему memmove, а не memcpy? И чего именно вы пытались добиться? Первая мысль была в том, что эта оболочка призвана бороться с недостатками варианта p = realloc(p, ...), но она с ними никак не борется. Так в чем же тогда смысл?

Ответ 2



Все ли здесь правильно? Всё неправильно. Начиная с того, что нет никакой нужды делать обёртки над хорошо себя зарекомендовавшими стандартными функциями. Я даже не буду смотреть в ваш код, ответьте на простой вопрос: зачем?

Как преобразовать String в Date?

#java #строки #дата #simpledateformat


Есть две строки на русском языке:


Сегодня, 12:00
1 сентября 2017


Подскажите, пожалуйста, как их преобразовать в Date? Буду благодарен за кусок кода
или полезную ссылку. Меня интересует преобразование именно этих двух строк. Я только
недавно начал учить java. Знания Date и SimpleDateFormat еще до конца не устаканились :)
    


Ответы

Ответ 1



1.С использованием LocalDateTime и поиска времени по шаблону: String string = "Сегодня, 12:00"; LocalTime timePart = null; LocalDate datePart = null; String regex = "([01]?[0-9]|2[0-3]):[0-5][0-9]"; Matcher m = Pattern.compile(regex).matcher(string); if (m.find()) timePart = LocalTime.parse(m.group(0)); if (string.contains("Сегодня")) datePart = LocalDate.now(); LocalDateTime date = LocalDateTime.of(datePart, timePart); Date out = Date.from(date.atZone(ZoneId.systemDefault()).toInstant()); System.out.println(out); // Wed Sep 06 12:00:00 MSK 2017 Для Вчера можно использовать datePart = LocalDate.now().minus(Period.ofDays(1)); 2. String string = "1 сентября 2017"; DateFormat format = new SimpleDateFormat("d MMMM yyyy", new Locale("ru")); Date date = format.parse(string); System.out.println(date); // Fri Sep 01 00:00:00 GMT+03:00 2017

Наличие 9 бита в байте в современных компьютерах

#ассемблер #битовые_операции


Вырезка из книги Питера Абеля: 


  Группа  из  девяти битов представляет собой  байт; восемь
            битов которого содержат данные и один бит -  контроль на чет
            ность.


В нынешних компьютерах до сих пор это используется? И можно ли как-нибудь повлиять
на него программно/использовать его (при его наличии) или это чисто машинная часть?
    


Ответы

Ответ 1



Не факт, что именно такая реализация. Но сам принцип: хранение избыточности с целью обнаружения (и, возможно, коррекции) ошибок — да, по-прежнему используется, в чипах оперативной памяти с ECC, используемой преимущественно на серверах. Такая память заметно дороже, чуточку медленнее и должна поддерживаться материнской платой и процессором. Реализация аппаратная: избыточность считается железкой. Коррекция, если возможна (один бит?) происходит тоже в железе, но система уведомляется об ошибке (на x86 через machine check exception) и может обработать событие программно на любом уровне. Если невозможно, то происходит только уведомление. Linux, к примеру, резко убивает процесс, использовавший страницу с умершей памятью и не использует эту страницу в дальнейшем. Способы ручного доступа к избыточным битам мне неизвестны. Подозреваю, что даже если они существуют, то скорее с отладочными целями, и использоваться конечными пользователями не должны.

функция mysql_query

#php #mysql


Здесь на сайте нашёл вопрос и к нему очень интересный комментарий, что функции mysql_query
не существует. Но я её использую, и она есть в php. Как такое возможно?  
    


Ответы

Ответ 1



Согласно документации функция mysql-query устарела и более не поддерживается. Данное расширение устарело, начиная с версии PHP 5.5.0, и удалено в PHP 7.0.0. Используйте вместо него MySQLi или PDO_MySQL. Смотрите также инструкцию MySQL: выбор API и соответствующий FAQ для получения более подробной информации. Альтернативы для данной функции: mysqli_query() PDO::query() А Вы, соответственно, используете php версия, которого ниже 7, поэтому Вы ею ещё можете наслаждаться :)

Количество чисел n, у которых число делителей равно числу делителей n+1

#c_sharp #алгоритм #простые_числа #факторизация


Сама задача на первый взгляд кажется довольно простой:


  Найти количество таких чисел n (n<10^5), у которых число делителей равно числу
делителей числа n+1


Вот мое решение:  

static int NumberOfDividers(int number)
        {
            int counter = 0;
            for (int i = 1; i <= number; i++)
                if (number % i == 0)
                    counter++;
            return counter;

        }
        static void Main()
        {
            int counter = 0;
            for (int i = 1; i < 100000; i++)
            {
                if (NumberOfDividers(i) == NumberOfDividers(i + 1))
                    counter++;
            }
            Console.WriteLine(counter);
        }


Но алгоритм работает очень долго, какие есть варианты для его упрощения?
    


Ответы

Ответ 1



Для начала уберем лишние вычисления из основного цикла. Обратите внимание, что на каждой итерации вы вычисляете количество делителей для обоих чисел, хотя на каждой предыдущей итерации для меньшего числа значение уже было вычислено. void Main() { int counter = 0; int current = 0; for (int i = 1; i < 100000; i++) { int next = NumberOfDividers(i); if (current == next) { counter++; } current = next; } Console.WriteLine(counter);//10585 } Только это изменение уменьшит время работы вдвое. Теперь разберемся с вычислением количества делителей. Любое число делится на 1 и себя, поэтому сразу запишем 2 в счетчик, или 0, если это единица. static int NumberOfDividers(int number) { int counter = number == 1 ? 0 : 2; Также как и с простыми числами, нет смысла перебирать все предшествующие значения, достаточно перебрать значения до корня из заданного числа. Если есть делители меньше корня, то им будут соответствовать парные делители больше корня. double root = Math.Sqrt(number); Если число является квадратом, то один из делителей будет равен корню, проверяем и добавляем единицу в счетчик остальные делители парные. Для проверки нужна только целая часть корня, иначе при сравнении мы никогда не получим равенства (см. этот вопрос-ответ). Кроме того, если исходное число - единица, эта проверка добавит в счетчик ее единственный делитель и функция вернет 1, как и должна. int intRoot = (int)root; if(intRoot * intRoot == number) counter++; Остался основной цикл. Начинаем с 2, т.к. единица и само число уже учтены. Делители ходят парами, поэтому счетчик увеличиваем на 2. Исключением является корень из числа, но его мы уже учли. for (int i = 2; i < root; i++) if (number % i == 0) { counter +=2;//делители ходят парами. поэтому увеличиваем сразу на два. } return counter; } После всех манипуляций суммарное время выполнения, по грубым замерам*, уменьшилось с ~3 минут до ~0,4 секунды. Т.е. примерно в 450(!) раз. *стандартный тестовый стенд не собирал, данные со встроенного счетчика времени LiNQPad

Ответ 2



Я прошу прощения, но на C# пас. Зато могу набросать на C++ :) Итак, чтобы посчитать количество делителей - раскладываем число на простые сомножители; количество делителей после этого определяется как... как в этом ответе :) - там расписано. Искать делители просто - достаточно проверять простые числа до квадратного корня из числа, причем само число всякий раз уменьшаем делением на найденный простой делитель - для скорости. Быстрый квадратный корень передираем у Уоррена в "Алгоритмических трюках"; но можно использовать и обычный sqrt. Считаем для каждого числа один раз, запоминая значение для предыдущего числа. Все, собирая все вместе - #include #include #include using namespace std; unsigned int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317 }; inline unsigned long isqrt(unsigned long x) { unsigned long x1, g0, g1; if (x <= 1) return x; int s = 1; x1 = x - 1; if (x1 > 0xFFFF) { s = s + 8; x1 >>= 16; } if (x1 > 0xFF) { s = s + 4; x1 >>= 8; } if (x1 > 0xF) { s = s + 2; x1 >>= 4; } if (x1 > 0x3) { s = s + 1; } g0 = 1ll << s; g1 = (g0 +(x>>s)) >> 1; while( g1 < g0) { g0 = g1; g1 = (g0 + (x/g0)) >> 1; } return g0; } int factors(unsigned long m) { map fs; for(unsigned int i = 0; m > 1 && primes[i] <= isqrt(m);) { if (m%primes[i]) { ++i; continue; } m /= primes[i]; fs[primes[i]]++; } if (m > 1) fs[m]++; int count = 1; for(auto q: fs) count *= (q.second+1); return count; } int main(int argc, const char * argv[]) { int total = 0, last = 1; for(unsigned long n = 2; n < 100000; ++n) { int count = factors(n); if (last == count) { // cout << (n-1) << " vs " << n << " count = " << count << endl; ++total; } else last = count; } cout << total; } Считает за миллисекунды - см. https://ideone.com/QRI81U Еще раз прошу прощения за C++, а не C#...

Вызвать static конструктор без обращений к классу

#c_sharp #static


Возможно ли, какими нибудь окольными путями (меняя код в рамках одного класса Test),
заставить программу на старте вызывать статик конструктор класса Test?

Как я понимаю, шарп, в каком то смысле, оптимизирует программу, и не выполняет построение
статик конструкторов до тех пор, пока имя класса не встретится в коде? Есть ли способы
заставить шарп построить класс, который нигде не упоминается, но, включён в сборку?

using System;

namespace Program {

    public static class Test {
        static Test() {
            Console.WriteLine("Hello World!");   
        }
    }

    public class Activator {

        public static void Main(string[] args) {
            Console.WriteLine("start...");
        }

    }

}


Поясню, я хочу увидеть в консоли:


  Hello World!
  
  start...

    


Ответы

Ответ 1



Без дополнительного вызова (хотя бы одного), который запустит инициализацию твоих типов - нет, нельзя. С ним можно. using System; using System.Reflection; using System.Runtime.CompilerServices; namespace Program { [InvokeStaticCtorAttribute] public static class Test { static Test() { Console.WriteLine("Hello World!"); } } public class Activator { public static void Main(string[] args) { InvokeStaticCtorAttribute.InitializeStaticCtors(); Console.WriteLine("start..."); } } [AttributeUsage(AttributeTargets.Class)] public class InvokeStaticCtorAttribute : Attribute { public static void InitializeStaticCtors() { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { foreach (var type in assembly.GetTypes()) { if (type.GetCustomAttribute() != null) RuntimeHelpers.RunClassConstructor(type.TypeHandle); } } } } }

Ответ 2



Для комментария слишком много, для ответа... в общем пусть пока повисит, там видно будет. Для приведенного примера статического конструктора мало что можно сделать, так или иначе класс упомянуть в коде придется. Если же нужен доступ к статическим константам, как, например, в классе Math, или значениям из файлов конфигурации, то можно довольно легко выйти из положения, вспомнив о том, что свойства, на самом деле, являются одним или парой методов. Таким образом, для констант или значений из конфигурации, которые нужно получить без явного вызова методов инициализации, достаточно заменить поля на свойства (readonly для констант). Обращение к статическому свойству равноценно вызову статического метода, а значит с тем же успехом заставит CLR загрузить класс и вызвать статический конструктор.