Страницы

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

вторник, 9 апреля 2019 г.

Как мне работать с многопоточностью при парсинге?

Не совсем понимаю работу многопоточности, в моем представлении многопоточность выглядит так.
Это человек который роет яму (один поток) и к нему ты добавляешь еще одного и типа они должны рыть два раза быстрее. Но тут встает вопрос о разделении площади работы на двоих, чтобы они друг-другу не мешали? Так ли это?
Чтобы перейти к более практичным вещам, я разрабатываю парсер, который работает по такой схеме.
У меня есть xml файл с ссылками на страницу товара, я читаю этот xml и затем сразу же перехожу по ссылке загружаю не достающую информацию по товару в базу.
Скорость работы меня не устраивает и я решил разобраться в многопоточности.
Обдумываю такую схему, я читаю весь xml и записываю его в базу, после того как я его полностью записал в базу, начинаю создавать потоки и каждому из них передавать записи, одному например четную запись из базы, другому не четную.
По идеи скорость должна возрасти в два раза и не возникнет ли у меня проблем если эти два потока решат одновременно произвести операцию записи в базу. И вообще является ли мой алгоритм правильным?
Будет приятно, если вы напишите на образных примерах и немного кода тоже не помешает.


Ответ

Дело в том, что нет смысла читать файл(ы) с одного физического накопителя в несколько потоков - это абсолютно не увеличит производительность (а может даже уменьшит). Так что, в вашем случае, скорее всего, узким местом будет именно чтение xml.
А вот дальнейшую обработку, уже после чтения с диска, вполне можно выполнять в отдельных потоках. Для этого удобно применять конвейеры (pipelines).
Например, шаблон может выглядеть следующим образом:
var inputValues = new BlockingCollection();
var readXml = Task.Run(() => { try { using (var xmlReader = XmlReader.Create("test.xml")) { while (xmlReader.ReadToFollowing("nodeName")) inputValues.Add(xmlReader.ReadElementContentAsString()); } } finally { inputValues.CompleteAdding(); } });
var processValues = Task.Run(() => { foreach (var value in inputValues.GetConsumingEnumerable()) { // обрабатываем value } });
Task.WaitAll(readXml, processValues);
Такой способ также называют производитель-потребитель (producer-consumer). Один поток производит данные - другой(ие) их потребляет.
Использование BlockingCollection автоматически обеспечивает много преимуществ, о которых можно почитать в справке.
При необходимости, количество стадий конвейера можно легко увеличивать:
var inputValues = new BlockingCollection(); var processedValues = new BlockingCollection();
var readXml = Task.Run(() => { try { using (var xmlReader = XmlReader.Create("test.xml")) { while (xmlReader.ReadToFollowing("nodeName")) inputValues.Add(xmlReader.ReadElementContentAsString()); } } finally { inputValues.CompleteAdding(); } });
var processValues = Task.Run(() => { try { foreach (var value in inputValues.GetConsumingEnumerable()) { // обрабатываем value var newValue = Process(value); processedValues.Add(newValue); } } finally { processedValues.CompleteAdding(); } });
var writeToDB = Task.Run(() => { foreach (var value in processedValues.GetConsumingEnumerable()) { // записываем данные в БД } });
Task.WaitAll(readXml, processValues, writeToDB);
Если один из потоков работает намного быстрее других и забивает память, то можно ограничить ёмкость его коллекции:
var inputValues = new BlockingCollection(boundedCapacity: 50);
Таким образом, заполнив коллекцию до указанного значения, он будет ждать, пока другие потоки не выберут данные.
Обработку данных внутри каждой стадии конвейера можно дополнительно распараллелить, если это необходимо и вообще возможно:
foreach (var value in inputValues.GetConsumingEnumerable() .AsParallel() // распараллеливаем обработку .AsOrdered() // обеспечиваем правильный порядок, если нужно ) { // обрабатываем value }

Можно ли в несколько потоков записывать данные в БД? Вероятно, на эту тему нужно задать отдельный вопрос, обязательно указав, какая именно СУБД используется и прочую информацию.
Многие СУБД имеют специальные возможности по массовому эскпорту и импорту данных. Например, SQL Server. Вероятно, их использование будет эффективней, чем ручное написание многопоточного кода.

Удаление из списка всех элементов, которые в себе имеют меньше четырех знаков

Например :
lst = ['1234','2341','123']
А должно стать:
lst = ['1234', '2341']
'123' - не подошло потому что там меньше четырех знаков


Ответ

lst = ['1234', '2341', '123'] lst = [item for item in lst if len(item) >= 4]

Передача флагов форматирования в функцию

Как передать в функцию флаг форматирования std::left, std::right или std::internal?


Ответ

Вообще-то можно передавать их и как целые числа (точнее, перечисление) - просто нужно передавать не std::left, а ios_base::left, и использовать не в конструкции <<, а как параметр setf(). Обычно почему-то этот метод оказывается незаслуженно забыт.
Подробнее - см. тут

Объявленная переменная умерла?

Всем привет! Вот,собственно вопрос про С++: объявил в первом цикле for переменную инт, а во втором цикле IDE ее не видит и выдает ошибку, мол она не объявлена? Наводит на мысль, что это не баг, а фича. Так и должно быть? Объявленная в цикле переменная видна только для этого цикла?


Ответ

Согласно описанию for-предложения в стандарте C++ (6.5.3 The for statement)
1 The for statement
for ( for-init-statement conditionopt; expressionopt) statement
is equivalent to
{ for-init-statement while ( condition ) { statement expression ; } }
except that names declared in the for-init-statement are in the same declarative region as those declared in the condition, and except that a continue in statement (not enclosed in another iteration statement) will execute expression before re-evaluating condition. [Note: Thus the first statement specifies initialization for the loop; the condition (6.4) specifies a test, made before each iteration, such that the loop is exited when the condition becomes false; the expression often specifies incrementing that is done after each iteration. —end note]
Поэтому ваше предложение for можно представить, как это описано в стандарте
{ // блок кода, в котором объявлена переменная i int i = 0;
{ while ( i < 10; ) { massiv[i] = i; i++; } } }
// здесь уже нет доступа к переменной `i` в виду прекращения ее существования.
После выхода из предложения for переменная прекращает свое существование, и соответствующее имя становится необъявленным.

Помогите создать класс для JSON

Мне приходит от сервера вот такой ответ:
{ "request.id" : null, "list" : { "email1@email.com" : { "Type" : "1" }, "email2@email.com" : { "Type" : "1" }, "email3@email.com" : { "Type" : "1" } }
Как и в какой класс мне его преобразовать при помощи библиотеки JSON.Net на C#? Учитывая, что Email в List могут быть всегда разные.


Ответ

Существуют несколько инструментов для генерации C# классов из JSON строки:
http://json2csharp.com Если у вас установлено Web Essentials в Visual Studio, то выполните Edit > Paste special > paste JSON as class. Можно воспользоваться бесплатной программой jsonclassgenerator.exe
Любой из этих инструментов на выходе дает классы, используемые для сериализации/десериализации JSON строки. Сам лично в большинстве случаем пользуюсь инструментом под номером 3.
На выходе для вашего примера он дает следующие классы
namespace Example {
internal class SampleResponse1 {
[JsonProperty("request.id")] public object RequestId { get; set; }
[JsonProperty("list")] public List List { get; set; } }
}
namespace Example.SampleResponse1JsonTypes {
internal class List {
[JsonProperty("email1@email.com")] public Email1EmailCom Email1EmailCom { get; set; }
[JsonProperty("email2@email.com")] public Email2EmailCom Email2EmailCom { get; set; }
[JsonProperty("email3@email.com")] public Email3EmailCom Email3EmailCom { get; set; } }
internal class Email1EmailCom {
[JsonProperty("Type")] public string Type { get; set; } }
internal class Email2EmailCom {
[JsonProperty("Type")] public string Type { get; set; } } internal class Email3EmailCom { [JsonProperty("Type")] public string Type { get; set; } }
}
Учитывая, что Email в List могут быть всегда разные.
В таком случае, для генерации С# классов ваш JSON должен модифицироваться в такой вид
{ "request.id" : null, "list" : [ { "email" : { Name: "email1@email.com", Type: "1" }, "email" : { Name: "email2@email.com", Type: "1" } }] }
Иначе вы не сможете сгенерировать классы с переменным названием класса. Изменяемая часть не должна быть ключом JSON-объекта. Для генерации C# классов ключи JSON объектов должны быть фиксированными. Ключ содержит в себе название генерируемого класса. Либо нужно попробовать переписать этот пример через Dictionary. В итоге получился такой вариант.
namespace Example {
internal class SampleResponse1 {
[JsonProperty("request.id")] public object RequestId { get; set; }
[JsonProperty("list")] public Dictionary List { get; set; } }
} namespace Example.SampleResponse1JsonTypes { class Email { [JsonProperty("type")] public string Type{ get; set; } } }

Почему не успевают генерироваться случайные числа? [дубликат]

На данный вопрос уже ответили: C# случайные числа 1 ответ Столкнулся с такой неприятной ситуацией. Нужно получить два случайных числа из одного метода. Сначала, в переменную X помещаем возвращаемое значение метода Remove, затем в Y снова помещаем результат работы того же метода. Мне выводит одни и те же числа, например: (80; 80), (-3; -3) и тп. Хотя через построчный Debug выводит разные X и Y. Такое чувство, что VisualStudio слишком быстро работает и Random не успевает сгенерировать новое число.
Вот код:
int x1, y1; x1 = circle1.Remove(); y1 = circle1.Remove(); Console.WriteLine("(" + x1 + "; " + y1 + ")");
Ведомый метод:
public int Remove() { Random rnd = new Random(); return rnd.Next(-99, 99); }


Ответ

Предложенный мой вариант с задержкой лучше рассматривать в самом крайнем случае, а еще лучше не рассматривать. Лучше сделать как советует Vladislav Khapin
class Circle { private static Random rnd = new Random();
public int Remove() { return rnd.Next(-99, 99); }
}

Переименование ключей массива

Здравствуйте.
Имеется двумерный массив следующего вида:
array(211) { [0]=> array(3) { ["name"]=> string ["type"]=> string ["id"]=> int(54609) [1]=> array(3) { ["name"]=> string ["type"]=> string ["id"]=> int(2849) [2]=> array(3) { ["name"]=> string ["type"]=> string ["id"]=> int(59393) и т.д. }
Необходимо ключи массивов первого уровня переименовать в значение ["id"], то есть новый массив должен выглядеть так:
array(211) { [54609]=> array(3) { ["name"]=> string ["type"]=> string ["id"]=> int(54609) [2849]=> array(3) { ["name"]=> string ["type"]=> string ["id"]=> int(2849) [59393]=> array(3) { ["name"]=> string ["type"]=> string ["id"]=> int(59393) и т.д. }
Как это можно реализовать?


Ответ

Нужно перебрать существующий массив ($old_arr) и на его основе создать новый ($new_arr).
$new_arr = []; foreach ($old_arr AS $key => $val) { $new_arr[$val['id']] = $val; }

Как отследить, что приложение на андроид было свернуто?

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


Ответ

Хотя так делать не рекомендуется, но можно в onStop убить весь процесс приложения полностью:
public void onStop() { android.os.Process.killProcess(android.os.Process.myPid()); super.onStop(); }

Сложность алгоритма, содержащего рандомную операцию

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


Ответ

Да, можно. Следует оценивать с учётом вероятности.
Например, сложность bogosort оценивается как
я имею массив чисел и хочу вытащить оттуда любое, условно, четное. Но перебирать их буду не по-порядку, а рандомно, в бесконечном цикле, пока не найду нужное.
Если в массиве около половины чисел чётные, то O(1). Если только одно число чётное, то O(n) с жирненькой константой. Если ни одного, то алгоритм вообще не завершится.
Если рассматривать случайный (равномерный) массив, то, вероятно, будет сводиться к O(1) - как доступ по ключу хэш-таблицы.
PS: Провёл эксперимент для случая с единственным искомым числом (результат смотреть в реальной консоли, открытой до запуска сниппета; при запуске браузер может зависнуть на несколько секунд):
function go(n) { while (Math.random() * n | 0); } var res = []; function check(n) { var t = performance.now(); go(1< x+y) } } console.table(res.map(stat));

При удвоении длины время увеличивается вдвое, т. е. действительно O(n).

Почему при использовании AngularJS перестает работать jQuery?

Страница состоит из двух блоков: список всех элементов и создание нового элемента. Создание нового сделал с использованием jquery.steps. Работало хорошо. Далее добавил angular и директиву ng-switch. Angular заработал, перестал работать steps. Странность еще в том, что если сделать форму выбором по умолчанию (в скрипте selection = 'new'), то и steps начинает работать, а если по человечески, сначала список, а по нажатию на кнопку новый - ломается.



Ответ

ng-switch как и ng-if - удаляют полностью элементы из разметки, поэтому элемент form на который ты инициализируешь плагин у тебя то появляется до того как идет вызов form.steps, в этом случае до переключения switch все работает, то не появляется, в этом случае ничего не работает.
Решений может быть несолько:
отказаться от отдельного плагина jQuery и найти аналог в анугляре поместить вызов плагина в отдельную директиву и в ней отслеживать изменения, чтобы переинициализировать плагин в самом контроллере переинициализировать плагин с задержкой, чтобы во view успел отрисоваться нужный элемент (самый плохой вариант) Отказаться от использования ng-if/switch и заменить их на ng-show/hide, так как данные директивы только меняют style:display, но не убирают элемент из разметки. Если сделать директиву для тега form, то отслеживать ничего не надо, так как функция link будет вызываться каждый раз при добавлении элемента.

Пример директивы:
.directive('formSteps',function(){ return { link: function(scope,elem){ elem.steps({ headerTag: 'h3', bodyTag: 'fieldset', transitionEffect: 'slideLeft' }); } } })
Разметка при этом будет выглядеть так:


И в коде часть
$(function () { var form = $('#formwizard').show(); form.steps({ headerTag: 'h3', bodyTag: 'fieldset', transitionEffect: 'slideLeft' }); });
уже не нужна.

drawable xml(android)

Как программно задать изображение на кнопке при клике на неё?
android:drawableRight="@drawable/ic_plus_1"

Bitbucket удаление репозитория

Добрый день!
На bitbucket удаляю репозиторий, в cmd выполняю:
git reset --hard git remote rm
Создаю на bitbucket новый репозиторий с тем же именем.
git init git remote add origin git add README.md git add .gitignore git commit -m “init” git add . git commit -m “test tasks” git push -u origin --all
и снова на bitbucket все старые коммиты. где ещё я что-то забыл удалить?


Ответ

Как удалить историю коммитов в репозитории:
Локально
Как обнулить историю Git? Вопрос не совсем про это, но связанный: Если нужно удалить Git tracking (версионирование), правильно ли просто удалить папку .git/?
На удалённом репозитории
(например, Bitbucket, GitLab, GitHub и т.п.):
Пересоздавать репозиторий в принципе необязательно. Если вы уже обнулили локальную историю, вы можете просто отправить её на удалённый репозиторий с ключом -f.
git push -f origin
Внимание, это нельзя делать, если репозиторием пользуется ещё кто-то кроме вас! (подробнее о том, почему так и что за это будет.)
При этом будет заменено только содержимое ветки origin/master. Если на удалённом репозитории есть другие ветки, их можно удалить следующим образом (отдельно для каждой ветки с именем, например, branchname):
git push origin :branchname
Разумеется, если там много веток и/или тегов, то будет проще удалить и пересоздать весь репозиторий.
Что произошло, почему остались старые коммиты
Разберём последовательно все выполненные команды.
git reset --hard
Просто сбросили локальные изменения.
git remote rm
Не работает без ещё одного аргумента, вы просто не заметили ошибку. Но даже если делать так:
git remote rm origin
То удалится только запись в конфигурации локального репозитория о подключенном репозитории (remote) под именем origin
Дальше:
git init
Если эта команда выполняется в уже существующем репозитории, то она ничего не делает. Если вы хотите удалить историю изменений и начать версионирование с нуля, нужно было идти другим путём: Как обнулить историю Git?
git remote add origin
Поскольку репозиторий под именем origin уже есть в локальной конфигурации, ничего не произойдёт.
git add README.md git add .gitignore git commit -m “init” git add . git commit -m “test tasks”
Просто добавили пару коммитов в локальный репозиторий. Если на каком-то шаге изменений не было (были добавлены/индексированы файлы, не содержащие изменений), то и коммита не было.
git push -u origin --all
И запушили полученный результат на репозиторий origin. Закономерно видим там всю ту же историю коммитов, которая есть у нас локально. Посмотреть на локальную можно, например, так:
git log --oneline --graph --decorate --all

Глобальная константная переменная

Нужно объявить глобальную переменную:
extern int SIZE_A=10;
Почему-то выводит предупреждение:
warning: 'SIZE_A' initialized and declared 'extern'


Ответ

Эта переменная у вас вовсе не константная :), но проблема не в этом.
Просто нормальная практика такова: в одном файле глобальная переменная объявлена и определена, типа
int SIZE_A = 10;
а в других (например, с помощью механизма включаемых заголовочных файлов) - только объявлено, что где-то в другом файле (т.е. extern) есть такая переменная
extern int SIZE_A;
Просто иначе вы рискуете указать разные значения этой переменной в разных файлах - о чем вас и предупреждают. При этом возможны варианты, в зависимости от компилятора, когда extern со значением приведет к созданию переменной в объектном файле - тогда при линковке будет коллизия - две переменные с одинаковыми именами; какую из них считать верной? или когда extern приведет все же только к ссылке на переменную в другом файле - но тогда будет полностью проигнорировано значение в объявлении extern - его просто некуда будет записать :)

Как написать робота на Java? [закрыт]

Меня этот вопрос мучает ещё с того, как начинал учить Java. Код на Java работает везде где есть машина JVM? Тогда как её залить в робота? А если прикрутить ему руку и реализовать её подъём/опускание, то как через код это делать? Что насчёт мат. платы? Самому собирать?
Это.. вообще возможно?


Ответ

Зря минусуют. Тема вообще-то интересная.
Никто же не мешает вам засунуть мат.плату/ЦП/ОЗУ в коробку из под обуви, прикрутить её к машинке, отнятой у маленького сына и сделать из этого робота в домашних условиях. Соответственно установить Винду/Линух + Java.
Ну а если серьёзно, для роботов обычно используют микроконтроллеры, сочетающие в себе мат. плату, ЦП, ОЗУ, ПЗУ, интерфейсы ввода и вывода. Только в основном у них свои системные языки.
Другой вариант - не просто контроллеры, а микрокомпьютеры. Суть та же, но появляется возможность использовать высокоуровневые языки программирования.
Вот кстати пример робота, программируемого на JAVA.

C# MSSQL Что необходимо для запуска?

Создал проект windows forms с .NET v4.0, добавил в проект Service-based Database, назвал Database.mdf.
Я хочу запустить приложение на другом компьютере, кроме .NET v4.0, что мне еще необходимо установить для корректной работы с MDF базой? Локально все работает, на других компьютерах нет.
Ошибки:
System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 50 - Local Database Runtime error occurred. The specified LocalDB instance does not exist.
Строка подключения к базе:
con.ConnectionString = @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Database.mdf; Integrated Security=True";


Ответ

Вы используете SQL Server Local DB - он не требует установки как сервиса, но требует ручного создания экземпляра сервера из командной строки.
The specified LocalDB instance does not exist.
Эта ошибка означает, что экземпляра с именем MSSQLLocalDB не существует. Его надо создать, из консоли:
sqllocaldb c MSSQLLocalDB

Local DB предназначен прежде всего для разработки. Для живого развертывания приложения стоит использовать полноценный SQL Server.

Прибавить к дате 15 минут

Как прибавить к дате 15 минут? Пытаюсь таким способом, но не выходит
let date = new Date(); let h = date.getHours(), m = date.setMinutes(date.getMinutes() + 15), res = h + ':' + m;
$('.you-loan .js-loan').html(' ' + res);


Ответ

Вот так работает:
var CurrentTime = new Date(); CurrentTime.setMinutes(CurrentTime.getMinutes() + 15); console.log(CurrentTime.getHours()+":"+CurrentTime.getMinutes());
Ваша проблема в том, что setMinutes возвращает значение в милисекундах между 1 января 1970 00:00:00 UTC и обновленной датой. Правильнее пользоваться getMinutes().
Кроме того, важно, что getHours и getMinutes вызываются после изменения даты - а не до того.

Умный указатель и массив

Задача поставлена следующим образом: создать класс умный указатель, с которым можно будет реализовать следующее:
int main() { SmartPointer p1 = new int(2); p1->Method1(); p1[2] = int(); // должна быть ошибка на этапе компиляции SmartPointer p2 = new int[3]; p2->Method1(); //должна быть ошибка на этапе компиляции p2[2] = int(); return 0; }
если создаем объект Object = new Object(3); - тогда мы можем обратиться с помощью стрелки ко всем методам которыми обладает объект Object если мы создали массив объект Object = new Object[3] - тогда мы не можем обратиться с помощью стрелки к массиву.
Код ниже:
template class SmartPointer { private: DefaultDeleter m_deleter;
Counter *m_count = nullptr; T *m_ptr = nullptr;
typedef std::remove_all_extents_t ptr;
public: SmartPointer(T* const ptr) : m_count(new Counter), m_ptr(ptr) { m_count->incrementCount(); }
SmartPointer(const SmartPointer &source) m_count(source.m_count), m_ptr(source.m_ptr) { m_count->incrementCount(); }
SmartPointer& operator=(const SmartPointer &right) { m_count->decrementCount(); return SmartPointer(right).Swap(*this); } T& operator*() { return *m_ptr; } T* operator->() { return m_ptr; } T& operator[](unsigned int index) { return m_ptr[index]; }
SmartPointer& Swap(SmartPointer& other) { std::swap(m_ptr, other.m_ptr); return *this; } ~SmartPointer() { { m_count->decrementCount(); if (m_count->getCount() == 0) { m_deleter.Delete(m_ptr); delete m_count; } } } };
template class DefaultDeleter { public: void Delete(T* const ptr) { delete ptr; } };
template class DefaultDeleter { public: void Delete(T* const ptr) { delete[] ptr; } };
class Counter { private: unsigned int m_uses=0; public: void incrementCount() { ++m_uses; } void decrementCount() { --m_uses; } unsigned int getCount() { return m_uses; } };
Не совсем понятно как сделать так что бы компилятор понимал где (), а где [] где один элемент, а где массив элементов + как исправить ошибку в этой строке кода:
SmartPointer p2 = new int[3];


Ответ

Вам нужно просто сделать два разных класса: один для массива, другой - для скаляра. Так же это сделано для std::unique_ptr. Пример:
template struct smartPtr { T* operator->() { return ptr; } T* ptr; };
template struct smartPtr { T& operator[](int i) { return ptr[i]; } T* ptr; };
struct A { void foo() {} };
int main() { smartPtr ip; ip->foo(); ip[0]; // error
smartPtr ia; ia->foo(); // error ia[0].foo(); }

Условие закрытие пула потоков

Есть вот такой вот участок кода:
BlockingQueue queue = new ArrayBlockingQueue(links.size()); for (String link : links) { queue.add(link); }
ExecutorService executorService = Executors.newCachedThreadPool(); int threadsNumber = Integer.valueOf(arguments.get("-n"));
for (int i = 0; i < threadsNumber; i++) { executorService.submit(new Consumer(queue, arguments.get("-o"), Integer.valueOf(arguments.get("-l")))); }
while (!queue.isEmpty()) { Thread.sleep(1000); }
executorService.shutdownNow(); System.out.println("Все файлы были успешно скачены");
Последние строчки означают, что я собираюсь закрыть пул с потоками когда все сообщения из очереди будут прочитаны. Все отлично, но возникает проблема в момент, когда один из потоков забирает последнее сообщение из очереди. Условие !queue.isEmpty() перестает выполняться и программа завершается до того как это сообщение обработалось.
Как мне сделать так, чтобы программа завершалась только после обработки всех сообщений в очереде ?
Метод run в Consumer
@Override public void run() { try { while (true) { if (!queue.isEmpty()) { String stringURL = queue.take(); String inputFileName = Paths.get(stringURL).getFileName().toString(); String outputFileName = new File(new File(storageFilesDirectory), inputFileName).toString();
Downloader.download(stringURL, outputFileName, speedLimit); System.out.println(String.format("Файл %s был успешно скачен", inputFileName)); } Thread.sleep(500); } } catch (InterruptedException e) {
} catch (FileCouldNotBeDownloaded e) { System.out.println(String.format("Произошла ошибка скачивания файла.")); } }
В пуле у меня всего два потока, а сообщений в очереди может быть неограничено.


Ответ

Если нужно выполнить N заранее известных задач в K потоков, то проще использовать Executor с фиксированным числом потоков и скормить ему N Runnable выполняющих одну задачу:
final int NUMBER_OF_WORKERS = 2; List urls = IntStream.range( 0, 20 ).mapToObj( String::valueOf ).collect( Collectors.toList() );
ExecutorService executor = Executors.newFixedThreadPool( NUMBER_OF_WORKERS ); for ( String url : urls ) { executor.submit( () -> { // new SingleUrlDownloadTask( url ) etc... System.out.printf( "Worker [%s] downloading url: %s%n", Thread.currentThread().getName(), url ); try { Thread.sleep( 300 + ThreadLocalRandom.current().nextInt(400) ); } catch (Exception e) {} System.out.printf( "Worker [%s] completed url: %s%n", Thread.currentThread().getName(), url ); }); }
System.out.println( "All tasks queued." );
executor.shutdown(); // пул перестает принимать новые задачи, // уже поставленные в очередь задачи будут выполнены рано или поздно executor.awaitTermination( Long.MAX_VALUE, TimeUnit.NANOSECONDS );
System.out.println( "All tasks done.");

Как сделать так, чтобы правая колонка всплывала вверх?

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

Информация

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sed massa sollicitudin, accumsan diam et, luctus elit. Praesent odio est, faucibus a est at, dictum facilisis mi. Vestibulum a libero odio. Sed nec ullamcorper nulla, ac lobortis odio. Donec egestas vel risus ac gravida. Curabitur consectetur lobortis auctor. Fusce cursus semper lorem, ac auctor nunc fermentum sit amet. Pellentesque nec lacus in magna consectetur viverra. Proin quis turpis laoreet, aliquam est ac, lacinia nibh. Aliquam erat volutpat. Curabitur placerat consectetur maximus. Mauris accumsan leo non lacus vehicula efficitur.

Фотогалерея

Место для фотогалереи

Новости

Место для новостей

Газета

Содержимое блока

Контакты

jjj


Ответ

Бутстрап умеет менять колонки местами: http://getbootstrap.com/css/#grid-column-ordering
Их надо расположить так, как они будут стоять на мобильном, и при переходе к широкому экрану верхнюю колонку оттолкнуть вправо, а нижнюю вытянуть влево.

Газета

Содержимое блока

Контакты

jjj

Информация

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sed massa sollicitudin, accumsan diam et, luctus elit. Praesent odio est, faucibus a est at, dictum facilisis mi. Vestibulum a libero odio. Sed nec ullamcorper nulla, ac lobortis odio. Donec egestas vel risus ac gravida. Curabitur consectetur lobortis auctor. Fusce cursus semper lorem, ac auctor nunc fermentum sit amet. Pellentesque nec lacus in magna consectetur viverra. Proin quis turpis laoreet, aliquam est ac, lacinia nibh. Aliquam erat volutpat. Curabitur placerat consectetur maximus. Mauris accumsan leo non lacus vehicula efficitur.

Фотогалерея

Место для фотогалереи

Новости

Место для новостей

Семантика работы\хранения UpCast“инга \ DownCast”инга в CLR

Начнем с теории. Допустим,имеется следующие классы:
class A{} class B : A{} class C : B{}
Далее,мы делаем UpCast :
A a1 = new C();
Будет ли следующее утверждение верным : объект a1 является объектом типа C,и базовым классом для него является тип А (то бишь вверх по иерархии) !?
Далеко не уходя от кассы, представьте что добавили в код следующее:
class A { public virtual void Method() { Console.WriteLine("Method A invoked"); } } class B : A { public new virtual void Method() { Console.WriteLine("Method B invoked"); } } class C : B { public override void Method() { Console.WriteLine("Method C invoked"); } }
Что будет выведено на экран ? В первую очередь покажется,что тут все очевидно,и вывод выходе получим :
Method A invoked Method A invoked Method С invoked Method C invoked
Но на самом то деле,мы получим : Method A invoked Method A invoked Method A invoked Method C invoked
Исходя из этой логики,выходит что мое предыдущее высказывание не верное,и это значит,что все таки базовым классом для C,является B ?

Теперь перейдем к другой части вопроса. К примеру имеем код:
class Program { static void Main(string[] args) { //объект типа класса А A a = new A(); //объект типа класса B B b = new B(); //UpCast, который равен объекту "b" A a1 = b; //UpCast как отдельный объект A a2 = new B(); //DownCast, который равен объекту "а1" B b1 = (B)a1;
B b2 = a as B; // вернет Null, т.к. DownCast //без предварительного UpCast не возможен
// B b2 = new A(); - невозможно из за безопасности типов
//сравниваем b с а1,видим что типы идентичны. Console.WriteLine(b.GetType() == a1.GetType()); //сравниваем а2 с а1,видим что типы идентичны. Console.WriteLine(a2.GetType() == a1.GetType()); //сравниваем b1 и а1,видим что типы идентичны Console.WriteLine(b1.GetType() == a1.GetType());
//Проверяем сами обьекты,вернет True Console.WriteLine(a1.Equals(b)); //вернет False,но реализация этих объектов идентична Console.WriteLine(a2.Equals(a1)); //Вернет True Console.WriteLine(b1.Equals(a1));
Console.ReadKey(); } } class A { } class B : A { }

Так все же,что происходит за кулисами? Как при UpCast"е \ DownCast"е ,два одинаковых объекта(точнее две ссылки,указывающие на один и тот же объект),имеют различную реализацию(да,да - это полиморфизм). За счет чего это достигается(то бишь,как CLR реализует эту модель поведения) и как примерно выглядит все это чудо-юдо в самой среде CLR ? Как выглядит "наследование" внутри CLR между типами?


Ответ

По порядку:
Будет ли следующее утверждение верным : объект a1 является объектом типа C,и базовым классом для него является тип А (то бишь вверх по иерархии) !?
Нет. Корректным утверждением будет следующее: объект a1 является объектом типа C,и базовыми классами для него являются типы B и А
Разница большая, поскольку каждый тип в иерархии наследования может привносить новые аспекты поведения.
Теперь дальше:
class A { public virtual void Method() { Console.WriteLine("Method A invoked"); } } class B : A { public new virtual void Method() { Console.WriteLine("Method B invoked"); } } class C : B { public override void Method() { Console.WriteLine("Method C invoked"); } }
А данном примере сложно сказать, что именно хотел сказать автор этих строк с точки зрения бизнес-логики, но звучит это примерно так: класс B добавляет новый метод Method, но, к сожалению, он использует метод, имя которого уже есть в базовом классе. Но класс B хочет не "подменить" поведение метода из базового класса, а создать свой собстенный метод, который ничего не имеет общего с методом базового класса, кроме имени.
Подобная практика приводит к неоднозначному поведению, поскольку теперь выбор метода определяется не только динамическим типом объекта (типом времени исполнения), но и типом переменной (типом, известным компилятору): если используется переменная типа A, то будет вызван метод из класса A. Если же тип переменной - это B или C, то будет использоваться другая ветка методов (ниже будет объяснение, почему это так).
Другими словами, с точки зрения метода Method существует две ветки: одна начинается типом А и им же и ограничивается, и есть другая полиморфная ветка, которая начинается в типе B и продолжается в наследнике - типе С
Теперь немного о том, как это устроено в CLR.
Для каждого типа CLR хранит табличку с методами (Method Table), где каждая запись описывает отельный метод - его сигнатуру и признак того, переопределяет ли данный слот метод из базового класса.
Когда вы объявили метод с приставкой new в классе B, CLR добавила "новый" метод в табличку, при этом пометила этот метод, как новый, не связанный с методом из базового класса. В случае же класса С, метод Method в табличке методово типа C помечен, как полиморфный, т.е. переопределяющий поведение непосредственного базового класса.
Теперь стоит сказать, как происходит разрешение метода во время исполнения: в случае вызова a.Method будет вначале определен статический тип переменной a, после чего в таблице методов будет найден метод Method. Если статический тип переменной - это A, то вначале будет просмотрена таблица методов типа A. И в этом случае CLR увидет, что этот метод виртуальный. После чего будет определен реальный тип объекта (например, тип C) и CLR посмотрит, а есть ли у этого типа переопределение метода, объявленного в типе A. CLR получит отрицательный ответ, поскольку тип C не переопределяет метод Method, объявленный в типе A (ведь этот тип переопределяет метод Method типа B).
Вот и получается, что результат разрешения имени метода у нас теперь зависит не только от типа времени исполнения, но и от типа переменной времени компиляции.

Выборка из двух таблиц в MySQL

В базе имеется 2 таблицы с одинаковыми полями. К примеру, в таблице Table1 есть поле NAME, и в Table2 есть поле NAME. Каким образом можно вывести все данные из обоих таблиц, у которых значение поля NAME = FizLico?


Ответ

Не совсем понятно, что вам нужно вывести.
Можете попробовать UNION (при условии, что столбцы в таблице 1 и в таблице 2 одинаковые):
select * from ( select * from table1 where name = 'FizLico' UNION /*либо UNION ALL при необходимости сохранения дубликатов*/ select * from table2 where name = 'FizLico') b order by client
Пример на sqlfiddle.

Как перехватить вызов номера или “вызвать” им приложение?

Всем привет, уже не редко встречается как при помощи вызова какого нибудь "супер"-номера (например ##007*#*, при этом набирать его не надо), происходит вызов какого либо приложения или запланированной цели. Как такое можно реализовать?
Ну вот если кто-то ещё не понял мою мысль, привожу в пример один из антивирусов (названия не помню, тем более за рекламу мне ни кто не платил 😂), который постоянно скрыт, но если набрать номер (а на самом деле пароль, который был введён ранее в настройках) и соответственно позвонить, то антивирус сразу же разворачивается перед юзером.


Ответ

Задача довольно простая.
Создаете BroadcastReceiver, который будет перехватывать набранные номера:
public class OutgoingReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) {
// получаем набранный номер String mOutgoingNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); if (mOutgoingNumber.equals("##007*#*")) { setResultData(null); // сбрасываем звонок
// другие необходимые вам действия при наборе нужного номера
} } }
Регистрируем ресивер на срабатывание при наборе исходящего номера (интент NEW_OUTGOING_CALL) и даем необходимые разрешения на контроль исходящих звонков (пермишен PROCESS_OUTGOING_CALLS) в манифесте приложения.
AndroidManifest.xml:





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

Класс без данных

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


Ответ

Например, класс без членов данных может задавать интерфейс для своих производных классов. То есть такой класс может содержать лишь объявления методов (виртуальных, не виртуальных, статических).
Либо класс может быть контейнером для некоторых методов, чаще всего статических.

Удаление дублирующихся строк в файле

Есть текстовой файл, в нём 1000 Email-ов, каждый Email с новой строки. Часть из них повторяются. Необходимо, чтобы на выходе после обработки был файл только с уникальными Email-ами. Как это реализовать с помощью Python 3?


Ответ

Самый быстрый и простой способ убрать дубликаты из списка - преобразовать его к множеству. Конструктор множества set() принимает любой итерируемый объект, в том числе дескриптор файла. После чего остаётся только преобразовать множество обратно в строку и записать в другой файл:
with open('emails.txt') as in_fh, open('deduplicated.txt', 'w') as out_fh: out_fh.write(''.join(set(in_fh)))

Компиляция программы с другими значениями переменных

Уже задавал похожий вопрос, но возникла надобность передать строку в программу на стадии компиляции.
Есть код:
#ifdef VALUE std::cout << VALUE << std::endl; #endif // VALUE #ifndef VALUE char* VALUE = "not defined"; std::cout << VALUE << std::endl; #endif // !VALUE
При компиляции с параметром
cl /DVALUE=100 core.cpp
Всё работает и программа выдаёт число.Как я понял, ключ /D - это вариант только для чисел, а есть ли аналогичный ключ для строк?


Ответ

Это не для чисел, а для литералов. Просто в тексте VALUE до компиляции будет заменено на то, что вы подставите.
Хотите с кавычками - подставьте в командной строке Windows
cl /DVALUE=\"100\"
А вообще - читайте о препроцессоре, это большая и интересная тема... Например, тут

Как на чистом css стилизовать последний нечётный элемент?

Есть условный родительский блок с секциями, которые добавляются и удаляются динамически:

...

Можно ли на чистом css стилизовать последнюю нечётную секцию? То есть если секций чётное число, тогда ничего не происходит, а если нечётное, то к последней секции применяются другие стили?


Ответ

Для этого можно использовать псевдокласс последнего элемента :last-child и с помощью :nth-child выделить все нечётные элементы:
section { display: block; width: 200px; height: 50px; margin-bottom: 5px; background-color: black } section:last-child:nth-child(2n+1) { background-color: red; }


Как создать такие треугольники с помощью псевдоэлементов?

Здравствуйте,помогите,пожалуйста,создать вот такие вот треугольники...У меня,правда,нет идей. Уже гуглил на эту тему,но ничего стоящего не нашел. Изображением вставлять не канает. Нужно именно с помощью CSS.


Ответ

Gradient Generator - colorzilla.com
CSS triangle generator - http://apps.eky.hk/css-triangle-generator/
* { padding: 0; margin: 0; box-sizing: border-box; } .b-breadcrumbs { text-align: center; font-size: 0; background: #271E19; padding: 25px; line-height: 1.15; } .b-breadcrumbs > li { display: inline-block; vertical-align: top; font-size: 16px; margin-left: 34px; } .b-breadcrumbs > li > a { height: 48px; position: relative; display: block; color: #000; font-weight: 700; padding: 15px; background: -moz-linear-gradient(top, rgba(255, 201, 55, 1) 0%, rgba(255, 201, 55, 1) 50%, rgba(255, 165, 35, 1) 50%, rgba(255, 165, 35, 1) 100%); /* FF3.6-15 */ background: -webkit-linear-gradient(top, rgba(255, 201, 55, 1) 0%, rgba(255, 201, 55, 1) 50%, rgba(255, 165, 35, 1) 50%, rgba(255, 165, 35, 1) 100%); /* Chrome10-25,Safari5.1-6 */ background: linear-gradient(to bottom, rgba(255, 201, 55, 1) 0%, rgba(255, 201, 55, 1) 50%, rgba(255, 165, 35, 1) 50%, rgba(255, 165, 35, 1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ } .b-breadcrumbs > li > a:before, .b-breadcrumbs > li > a:after { content: ''; position: absolute; left: 100%; width: 0; height: 0; border-style: solid; } .b-breadcrumbs > li > a:before { top: 0; border-width: 24px 0 0 24px; border-color: transparent transparent transparent #FFC937; } .b-breadcrumbs > li > a:after { bottom: 0; border-width: 24px 24px 0 0; border-color: #FFA523 transparent transparent transparent; } .b-breadcrumbs > li:last-child > a:before, .b-breadcrumbs > li:last-child > a:after { display: none; } .b-breadcrumbs > li > a > span { position: absolute; top: 0; right: 100%; height: 100%; width: 24px; } .b-breadcrumbs > li > a > span:before, .b-breadcrumbs > li > a > span:after { content: ''; position: absolute; width: 0; height: 0; border-style: solid; left: 0; } .b-breadcrumbs > li > a > span:before { top: 0; border-width: 0 24px 24px 0; border-color: transparent #FFC937 transparent transparent; } .b-breadcrumbs > li > a > span:after { bottom: 0; border-width: 0 0 24px 24px; border-color: transparent transparent #FFA523 transparent; } .b-breadcrumbs > li > a:hover { color: #fff; background: red; } .b-breadcrumbs > li > a:hover:before { border-left-color: red; } .b-breadcrumbs > li > a:hover:after { border-top-color: red; } .b-breadcrumbs > li > a:hover > span:before { border-right-color: red; } .b-breadcrumbs > li > a:hover > span:after { border-bottom-color: red; }


Вариант 2 - с использованием clip-path
* { padding: 0; margin: 0; box-sizing: border-box; } .b-breadcrumbs { text-align: center; font-size: 0; background: #271E19; padding: 25px; } .b-breadcrumbs > li { display: inline-block; vertical-align: top; font-size: 16px; margin-left: 0; } .b-breadcrumbs > li > a { position: relative; display: block; color: #000; font-weight: 700; padding: 15px 25px; background: -moz-linear-gradient(top, rgba(255, 201, 55, 1) 0%, rgba(255, 201, 55, 1) 50%, rgba(255, 165, 35, 1) 50%, rgba(255, 165, 35, 1) 100%); /* FF3.6-15 */ background: -webkit-linear-gradient(top, rgba(255, 201, 55, 1) 0%, rgba(255, 201, 55, 1) 50%, rgba(255, 165, 35, 1) 50%, rgba(255, 165, 35, 1) 100%); /* Chrome10-25,Safari5.1-6 */ background: linear-gradient(to bottom, rgba(255, 201, 55, 1) 0%, rgba(255, 201, 55, 1) 50%, rgba(255, 165, 35, 1) 50%, rgba(255, 165, 35, 1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ -webkit-clip-path: polygon(0 0, 90% 0, 100% 50%, 90% 100%, 0 100%, 10% 50%); clip-path: polygon(0 0, 90% 0, 100% 50%, 90% 100%, 0 100%, 10% 50%); } .b-breadcrumbs > li:first-child > a{ padding-left: 15px; -webkit-clip-path: polygon(90% 0, 100% 50%, 90% 100%, 0 100%, 0 0); clip-path: polygon(90% 0, 100% 50%, 90% 100%, 0 100%, 0 0); } .b-breadcrumbs > li:last-child > a{ padding-right: 15px; -webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 10% 50%); clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 10% 50%); } .b-breadcrumbs > li > a:hover{ color: #fff; background: red; }

Рекурсия вызваная из базового класса

Все мы знаем обычную рекурсию, например:
функция имя(){ условие_завершения; имя(); }
Понятно что эта функция будет существовать в памяти в нескольких экземплярах до завершения всей цепочки вызовов.
Встретил вот такой код:
class SimpleDelegate : public QStyledItemDelegate { public: void paint(QPainter* pPainter, const QStyleOptionViewItem& option, const QModelIndex& index ) const ...... условие_выхода ...... { QStyledItemDelegate::paint(pPainter, option, index); // рекурсия ? } };
Вроде бы тоже рекурсия но как она работает? То ли копия базового объекта создается то ли просто метод дублируется для текущего объекта, то ли.. , в общем не понятно.


Ответ

В данном определении функции-члена класса рекурсии нет
class SimpleDelegate : public QStyledItemDelegate { public: void paint(QPainter* pPainter, const QStyleOptionViewItem& option, const QModelIndex& index ) const ...... условие_выхода ...... { QStyledItemDelegate::paint(pPainter, option, index); // рекурсия ? } };
Имеются две различные функции. Одна функция - это SimpleDelegate::paint , другая функция - это QStyledItemDelegate::paint
Первая функция в области определения производного класса скрывает объявление второй функции с тем же самым именем в базовом классе. Поэтому если вы хотите из функции производного класса вызвать одноименную функцию базового класса, то вам нужно указывать ее квалифицированное имя, что и делается в приведенном примере.
Рассмотрите данную демонстрационную программу
#include #include
int main() { struct A { void f(const char *) const { std::cout << "Hello"; } void f(char) const { std::cout << ' '; } };
struct B : A { void f(const std::string &s ) const { A::f(nullptr); A::f(' '); std::cout << s << std::endl; } };
B().f(std::string("perfect"));
return 0; }
Ее вывод на консоль
Hello perfect
Здесь функция, объявленная в производном классе B скрывает одноименные функции, объявленные в базовом классе A. Поэтому чтобы обратиться к этим функциям базового класса в области определения производного класса, следует использовать квалифицированные имена функций базового класса.
Другой альтернативный подход при условии, что нет неоднозначности в перегрузке функций, это использовать using объявления в производном классе. Например,
struct B : A { using A::f; void f(const std::string &s ) const { f(nullptr); f(' '); std::cout << s << std::endl; } };
Однако, если сигнатуры одноименных функций в базовом и производном классах совпадают, то, чтобы исключить неоднозначность, придется явно указывать квалифицированные имена функций для базового класса.

Сохранить параметр css в cookie [дубликат]

На данный вопрос уже ответили: Как записать в cookie присвоенный элементу класс 1 ответ Всем привет. У меня есть элемент, свойство которого изменяется при нажатии на пользователем на определенную кнопку. А именно, ul которому присваивается display: none. Мне нужно, чтобы это сохранялось при перезагрузке страницы. Как с помощью cookie и jquery сохранять стиль элемента?
upd. Наверное, некорректно объяснил проблему, приведу все с примером кода.
$('.odz-toggle').after().next().css("display", "none"); // Убираем лишние блоки $(".odz-toggle").click(function () { $(this).closest('li').siblings().find('div').slideUp('normal'); $(this).next('ul').slideToggle('normal'); }); // открываем нужный блок при нажатии на кнопку
Необходимо позицию нужного ul'a (открытый или закрытый) сохранить в cookie.


Ответ

Создать куки с параметрами
$(document).ready(function(){ $.cookie("background:","red"); })
Считать информацию из кукиз:
$.cookie("background:");
Ответ: к дополниному вопросу: Проверяем если елемент закрыт или открыт, затем пишем куки
$(document).ready(function(){
$('.odz-toggle').after().next().css("display", "none");
var ter = $('.innersubmenu-ul'); for(i =0; i < ter.length; i++) { if($.cookie('visible'+i) != null) { $('.innersubmenu-ul').eq($.cookie('visible'+i)).css('display', "block"); } if($.cookie('hidden'+i) != null) { $('.innersubmenu-ul').eq($.cookie('hidden'+i)).css("display", "none"); } }
$(".odz-toggle").click(function () {
$(this).closest('li').siblings().find('div').slideUp('normal');
var ind = $(this).parent().index(); var open = $.cookie('visible'+ind); if(open == "null") { $(this).next('ul').slideToggle('normal'); $.cookie("hidden"+ind ,null); $.cookie("visible"+ind ,$(this).parent().index()); } else { $(this).next('ul').slideToggle('normal'); $.cookie("visible"+ind ,null); $.cookie("hidden"+ind ,$(this).parent().index()); } }); });

Массив из значений false

Читаю книгу и вычитал, что по умолчанию переменные типа boolean имеют значение false. Следовательно, если я создам массив из четырёх значений false, мне достаточно просто написать так?
boolean[] flags = new boolean[4];
А если так?
Boolean[] flags = new Boolean[4];
Или в массивax это правило не работает? Будет null? Если работает, то где не работает?


Ответ

Boolean - объект, и для него будет null. boolean - примитив, и для него будет false

'cout << …' или 'cout.put(…)'?

Что лучше использовать для вывода на консоль символов: 'cout << ...' или 'cout.put(...)'?


Ответ

Функция-член класса put стандартного класса basic_ostream, объявленная как
basic_ostream& put(char_type c)
предназначена только для объектов типа char_type, Она не перегружена для объектов других типов. Поэтому, например, чтобы написать эквивалентный вывод данным предложениям
int x = 10;
std::cout << "x = " << x << std::endl;
вам придется писать
int x = 10;
std::cout.put( 'x' ).put( ' ' ).put( '=' ).put( ' ' ) << x << std::endl;
что выглядит очень вычурно.
Внутренне такие функции, как, например, std::endl и std::ends используют функцию put. То есть эта функция считается функцией низшего уровня. В прикладных программах лучше использовать operator << , который перегружен для всех стандартных типов и кроме того может быть перегружен для пользовательских типов. При этом код с использованием этого оператора выглядит более естественным и не вызывает вопросов.
На низшем уровне, например, когда вы реализуете свою функцию более высокого уровня, как, например, тот же самый оператор operator << вы можете использовать функцию put

Совместный доступ к файлам из разных процессов

Возникает ошибка открытия бинарного файла: "файл уже открыт". Дело в том, что у меня есть два приложения: одно, написанное на C++Builder:
void __fastcall TForm1::BitBtn1Click(TObject *Sender) { TFileStream *fileStream;
fileStream->Free();
fileStream = new TFileStream("E:/DELETE/n.dat",fmOpenReadWrite); }
void __fastcall TForm1::StringGrid2SetEditText(TObject *Sender, int ACol, int ARow, const UnicodeString Value) { fileStream->Position = (sizeof(nr) * nn);
fileStream->Write(&nrt.nn, sizeof(nr)); }
В данном приложении вносятся изменения и сохраняются в файл. Далее я читаю в C# то что записалось:
private List ReadBinaryFiles(string path) { List testL = new List();
Int32 obj = 0; try { using (BinaryReader reader = new BinaryReader( File.Open( path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) { while (reader.PeekChar() > -1) { obj = reader.ReadInt32();
testL.Add(obj); } } } catch (Exception e) { Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Ошибка: {0}", e.Message);
Console.ResetColor(); } return testL; }
Я понимаю, что вверху нужно закрыть этот файл, но мне нужно работать с файлом без его закрытия, возможно что-то придумать? Если нет, тот где правильно поставить fileStream->Free();, чтобы при повторной записи файл был доступен? Может возможно открыть файл с разрешением на совместный доступ на чтение?


Ответ

Возможно вам нужен fmShareDenyNone (для С++) и FileShare.ReadWrite (для C#).
Это даст вам возможность открыть файл так чтоб другие процессы тоже могли с ним работать.
fileStream = new TFileStream("E:/DELETE/n.dat", fmOpenReadWrite | fmShareDenyNone);
fmShareDenyNone is one of the attributes assignable in the Create. The TFileStream is used to read and write files. It specifies file sharing that does not prevent any other applications from reading from or writing to the file.

Функция fseek()

Не могу понять принцип работы функции fseek в С. Допустим, сначала открываем текстовый файл для чтения: fp=fopen(...). Это приводит к тому, что создается указатель на структуру FILE, содержимое полей _base и _prt при этом NULL. Далее пытаемся прочесть несколько символов ch=getc(fp), ... Часть файла заносится в буфер, адрес которого записывается в _base, а позиционирование по файлу осуществляется по указателю _ptr. Казалось, что когда мы хотим получить доступ к определенному байту, fseek просто корректирует значение _ptr. Но как я понял, получается, что fseek просто заново записывает файл в буфер уже начиная с указанного в аргументах места. Или я неправильно понял?


Ответ

когда мы хотим получить доступ к определенному байту, fseek просто корректирует значение _ptr.
Новая позиция в файле может находиться за пределами буфера, причём в обе стороны. В вашей реализации fseek() решили, что нерационально проверять граничные условия, а проще сразу
fseek просто заново записывает файл в буфер уже начиная с указанного в аргументах места.
Но на самом деле это не имеет значения. Потому что реализаций fseek() может быть (и есть) много, как и вариантов структуры FILE. И что актуально для одной реализации/одного варианты структуры, не имеет смысла для других. Например, "моя" FILE (в смысле на моей ОС и в моём компиляторе) выглядит так:
struct _IO_FILE { int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ #define _IO_file_flags _flags
/* The following pointers correspond to the C++ streambuf protocol. */ /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ char* _IO_read_ptr; /* Current read pointer */ char* _IO_read_end; /* End of get area. */ char* _IO_read_base; /* Start of putback+get area. */ char* _IO_write_base; /* Start of put area. */ char* _IO_write_ptr; /* Current put pointer. */ char* _IO_write_end; /* End of put area. */ char* _IO_buf_base; /* Start of reserve area. */ char* _IO_buf_end; /* End of reserve area. */ /* The following fields are used to support backing up and undo. */ char *_IO_save_base; /* Pointer to start of non-current get area. */ char *_IO_backup_base; /* Pointer to first valid character of backup area */ char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers; struct _IO_FILE *_chain; int _fileno;
#if 0 int _blksize; #else int _flags2; #endif _IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary */ /* 1+column number of pbase(); 0 is unknown. */ unsigned short _cur_column; signed char _vtable_offset; char _shortbuf[1];
/* char* _save_gptr; char* _save_egptr; */ _IO_lock_t *_lock; #ifdef _IO_USE_OLD_IO_FILE };
Немного отличается от пары _base/_ptr?

Как сравнить две метки времени ЧЧ:ММ?

В JS есть переменная var a = '14:35', значение a изменяется динамически, она получает время. Надо сравнить со временем браузера, время браузера это var b = '14:37'. Если время браузера больше чем на 2 минуты, то есть, допустим, 14:37, то вывести alert('опоздал на 2 минуты'). Как такое реализовать?


Ответ

var a = '23:59'; var b = '00:10'; //разделяем минуты и часы, часы умножаем на 60. //Минуты умножаем на 1, чтобы преобразовать в число var amin=a.split(':')[0]*60+a.split(':')[1]*1; var bmin=b.split(':')[0]*60+b.split(':')[1]*1; //Если второе время меньше первого больше чем на 12 часов, добавим 24 часа: if(bmin+60*12 0) alert('опоздал на '+c+' минут');

Java аннотации - реализация бизнес логики

Хочу написать свои аннотации, так как возникло несколько идей, но не могу понять как это сделать. Вроде легко, но вопрос: как к аннотации прикрепить бизнес логику? Что я могу сделать с теми данными которые мне пришли в аннотации. пример: @Annotation(SomeValue.VALUE). И как мне взять это велью с сделать с ним какую-то бизнес логику? Например засунуть в какой-то метод из другой библиотеки прокрутить его и вернуть значения..


Ответ

Для использования своей аннотации нужно:
Реализовать аннотацию (public @interface MyAnnotationExample c типом аннотации ElementType - например: класс/метод/конструктор/поле и т.п.). Использовать эту аннотацию MyAnnotationExample в вашем коде (в соответствии с типом ElementType аннотации MyAnnotationExample), т.е. добавить аннотацию к классу/методу/полю/и т.п. Реализовать обработчик этой аннотации через рефлексию
Пример #1. Аннотация на класс и чтение аннотации класса через рефлексию.
Создадим аннотацию MyAnnotationExampleForClass
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target(value = ElementType.TYPE) //указание что данная аннотация вешается на класс @Retention(value = RetentionPolicy.RUNTIME) //аннотация доступна в процессе работы модуля public @interface MyAnnotationExampleForClass {
String name() default "default name"; //в name() мы будем хранить значения аннотации }
Создадим класс MyClassExample с использованием аннотации MyAnnotationExampleForClass
@MyAnnotationExampleForClass(name = "this is my annotation value!!!") public class MyClassExample { ... }
Создадим класс MyAnnotationProcessorExample для получения значений аннотаций:
class MyAnnotationProcessorExample { MyClassExample myClass = new MyClassExample(); //получаем нашу аннотацию из нашего объекта MyAnnotationExampleForClass a = myClass.getClass().getAnnotation(MyAnnotationExampleForClass.class); System.out.println("выводим значение аннотации = " + a.name()); System.out.println("печатаем тип аннотации со значением = " + a.toString()); }
Пример #2. Аннотация на метод класса и чтение аннотации метода через рефлексию. Добавим еще аннотацию MyAnnotationExampleForMethod для метода:
@Target(value = ElementType.METHOD) @Retention(value = RetentionPolicy.RUNTIME) public @interface MyAnnotationExampleForMethod {
String name() default "default name 2"; }
Добавим в наш класс MyClassExample (из примера #1) новый метод runForest()
@MyAnnotationExampleForClass(name = "this is my annotation value!!!") public class MyClassExample {
@MyAnnotationExampleForMethod(name = "this is my method-annotation value") public void runForest() { System.out.println("Our Forest run very good!"); } }
Создадим класс MyAnnotationProcessorExample2 для получения значений аннотаций:
class MyAnnotationProcessorExample2 { MyClassExample myClass = new MyClassExample();
//получаем наш метод из нашего объекта Method m = tm.getClass().getMethod("runForest");
//получаем аннотацию из нашего метода MyAnnotationExampleForMethod a = m.getAnnotation(TimeAnnotationMethod.class);
System.out.println("выводим значение аннотации = " + a.name()); System.out.println("печатаем тип аннотации со значением = " + a.toString()); }
Теперь можно эти классы-обработчики MyAnnotationProcessorExample и MyAnnotationProcessorExample2 использовать в нужных местах для обработки бизнес-логики. Примеры привел самые примитивные, только для общего понимания. Для более полноценных реализаций нужно разбираться с понятием java reflection.
Также рекомендую посмотреть темы:
В каких случаях на практике применять рефлексию, аннотации? Зачем создавать собственные аннотации? Аннотация в Java EE

Не пойму что от меня хочет компилятор

Здравствуйте вот есть код, вроде написан правильно, пишу на CodeBlocks:
#include #include #include
using namespace std;
template elemType& min (const std::vector &vec) { typename std::vector::iterator select = vec.begin(), it = next(select), end_it = vec.end(); for ( ; it != end_it; it++ ) { if ( *it < *select ) select = it; } return *select; };
int main() { int massiv[10] = {35, 66, 98, 15, 32, 41, 24, 90, 55, 100}; std::vector vec_train(massiv,massiv+10);
min(vec_train); return 0; }
Но выдает следующую ошибку:
error: conversion from 'std::vector::const_iterator {aka __gnu_cxx::__normal_iterator >}' to non-scalar type 'std::vector::iterator {aka __gnu_cxx::__normal_iterator >}' requested|
Как такие ошибки вообще расшифровывать самостоятельно, если я только недавно начал учить программирование? Спасибо.


Ответ

В функции параметр определен как константная ссылка
elemType& min (const std::vector &vec) { ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Поэтому такие функции, как begin и end возвращают итератор типа const_iterator. Исправьте
typename std::vector::const_iterator select = vec.begin(), it = next(select), end_it = vec.end();
Также вам следует включить заголовок
#include
так как в программе используется функция std::next, объявленная в этом заголовке.
Также имейте в виду, что функция min некорректна, так как в общем случае переданный вектор может быть пустым. А это значит, что в функции имеет место обращение к не существующему элементу вектора и, соответственно, разыменование недействительного итератора.
Имеется стандартный алгоритм std::min_element, объявленный в заголовке , который выполняет поставленную задачу.
Ваша функция может быть определена по аналогии с этим алгоритмом. Например,
#include #include
template auto min( const std::vector &vec ) { auto select = vec.begin();
if ( select != vec.end() ) { for ( auto it = vec.begin(), end_it = vec.end(); ++it != end_it; ) { if ( *it < *select ) select = it; } }
return select; }
int main() { int massiv[] = { 35, 66, 98, 15, 32, 41, 24, 90, 55, 100 }; const size_t N = sizeof( massiv ) / sizeof( *massiv );
std::vector vec_train( massiv, massiv + N );
auto it = min( vec_train );
if ( it != vec_train.end() ) { std::cout << "Minimum is " << *it << std::endl; }
return 0; }
Вывод прогоаммы на консоль
Minimum is 15
Если ваш компилятор не поддерживает спецификатор типа auto, то функцию можно определить как
template typename std::vector::const_iterator min( const std::vector &vec ) { typedef typename std::vector::const_iterator const_iterator;
const_iterator select = vec.begin();
if ( select != vec.end() ) { for ( const_iterator it = vec.begin(), end_it = vec.end(); ++it != end_it; ) { if ( *it < *select ) select = it; } }
return select; }

Работа промисов

Добрый Вечер. Наткнулся на такой пример с промисами :
var promise = new Promise(function(resolve, reject) { resolve(1); });
function logger(message) { console.log(message); }
promise .then(logger) .then(logger(2)) .then(() => logger(3));
В результате на выходе результат - 2, 1, 3. Правильно ли я понимаю, что перед тем, как начинать выполнять данный код, с начала отдается приоритет вызову функции logger ? Именно поэтому в результате с начала идет 2 ? Функция logger, возвращает undefined, а в консоль пишет 2. Затем, после выполнения промиса, после первого then (который вернул вместо промиса undefined), в консоль запишется 1, а уж затем вернется 3.


Ответ

Promise нужен для выполнения действий со значением, которого на момент определения действий может ещё не быть. Это чтобы было немножко понятнее, какова цель всего происходящего здесь.
Ещё обращу внимание, что существующие реализации JS однопоточны и переключения в пределах одной исполняющей среды (скажем, вебворкеры я считаю отдельными средами) происходят только между функциями, после завершения выполнения каждой. Разумеется, функции внутри себя могут синхронно (непосредственно) вызывать другие функции, но многое в JS API опирается на асинхронные вызовы, которые лишь приводят к добавлению в очередь событий и, когда-нибудь, обработку циклом событий.
Ну да к делу.
Вывод у вас происходит при вызове функции logger. Посмотрим, когда она вызывается.
Сначала выполняется наружный код. Определение цепочки промисов. Пока выполнение этого участка не дойдёт до самого конца, никакая другая функция вызвана по какому-либо событию (вроде разрешения промиса, что здесь происходит) не будет.
promise .then(logger) .then(logger(2)) .then(() => logger(3));
В первом вызове then аргументы разрешаются в значения напрямую, без вычислений. Никаких вызовов logger там не происходит. Пока что. Во втором вызове then аргумент уже выражение, требующее вычисления перед передачей: вызов функции logger. Тут-то и вызывается logger(2) и выводится 2 А возвращается из logger... ничего, что снаружи видно как undefined, которое функцией не является а потому приводит к "сквозному пробрасыванию" результата в следующий then (если таковой, как здесь, имеется), поскольку:
If the first argument is omitted or provided a non-function, the new Promise that is created simply adopts the fulfillment state of the Promise that then is called on (if it becomes fulfilled). Если первый аргумент не передан, или в нём передана не функция, то промис наследует состояние разрешения у промиса, на котором then был вызван (если он разрешается). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
Я б сказал, что игнорирование типа аргумента в then это грубый хак, сбивающий с толку и склоняющий к злоупотреблениям, но у него могут быть свои мотивы. Без большой необходимости кормить в then не-функции не стоит. В третьем вызове аргумент является функциональным выражением (стрелочной функцией, если точно), но для его вычисления вызовы logger не нужны, т. к. его результатом является функция, которая при вызове (но не создании!) вызывает logger и выводит что-то в консоль. А на этом этапе эта функция лишь создалась.
А потом уже управление переходит внутрь, поскольку промис требует запуска, его событие ждёт своей очереди на обработку. В зависимости от другого выполняющегося в той же машине JS-кода может быть и не сразу, но в рамках примера другого кода нет, так что тут — сразу внутрь цепочки.
Сначала вызывается функция из конструктора Promise. Она приводит к разрешению промиса со значением 1 Затем вызывается logger с аргументом, полученным из прошлого промиса: получается logger(1). А потому происходит вывод 1, а промис разрешается со значением undefined (т. к. функция ничего не вернула).
When a value is simply returned from within a then lambda, it will effectively return Promise.resolve() Затем сталкиваемся с пустым промисом, образованным без функции... фиг знает, что там внутри ещё происходит, но результат прошлого разрешения промиса (undefined) просто считается результатом и у этого и передаётся далее, состояние промиса (разрешился) при этом сохраняется. Затем функция () => logger(3) вызывается с аргументом undefined, но JS наплевать на лишние аргументы и в результате успешно выполняется тело функции, выполняется logger(3) и выводится 3

Поиск значение обьекта в массиве

Есть массив с обьектами
data = [{service_id: 7777}, {service_id:9999}]
у меня есть допустим переменная с айди
var myid = 9999
как мне проверить существование этого ади в массиве ?
средствами angularjs или javascript


Ответ

Вот пример:
var data = [{service_id: 7777}, {service_id:9999}] function getServicebyId(id) { return data.filter( function(data) { return data.service_id== id}); } var myid = 9999 var found = getServicebyId(myid); alert(found)

считать значения переменных в словарь из строки вида: “key1=value1 key2=value2 key3=value3”

Вводится строка виде "a=1 b=2 c=3". Необходимо считать значение переменных а,b,c в эти переменных. Проблема в том, что эти значения могут быть вперемешку(Не a,b,c, а b,a,c). Желательно, сохранить вообще всё это в словарь, но сойдёт и в переменные


Ответ

Вот записывает в словарь с ключами 'a', 'b' и 'c' и соответствующими им значениями:
d = {i.split('=')[0]: int(i.split('=')[1]) for i in input().split(' ')} print(d)
Или вот так:
d = {} for i in input().split(' '): spl = i.split('=') d[spl[0]] = int(spl[1]) print(d)

Получение данных из потока

Приветствую. Пытаюсь получить данные из потока.
process.stdin.setEncoding('utf8');
process.stdin.on('readable', () => { let chunk = String(process.stdin.read()); console.log(chunk); });
Мне возвращается
Input: 10 2 Your output: 10 2 null
Как избавиться от null?


Ответ

Как вариант, проверить, что process.stdin.read() вернул что-то полезное (не null).
Естественно, проверить надо до каста к строке, а не после. Примерно так:
process.stdin.on('readable', () => { var chunk = process.stdin.read();
if (!chunk) { return; }
chunk = "" + chunk;
console.log(chunk); });

Правильная нумерация ПО?

Есть версия ПО 2.9.9
Нужно выпустить новую версию, при этом не хотелось бы переходить на 3.0 Так и не смог разобраться, под какой версией выпустить ПО?
2.9.10? 2.10.1? 2.9.91?
Да так, чтобы было понятно людям, что эта версия новее предыдущей.


Ответ

Проблема: вы руководствуетесь принципами визуальной упорядоченности при установке версии. Версионирование не имеет никаких связей с визуальной упорядоченностью. Конфликт: вы не можете выбрать между виузальной упорядоченностью, которая говорит вам сделать 3.0.0, и принципом мажорного релиза, который осознаете скорее всего по-своему, но понимаете, что мажорный релиз это не "когда все цифры после первой становятся девятками". Решение: выбрать только одно из двух, потому что принцип мажорной версии запрещает вам скакать, как получится, а визуальная упорядоченность не дает вам использовать двузначное число в качестве одного из компонентов версии.
Как все-таки хоть немного программист я могу лишь призвать сделать выбор в пользу разумного назначения версии. Насколько понял, вы уже читали про семантическое версионирование, но, судя по комментарию, думаю, что попытаться адаптировать конвенцию для вас стоит.
Семантическая версия состоит из трех номеров: major, minor, patch. Они различаются следующими вещами:
patch-версия инкрементируется при выпуске релиза, закрывающего баги minor-версия инкрементируется при выпуске релиза с новым функционалом, не затрагивающем старый major версия инкрементируется при выпуске релиза, которым невозможно пользоваться так, как прежде
Поэтому определение "какую версию мне использовать" превращается в довольно простой условный блок:
Релиз содержит только багфиксы? Инкрементируется patch-компонент, 2.9.10 Релиз содержит нововведения, но старый функционал остался прежним? 2.10.0 Релиз содержит нововведения, которые меняют способ использования старого функционала? 3.0.0
Отвечая на вопрос, который тут же появляется - "мне что, инкремнтировать major-версию каждый раз, когда я ломаю обратную совместимость?". Ответ на этот вопрос - да, major-версия должна выпускаться каждый раз, когда какие-то вещи ломаются; это не игра в поддавки и визуальную упорядоченность. Если вас заботит скорость выпуска major-версий - это значит, что вы ломаете слишком много вещей, и какие-то обновления стоит придерживать в ветке до того, как появится моральная готовность выпустить новый major-релиз; на адаптацию к этой модели уйдет некоторое время, но на деле это всего лишь цифры, между которыми нет никакой разницы, версия 2.х.х или 17.х.х - для конечного потребителя это не так важно как то, сможет ли он пользоваться новой версией так же, как старой.
Не пытайтесь воспринимать 2.9.9. как 299. Это не число и не поддается правилам инкрементирования чисел.

Запись int в массив byte[] (NET3.5)

Как и при помощи какого метода можно записать целочисленное int в byte[]
Ограничен 3.5, DataInputStream/DataOutputStream - не подходят.
Предполагаемый код:
// Записать этот инт int _sizeBlock = 10489; // В этот массив byte[] info = new byte[4];


Ответ

int _sizeBlock = 10489;
byte[] info = BitConverter.GetBytes(_sizeBlock);
документация по методу
Возможен случай, когда на компьютере используется обратный порядок для хранения байт. Необходимо проверять флаг BitConverter.IsLittleEndian, если он установлен в true "перевернуть" байты в массиве.
if (BitConverter.IsLittleEndian) Array.Reverse(info);

Как правильно перевести секунды в формат HH:mm:ss?

Получаю продолжительность видео с ВК в секундах. Никак не могу перевести их в формат HH:mm:ss
Вот мой метод
public String secToStr(int duration){ SimpleDateFormat df = new SimpleDateFormat("hh:mm:ss"); String time = df.format(new Date(duration)); return time; }
Любой duration переводится в 3 часа. Что я делаю не так? Как можно это сделать двумя-тремя строчками?


Ответ

Разобрался. Вот так надо
public String secToStr(int duration){ return String.format("%02d:%02d:%02d", duration / 3600, duration / 60 % 60, duration % 60); }