Страницы

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

пятница, 8 февраля 2019 г.

Объединения (пример из сетевого программирования)

Я, видимо, не совсем понимаю, как работают union в Си, поэтому просьба прокомментировать мои вопросы по следующему небольшому коду. (Чтобы сократить код, приведу только функцию main())
int main(void) { int sockfd; socklen_t size = 2000;
union { struct sockaddr sa; char mas[2000]; }un;
sockfd = socket(AF_INET, SOCK_STREAM, 0); getsockname(sockfd, (struct sockaddr*)un.mas,&size); printf("%d

", un.sa.sa_family);
return 0; }
1) Я ведь даже не заполняю структуру struct sockaddr sa, почему printf() печатает правильный ответ?
2) Если я вместо union напишу struct, то ответ будет неправильный.
3) Если переменные не будут находиться в union или struct, то вылезает предупреждение sa.sa_family’ is used uninitialized in this function.
Помогите, пожалуйста, разобраться


Ответ

Неудобный пример. Представьте что у вас есть юнион:
typedef union { struct { int value; // 4 байта }; struct { char a; // 1 байт char b; // 1 байт char c; // 1 байт char d; // 1 байт }; } Test;
Первое поле - int - объединяет в себе последующие char поля. В этом концепция union-ов. Вот трейс:
Test test; test.value = 0; // value = { 00000000 00000000 00000000 00000000 } test.a = 1; // value = { 00000000 00000000 00000000 00000001 } test.b = 2; // value = { 00000000 00000000 00000010 00000001 } test.c = 3; // value = { 00000000 00000011 00000010 00000001 } test.d = 4; // value = { 00000100 00000011 00000010 00000001 }
Видно, что меняя одно из мелких char полей меняется и большое int поле с именем value. По сути, наш union - это int число, но, для удобства, мы разделили это число на 4 байта a,b,c,d. Можем работать как со всеми 4 байтами сразу - value, так и с каждым отдельным байтом - a,b,c,d.
В вашем случае всё аналогично. Есть struct sockaddr sa, далее, его представляют как массив из char длинной в 2000 байт.
1.) Заполняете.
getsockname(sockfd, (struct sockaddr*)un.mas,&size); // передаёте указатель на начало массива char.Данные пишутся туда, как видно из моего примера с int числом, заполняя a,b,c,d мы меняем value. Здесь так же. Заполняя массив, мы меняем sa.
2.) И это логично, структура - это структура, юнион - это юнион. Не путайте их.
3.) Неужели даже так не получается?
struct sockaddr sa; sockfd = socket(AF_INET, SOCK_STREAM, 0); getsockname(sockfd, (struct sockaddr*)&sa,&size); printf("%d

", sa.sa_family);

Как подключить свой JavaScript к чужому сайту?

У меня нестандартная задача. Вопрос: Как подключить к сайту свой JavaScript ?
Т.е. к примеру, загрузился сайт в ВКонтакте, а в нем, кроме его скриптов, загружен еще мой , например кнопка нажимая на которую происходит клиент по не прочитанному сообщению.
Знаю, что в браузере возможно подключать CSS, но возможно ли это сделать для JavaScript с последующим подключением Bootstrap ?
Если есть какие нибудь предложения и идеи буду очень признателен.


Ответ

Как подключить JavaScript или CSS без доступа к сайту?
подключаемся не стесняемся не проходм мимо добавляем свой любимый плагин в сравнительную таблицу
лично я, рекомендую User JavaScript and CSS
| имя | версия | браузер | JS | CSS | имп | эксп | обл | ред | ру | - | |-------------------------|--------|-----------|----|-----|-----|------|-----|-----|----|---| | User JavaScript and CSS | 1.2.5 | C | Y | Y | Y | Y | Y | Y | Y | - | | Tampermonkey | 4.5 | С/F/S/E/O | Y | | / | / | - | Y | Y | - | | Stylish | 1.9.2 | C/F/S/O | | Y | Y | - | Y | - | - | - | | - | - | - | - | - | - | - | - | - | - | - | | имя | версия | браузер | JS | CSS | имп | эксп | обл | ред | ру | - |

| колонка | описание | - | сокращение | название браузера | |---------|-------------------------------|---|------------|-------------------| | версия | рассмитриваемая здесь версия | - | С | Chrome | | браузер | C/F/S/E/O | - | F | Firefox | | имя | имя расширения | - | S | Safari | | JS | JavaScript | - | E | Microsoft Edge | | CSS | CSS (не через JS а напрямую) | - | O | Opera Next | | имп | импорт скрипта | - | - | - | | эксп | экспорт скрипта | - | - | - | | обл | храние на сервере / ?социалки | - | - | - | | ред | редактор кода | - | - | - | | ру | поддержка русского языка | - | - | - | | - | - | - | - | - |
| ячейка | описание | |--------|----------| | Y | да | | | нет | | - | не знаю | | / | отчасти | | - | - |
User JavaScript and CSS 1.2.5
Свои JavaScript и CSS на любом сайте. Userscript и userstyle — расширение позволяет запускать собственные скрипты и стили оформления на любых сайтах. JavaScript и CSS подключаются мгновенно, еще до загрузки страницы, поэтому результат выходит без задержек.
Преимущества:
Мгновенный запуск Возможность добавлять свои библиотеки Система URL масок позволяет гибко изменять список сайтов к которым будут применены изменения
chrome.google.com/webstore
В Н И М А Н И Е !! НАСТРОЙКИ -> БИБЛИОТЕКИ
Tampermonkey 4.5
Это бесплатное расширение браузера и самый популярный менеджер пользовательских скриптов для браузеров на базе Blink и WebKit, таких как Chrome, Microsoft Edge, Safari, Opera Next, и Firefox. ... Кроме того, есть хорошие шансы на то, что несовместимые скрипты будут нормально работать при использовании Tampermonkey.
сайт
Stylish 1.9.2
Стильный интернет со Stylish, пользовательским менеджером стилей. Устанавливайте темы и скины для многих сайтов и создавайте свои. ... Stylish предлагает темы и скины для сайтов и веб-аппликаций со всего мира, таких как ✔ Поисковые машины – Google, Baidu, Yahoo ✔ Социальные сети - Facebook, Twitter, Reddit, Whatsapp, Instagram, WeChat ✔ Сайты для разработчиков – Stackoverflow, Github, JIRA, Thunderbird ✔ Браузеры – Chrome, Firefox, Opera, Safari ... Важная информация! Мы охраняем конфиденциальность ваших личных данных ... нам необходимо собирать данные о вашей активности в интернете ... Подробнее об этом – в нашей Политике конфиденциальности на странице: userstyles.org/login/policy.

Как из алгоритма в итерационном виде сделать рекурсивный

Есть такой алгоритм для поиска первого вхождения числа с помощью бинарного поиска.
int lower_bound(const vector &mas, const int &value) { int l = 0, r = mas.size() - 1; while (l < r) { int m = l + (r - l)/2; if (mas[m] >= value) r = m; else l = m + 1; } return mas[l] == value ? l : -1; }
Как его можно записать с помощью рекурсии?


Ответ

Вначале пара замечаний по коду
Никогда не создавайте переменных с именем l. Они неотличимы от 1 и сильно понижают читабельность кода Для двоичного поиска переменная m должна вычисляться по формуле
m = (left + right) / 2
поиск потому и "двоичный", что отрезок делится на равные части
А теперь код
int lower_bound_r(const vector &mas, const int &value, int left, int right) { if (left >= right) return mas[left] == value ? l : -1; int m = (left + right) / 2; if (mas[m] >= value) right = m; else left = m + 1; return lower_bound_r(mas, value, left, right); }
int lower_bound(const vector &mas, const int &value) { return lower_bound_r(mas, value, 0, mas.size() - 1); }

Как определить,в каких случаях эффективнее использовать рекурсию,а когда цикл?

Вопрос достаточно поверхностного характера.Интересно как в принципе на практике определить, что эффективнее в решении какой-либо задачи рекурсия или цикл?Заранее благодарю за внимание.


Ответ

По-своему опыту могу порекомендовать следующее:
Ответьте себе на вопрос: знаете ли вы уровень вложенности?
Если да, и уровень вложенности небольшой (например 3 цикла) - то смысла заморачиваться с рекурсией нет.
Если нет, и уровень вложенности может быть динамическим, то ответ очевиден - без рекурсии не обойтись
В любом случае,
Начинайте писать код без рекурсии, просто используйте вложенные циклы. Не обязательно с полной вложенностью, достаточно 2-3 вложенных цикла, отшлифуйте их, чтобы они работали корректно. Как только Вы это сделаете, переделать их в рекурсию или продолжить работать во вложенных циклах не вызовет никаких проблем в обоих случаях.
Начиная писать нерекурсивно, Вы с самого начала лучше разберетесь, как работает код, а впоследствие и сама рекурсия.

Разбор async await [дубликат]

На данный вопрос уже ответили: Нужен async/await или не нужен? 5 ответов Здравствуйте, извиняюсь за вопрос по этой теме т.к существует довольно огромное количество статей об этих ключевых словах, но возможно такое количество статей и ввело меня в некое не до понимание.
Я просто хочу узнать правильно ли я все понял и задать походу пару вопросов.
Начнем с async. Метод помеченный async разрешает нам внутри данного метода использовать await и требует что бы возвращаемый тип имел метод GetAwaiter. Ключевое слово await. Await ставится перед операцией которая выполняется во вторичном потоке. Он позволяет не дожидаться пока вторичный поток (IO или обычный Thread) закончит свое выполнение. Await просто оборачивает то, что идет после await в отдельный метод, который по callback вызывается когда отработает вторичный поток. Тем самым первичный поток продолжает выполняться дальше. А когда отработает вторичный поток из пула потоков возьмется рандомный поток который довыполняет вторую часть метода.
В итого что это дает в приложениях
в приложениях с ui потоками(не до конца понятно что за ui поток, работаю исключительно asp.net) наш поток продолжит выполнение и не заблочит действия пользователя; в asp.net mvc у меня первичный поток освободится и будет работать только вторичный; и последнее синтаксический сахар который скрывает всю логику которая это делает.
Вопросы
Правильно ли я все описал, действительно ли в этом смысл async await(разбить метод на две части и до выполнять вторую часть как callback, тем самым не задерживая первичный поток)? Что за метод configureawait? Почему многие говорят что эти ключевые слова не связаны с потоками. Ну как же await то ставится перед операцией, которая будет выполняться во вторичном потоке, да и суть то в чем, это конструкция была придумана что бы не держать первичный поток. Так что связь тут самая прямая или я не прав? Когда закончится выполняться вторичный поток, какой поток продолжит выполнять вторую часть метода. Тот самый вторичный поток? Или будет взят любой поток из thread pool?


Ответ

Для начала, ваши предположения.
Ну как бы технически говоря да. Но есть ещё одна важная для понимания вещь: с ключевым словом async функция разбиваются на куски так, что между этими кусками функция вообще нигде не бежит. А каждый из кусков выполняется синхронно, как обыкновенная функция. Границы этих кусков идут по await «Await ставится перед операцией которая выполняется во вторичном потоке.» — это неверно, await означает лишь, что в этой точке функция прекращает выполнение, и возобновляется тогда, когда Task, по отношению к которому производится await, завершается.
Task, как мы уже видели, вовсе не означает «кусок кода, бегущий в каком-то потоке». Например, async-функция производит Task, который бежит в конкретном потоке лишь иногда, кусками.

Теперь, ваши вопросы.
В общем и целом правда, но не на одну часть, а на много. Представьте себе, например, такой код:
async Task PrintSlowly(IEnumerable data) { Console.WriteLine("begin"); foreach (var n in data) { await Task.Delay(1000); Console.WriteLine(data); } Console.WriteLine("end"); }
В этом методе у нас k + 1 кусок, где k — количество элементов, полученных из IEnumerable Если await выполняется в UI-потоке (или в любом потоке, в котором есть свой TaskScheduler/SynchronizationContext), то следующий кусок функции перебрасывается для выполнения в тот же поток/SynchronizationContext. Если же вам это не нужно, вы можете сказать ConfigureAwait(false), что означает «мне безразлично, в каком контексте выполнятся остальные куски async-функции». При этом рантайм может заставить их выполняться где угодно, гарантий нет. Нет, операция, на которую делается await, не обязательно будет выполняться в другом потоке. Task не есть «кусок кода, который выполняется где-то ещё». Если эта операция реально не блокирует текущий поток, то да, текущий поток будет свободен. Но вы легко можете написать Task, который будет блокировать текущий поток:
async Task Weird() { if (Math.Sin(0) == 42) await Task.Delay(1000); for (int x = 0; x < 1_000_000; x++) for (int y = 0; y < 1_000_000; y++) for (int z = 0; z < 1_000_000; z++) { if (x * x * x * x + y * y * y * y == z * z * z * z) throw new Exception("Ферма лох"); } } Где и как выполняется Task, определяется исключительно самим Task'ом. Единственный случай, когда Task целиком выполняется на побочном потоке, есть Task, запущенный через Task.Run() (в этом случае поток берётся из пула потоков). В остальных случаях забота о том, где именно выполняться, лежит на самом Task'e, async/await этим не занимается, и даже не требует, чтобы Task вообще где-то выполнялся. Task должен бы завершаться, это да (и то не обязан), а выполняться он может вообще нигде. Вот пример:
static Task WaitTimer() { var tcs = new TaskCompletionSource(); new System.Threading.Timer(o => tcs.SetResult(0), null, 3000, System.Threading.Timeout.Infinite); return tcs.Task; }

И да, обязательно почитайте ответы к этому вопросу

std::map::operator[]: инициализация при обращении к несуществующему элементу

Есть такой код:
std::map m; int a = m[0];
Есть ли гарантия, что a будет содержать 0? Или есть вероятность что там будет мусор?
Общий вопрос: выполняется ли инициализация простых типов(char, int, float) при чтении несуществующего элемента map? Или там будет мусор, как это происходит с объявлениями переменных без инициализации, и нужно всегда инициализировать элементы map вручную?


Ответ

Да, гарантия есть. В "классическом" С++98 поведение такого operator[] при новом ключе x описывалось как вставка элемента make_pair(x, T()), где T - тип данных map. В вашем случае это int и выражение int() порождает нулевое значение.
Начиная с С++11 спецификация operator[] более "запутана". Выполняется конструкция пары через piecewise_construct с пустым списком аргументов для второго элемента. Для типа int такая инициализация выливается в обнуление.

Периодичные запросы к внешнему серверу средствами Spring

Разбираюсь в фреймворке Spring и возникла такая задача: необходимо, условно, раз в 3 часа делать запрос на внешний сервер и принимать в ответ html страничку. Собственно, как это можно сделать красиво именно в плане структуры и кода. Можно ли делать очереди заданий, периодичность каких либо действий средствами Spring?


Ответ

В Spring Integration есть подходящая аннотация - @Scheduled. Просто помечаете ею метод так:
@Scheduled(fixedRate = 3 * 60 * 60 * 1000) public void someTask() { ... }
или так
@Scheduled(cron = "0 */3 * * * ?") public void someTask() { ... }

Как равномерно выбрать N значений из БД?

В прошлом вопросе нужно было выводить значений Как равномерно выбрать N значений из массива?
Но сейчас задача чуть изменилась и не в легкую сторону. Теперь все данные хранятся в БД, причем каждое значение соответствует какому-то устройству, вроде:
+++++++++++++++++++++++ | id | value | device | +++++++++++++++++++++++ | 10 | 1020 | 5 | +++++++++++++++++++++++ | 11 | 1030 | 5 | +++++++++++++++++++++++ | 20 | 1040 | 5 | +++++++++++++++++++++++ | 30 | 1050 | 5 | +++++++++++++++++++++++ | 33 | 1000 | 6 | +++++++++++++++++++++++ | 47 | 9050 | 6 | +++++++++++++++++++++++ | 50 | 5020 | 6 | +++++++++++++++++++++++ .....
Т.е. что получается: в таблице есть список записей, например у устройства 5 записей 140, у устройства 6 записей 500.
Можно ли сделать такой запрос, который для каждого устройства равномерно выберет 100 записей?
upd уточнения
Версия mysql 5.5.55.


Ответ

Для того чтобы выбрать N записей из каждой группы с равными интервалами, нам нужно из каждой группы выбрать записи с порядковыми номерами, кратными T / N, где T - это количество записей в группе. Да это же работа для оконных функций count(*) over (partition by device) и row_number() over (partition by device order by id)... Стоп, их нет в MySQL. Ооооокей, достанем с балкона велосипед и попробуем их эмулировать.
count(*) over (partition by device) эмулируется легко и непринуждённо:
select d.id, d.value, d.device, cnt.records_in_group from data d inner join ( select device, count(*) records_in_group from data group by device ) cnt on cnt.device = d.device;
row_number() over (partition by device order by id) эмулируется чуть сложнее:
select d.id, d.value, d.device, rn.row_number from data d inner join ( select d1.id, count(*) row_number from data d1 left outer join data d2 on d1.device = d2.device and d2.id <= d1.id group by d1.id, d1.value, d1.device ) rn on d.id = rn.id;
По сути, для каждой записи в группе мы считаем количество записей с id меньшим, чем id текущей записи, и получаем её порядковый номер.
Соединяем, вводим поле factor, которое показывает, с каким шагом нужно брать записи из группы:
select d.id, d.value, d.device, cnt.records_in_group, rn.row_number, cnt.records_in_group / 100 factor from data d inner join ( select device, count(*) records_in_group from data group by device ) cnt on cnt.device = d.device inner join ( select d1.id, count(*) row_number from data d1 left outer join data d2 on d1.device = d2.device and d2.id <= d1.id group by d1.id, d1.value, d1.device ) rn on d.id = rn.id;
Теперь умножим factor на числа от 1 до T и получим индексы записей в группах, которые нужно выбрать. Сначала сгенерируем все пары (device, index), где index = [1, T]
select d.device, irn.idx from data d inner join ( select d1.id, count(*) as idx from data d1 left outer join data as d2 on d1.device = d2.device and d2.id <= d1.id group by d1.id, d1.value, d1.device ) irn on irn.id = d.id;
А теперь при помощи найдём все записи, индекс которых в группе кратен factor
select d.id, d.value, d.device from data d inner join ( -- наша эмуляция count(*) over(...) select device, count(*) records_in_group from data group by device ) cnt on cnt.device = d.device inner join ( -- наша эмуляция row_number(*) over(...) select d1.id, count(*) row_number from data d1 left outer join data d2 on d1.device = d2.device and d2.id <= d1.id group by d1.id, d1.value, d1.device ) rn on d.id = rn.id cross join ( -- все пары (device, index) select d.device, irn.idx from data d inner join ( select d1.id, count(*) as idx from data d1 left outer join data as d2 on d1.device = d2.device and d2.id <= d1.id group by d1.id, d1.value, d1.device ) irn on irn.id = d.id ) drn where drn.device = d.device and rn.row_number = floor(drn.idx * cnt.records_in_group / 100) -- factor спрятался тут order by d.device, d.id;
Несложно заметить, что подзапросы rn и irn идентичны. Немного сократим код, вынеся их в CTE... Стоп, CTE завезли только в 8 версии MySQL. Что ж, смиряемся с этим и принимаем запрос в текущем виде за финальный результат.
С этим запросом можно поиграть в SQL Fiddle. К сожалению, у меня под рукой нет рабочей базы MySQL, чтобы можно было померять производительность запроса на больших выборках.

Почему это работает, а это - нет?

Почему это компилируется???
class A { static { i = 8; } static int i = 6; }
А вот это - нет.
class A { static { i = 8; System.out.println(i); } static int i = 6; }


Ответ

Пожалуй, переведу эту статью с англоязычного so
При компиляции вашего кода вылетает (наверняка) ошибка illegal forward reference. Дело в том, что при инициализации полей на их использование в данном случае накладываются некоторые ограничения.
Вы не можете использовать имя вашей переменной с правой стороны выражения, т.е. читать ее значение, однако вполне можете что-то в нее записывать.
Обойти это можно двумя способами:
Поместить объявление переменной до статического блока
class A { static int i = 6; static { i = 8; System.out.println(i); } } Или использовать полное имя переменной
class A { static { i = 8; System.out.println(A.i); } static int i = 6; }
Ограничения связаны с тем, что блоки инициализации и инициализация переменных при объявлении производятся друг за другом, в том порядке, в котором они встречаются в коде. Но (если я не ошибаюсь) когда вы пытаетесь записать в переменную значение в блоке инициализации, который встречается до объявления самой переменной, то Java делает вид, что переменная уже объявлена, и после выполняет с переменной все необходимые действия. В этом можно убедиться, выполнив такой код:
public class A { static { i = 8; System.out.println(A.i); } static int i = 6;
public static void main(String args[]) {} }
На выходе вы увидите 8

Знак ? в регулярном выражении

Вопрос такой: Что означает первый знак ? слева в скобках
\.(?i:gif|jpe?g|png)$


Ответ

Всё, что Вы прочтете ниже- плод моих фантазий, этого нет в учебниках и книгах. Это- моя попытка простыми словами объяснить смысл (? в регулярных выражениях.
Представьте, что Вы пишите язык регулярных выражений с нуля, так проще всего будет понять, что обозначает (? в регулярных выражениях.
Для начала: Некое выражение, заключенное в скобки называется в регулярных выражениях группой
(это группа)
Итак, мы создаем язык регулярных выражений с нуля и мы не хотим перегружать язык множеством мета-символов и при этом нам ещё надо описать языком кучу возможностей:
атомарную группировку именованные группы группы без сохранения рекурсии изменение флагов внутри регулярного выражения и много-много других
А что бы мы сделали, если бы писали новый императивный язык? Мы бы написали кучу стандартных функций:
function atomic( expression ) { [native code] } function isNamedGroup( expression ) { [native code] } function groupWithoutCapture( expression ) { [native code] } и так далее
Грубо говоря
(? обозначает, что к группе необходимо применить некую функцию языка регулярных выражений.
А с таким пониманием всё становится очень просто:
(?> ... ) - атомарная группировка (?P ... ) - именованная группа (?: ... ) - группа без сохранения захваченного (?R) - рекурсия (?i ... ) - изменение флага внутри группы и много-много других, полный список в учебниках и гайдах
Всё это объединяет одно- конструкция начинается с (?, применяется до закрывающей ) и каким-либо образом добавляет функционал для обработки текста.