Страницы

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

среда, 18 декабря 2019 г.

Как удалить из коллекции все отрицательные числа?

#java #коллекции #java_stream


Можно это сделать используя java.util.stream?
Пытался сделать это обычным способом, но не получается, думаю из-за сдвига после
remove().

List list = new ArrayList();
    list.add(-1);
    list.add(-2);
    list.add(-3);
    list.add(4);
    list.add(1);

    for(int i = 0; i <= list.size(); i++) {
        if(list.get(i) < 0) 
            list.remove(i);
    }

    


Ответы

Ответ 1



By Эникейщик: Нельзя идти по массиву и проводить с ним манипуляции! Создайте новый массив и добавляйте туда элементы, удовлетворяющие условию. List list = new ArrayList(Arrays.asList(-1,-2,-3,5,4,2)); List list2 = new ArrayList<>(); for(int i = 0; i <= list.size(); i++) if(list.get(i) > 0) list2.add(list.get(i));

Ответ 2



В Java 8 появился специальный метод, для удаления элементов коллекции, которые соответствуют заданному предикату: list.removeIf(value -> value < 0); P.S и не требуется создавать новую коллекцию.

Ответ 3



Вот так можно создать новую коллекцию с только положительными числами с помощью стримов. list = list.stream() .filter(s -> s > 0) .collect(Collectors.toList());

Необходимость одноразовых функций в программе

#функции #любой_язык


Хочу спросить, какой смысл в использовании функции в программе, если она вызывается
один раз? Возможно, эстетический, для понятности кода?
Спасибо!
    


Ответы

Ответ 1



Разделение ответственности. Функция имеет некое предназначение и оно отделяется от того, что с ним не связано. Например, даже если строку надо привести в верхнему регистру всего один раз, то логично сделать отдельную функцию, которая именно это и делает, а не смешивать её с вводом и выводом этой строки. В момент, когда эта функция понадобится снова, её не придётся копипастить или выносить - она уже будет. Чистые функции позволяют запоминать результат вызова в случае, если аргументы не меняются. Да и в другой проект их перенести куда проще. Поэтому может иметь смысл отделять функцию-преобразование от побочных эффектов. Лямбда-функции передаются в другие функции как аргументы, например a.sort((x,y) => x-y). Сама лямбда-функция и так является функцией, но некоторые языки их не поддерживают и приходится писать самостоятельные функции. Упрощение потока кода. Когда из функции выносятся некие участки кода, и её становится проце читать. Например, var height = isFlexible ? calcFlexibleHeight() : calcHeight();, а каждая из вычисляющих функций по 100 строк - получится гораздо удобнее, чем огромный if-else с переменной перед ним. Но тут главное не перестараться - при разбивании на совсем маленькие участки код действительно можно читать как книгу, но вот отлаживать его - это ад. Изолировать область видимости. В некоторых языках скоупом для переменных является функция. Если нужно создать область видимости, то придётся создавать и функцию. Функция main, которая вызывается автоматически при запуске программы. Реализации членов интерфейса - тут уж никуда не деться, если по какой-то причине есть интерфейс и его нельзя менять, то придётся реализовывать.

Ответ 2



Для начала надо разобраться что такое функция. Давайте обратимся к источнику "знаний": Функция в программировании — фрагмент программного кода (подпрограмма), к которому можно обратиться из другого места программы. Теперь будет чисто отсебятина, ключевое в этом тексте(лично для меня) - что функция это подпрограмма, т.е. часть программы выполняющая осмысленное законченное действие. Если судить исходя из этого - есть смысл выделять в функции все участки кода которые сами по себе выполняют некое конечное действие. Допустим даже если нам нужно подсчитать сумму двух векторов в программе всего один раз - будет хорошим тоном выделить это в отдельную функцию. Далее выделение частей кода в осмысленные функции - улучшает читаемость кода, даже если функция вызывается один раз. Это не полный набор плюсов, но минусов(при правильной реализации) очень мало в современных реалиях. Дабы совсем о них не умолчать приведу два известных мне: Небольшой оверхед на перескок(call) Накладные расходы на сохранение\восстановление стека. p.s. Небольшое дополнение - многие современные ЯП умеют определять "оптимальность" выноса кода в функцию и в итоге в скомпилированном виде - вызов функции заменяется на вставку этого кода в место вызова. т.е. в исходниках у вас функция, а в бинарнике - функции как бы и нету.

Расположение блоков в Grid CSS

#html #css #css3 #html5 #css_grid


Ребят, помогите с помощью Grid CSS сделать структуру, как на картинке. Родитель должен
занимать все пространство экрана. Только познакомился с этим стилем и не могу найти
решение. 


    


Ответы

Ответ 1



Не знаю что тут сложного, но добавлю формальный ответ: .item1 { grid-area: header; } .item2 { grid-area: menu; } .item3 { grid-area: content; } .grid-container { display: grid; grid-template-areas: 'menu header header header header header' 'menu content content content content content' 'menu content content content content content'; grid-gap: 10px; background-color: #2196F3; padding: 10px; } .grid-container > div { background-color: rgba(255, 255, 255, 0.8); text-align: center; padding: 20px 0; font-size: 30px; }
Header
Menu
Content
Источник Update: Есть хороший ресурс, помимо вышеуказанного, где вы можете в игровой форме разобраться с сеткой, называется: Grid Garden

Ответ 2



.wrapper { display: grid; grid-template-columns: 20% 80%; } .wrapper div { border: 1px solid red; } #sidebar { grid-row-start: 1; grid-row-end: 3; } Example
content


Ответ 3



.container { display: grid; grid-template-columns: 100px 400px;; grid-template-rows: 100px 400px; } .container1 { border: 3px solid brown; grid-area: 1 / 1 / 3 / 2; } .container2 { border: 3px solid green; grid-area: 1 / 2 / 2 / 3; } .container3 { border: 3px solid blue; grid-area: 2 / 2 / 3 / 3; }
Вот мое решение

Для чего необходимо внедрение зависимости (dependency injection)?

#шаблоны_проектирования #net #c_sharp


Вот пример кода из всеми любимого тутора Nerddinner
public class DinnersController : Controller {

    IDinnerRepository dinnerRepository;

    //
    // Dependency Injection enabled constructors

    public DinnersController()
        : this(new DinnerRepository()) {
    }

    public DinnersController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }

   ...

Какая разница, если я буду создавать объект репозитория в методах контроллера? 
   public ActionResult Edit(int id) {

        DinnerReposotiry dinnerRepository = new DinnerRepository();
        Dinner dinner = dinnerRepository.GetDinner(id);

        if (!dinner.IsHostedBy(User.Identity.Name))
            return View("InvalidOwner");

        return View(dinner);
    }
    


Ответы

Ответ 1



Использование DependencyInjection даёт три преимущества. Возможность подменить некий сервис, не являющийся технологически нейтральным. Возможность автоматически тестировать различные модули программы независимо. В Вашем примере Dependency Injection позволяет написать автоматический тест, проверяющий, что DinnersController правильно вызывает методы DinnerRepository. Возможность повторно использовать код DinnersController с другими реализациями IDinnerRepository.

Ответ 2



Разница в том, что в классе-потребителе ты будешь работать с объектом на уровне абстракций и иметь возможность подставлять любую реализацию абстрактного интерфейса. Приведу пример: У тебя есть интерфейс, который предоставляет некий набор операций. Сегодня заказчик хочет, чтобы метод GetSomeInfo() реализации этого интерфейса обращался к локальной БД, а так же в будущем еще и к веб-сервисую На начальном этапе ты пишешь реализацию MyBDInterfaceImplementation, у которой GetSomeInfo() обращается к базе. Класс-потребитель при этом просто знает об интерфейсе, что он владеет методом GetSomeInfo и вызывает его. Потом ты реализуешь другой класс, который реализует этот интерфейс и метод GetSomeInfo() в данном случае обращается к веб-сервису. В итоге в классе потребителе тебе не нужно ничего менять, только в месте, где вызывается конструктор этого класса передать ему объект другого типа. Таким образом, на практике пользователь твоего приложения выбирает использовать локальную БД - ты в конструктор класса потребителя передаешь первую реализацию интерфейса, если пользователь выберет веб-сервис - аналогично подставляешь реализацию с доступом через веб-сервис. Следующий плюс - тестируемость. Во-первых, легко писать используя TDD, User Stories и тд. Во-вторых, легко тестировать с помощью моков, подставных реализаций и тд. Так же полезной будет статья Фаулера об IoC. Книги Роба Мартина об агил-девелопменте и чистом коде. Надеюсь, ответ на вопрос помог разобраться.

Книги по алгоритмам [дубликат]

#алгоритм #книги


        
             
                
                    
                        
                            This question already has answers here:
                            
                        
                    
                
                        
                            Книги и учебные ресурсы по фундаментальным знаниям и
навыкам разработчика
                                
                                    (2 ответа)
                                
                        
                                Закрыт 3 года назад.
            
                    
Ищу книгу по основам алгоритмизации. Главный требование - это простой и доступный
стиль изложения материала в книге и была предназначена для новичков в этом деле. Алгоритмы
- это моя самая слабая часть в программирование, поэтому я хочу поработать над ней.
Поэтому прошу посоветовать книгу. Заранее благодарен за помощь.    


Ответы

Ответ 1



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

Ответ 2



Дасгупты, Пападимитриу, Вазирани "Алгоритмы" бесплатно (в комментах можно и в бумажном виде заказать) Стивен С. Скиена "Теория алгоритмов" Лучше учебников (не толстенных) не видел.

Ответ 3



Трилогия Кнута (Книга 1 - Основные алгоритмы, Книга 2 - Сортировка и поиск, Книга 3 - Получисленные алгоритмы) - эти труды могут быть достаточно сложоусоваиваемыми...я понял суть Вашего вопроса, но это хорошие книги на самом деле. Т.Кормен - Алгоритмы построение и анализ.

Ответ 4



Вот тут богатый выбор: Алгоритмы, компьютерная алгебра

Ответ 5



Вирта можно почитать. Алгоритмы и структуры данных. у нас как раз перед Кнутом был.

Ответ 6



Ну и для полноты Роберта Седжвик Алгоритмы на C++. Фундаментальные алгоритмы и структуры данных. :)

Ответ 7



Также посоветую Emaxx http://e-maxx.ru/algo/ , очень много алгоритмов, с оценкой асимптотики, доказательствами и примерами на с++, а также указаны пример задач на использование этих алгоритмов.

C++ динамическое выделение памяти

#cpp


Здравствуйте, у меня вопрос почему память после оператора delete память так и остается
задействована или я что то не так понимаю:
#include 

using namespace std;

int main(){

    int *p=new int[10];

    for(int i=0;i<10;i++){

       p[i]=i;

     }
     delete [] p;//удаление массива

      cout<


Ответы

Ответ 1



Про то, как надо удалять массивы, Вам уже написали. Напишу про то, почему сохраняется доступ к старым данным. Даже если правильно удалять динамически выделенную память, то не всегда из кучи выгружаются подключенные страницы памяти, особенно если они в середине кучи. Просто они в помечаются как свободные и при повторном запросе на выделение памяти могут быть использованы, если хватает объема. Это ускоряет процесс динамического выделения памяти, которые является довольно ресурсоемким.

Ответ 2



Во-первых вы не правильно выполняете удаление массива - надо удалять так delete [] p; Во-вторых, после освобождения памяти, содержимое обычно не очищается, просто участок помечается как свободный. Поэтому там могут некоторое время сохранятся старые значения.

Ответ 3



То, что создается с помощью new[], должно удалятся с помощью delete[]. Иначе будут утечки. А то что значение выводится - это компилятор не досмотрел и не дал по пальцам, а вообще то должно было б сгенерироваться исключения доступа к памяти (хотя в релизных вариантах не объязательно). То есть, то что Вы обратились к памяти, которую освободили и там что то вывелось - это просто UB (неопределенное поведение). В приведенном выше примере ничего плохого скорее всего не будет, а вот в какой нибудь нагруженной системе может вывестись совсем другое значение (в лучшем случае).

Ответ 4



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

Скрытие кода *.exe-файла

#шифрование #обфускация #дизассемблирование #обратная_разработка


Как можно скрыть код exe-файла (написаного, например, на Delphi) от расшифровки под
дизассемблером и, впоследствии, от реверса.

Строки, например, можно просто XOR-ить или смещать каждый символ на k позиций по
таблице ASCII (первое лучше, ИМХО). А вот как скрыть имена функций или даже целые блоки
кода? Ведь многие разработчики (особенно вирусописатели) любят это делать, тем самым
скрывая свои «творения» от исследования посторонними лицами. Таким же образом скрывается
от антивирусов всем известный SpyEye. А как этого добиться мне?
    


Ответы

Ответ 1



(Некоторое время не занимался реверсингом, поэтому информация может быть outdated) Если говорить о серьезной обфускации, то имеет смысл рассматривать только языки, которые компилируются в машинный код (C++, например). Языки с промежуточным слоем байт-кода обычно легко поддаются реверсингу и, судя по всему, пока нет более-менее адекватных способов запротектить написанные на них приложения. Адекватные протекторы совершают некоторую последовательность действий для защиты готового приложения от реверсинга: Вставляют в готовый бинарник готовые антиотладочные фрагменты кода (например, дешифрующий его в рантайме), путают секции, совершают хитрые джампы, в общем, совершают атомарные изменения (не меняющие поведение программы!) над исполняемым кодом, которые затрудняют отладку человеку. Человек - это reverse engineer, который открывает ваше приложение в IDA, зрительно выцепляет знакомые паттерны из дизассемблерного листинга, трейсит приложение, подменяя содержимое стека и патча это самое приложение в его рантайме. И основная цель этих защитных действий протектора - заставить реверсера сказать "Тьфу, пошло оно в ж*пу, задолбало", поскольку последовательность действий протектора всегда можно совершить в обратную сторону, был бы опыт и знания. Более серьезная защита, иногда останавливающая даже крутых и опытных реверсеров - это виртуализация кода приложения для того, чтобы исполнять его на собственной виртуальной машине (обычно сочетается со стандартным антиотладочными приемами, описанными выше). При этом виртуальная машина внедряется в бинарник вместе с некоторым IL-кодом, который может выглядеть абсолютно произвольно. Параметры создаваемой машины также можно варьировать в некоторых пределах - при желании можно и виртуалку с троичной логикой написать. Бонус такого подхода в том, что для полноценного реверсинга такого приложения необходимо каким-либо образом воспроизвести эту самую виртуальную машину. В такой ситуации (если виртуалка оказывается достаточно хитрой), большая часть стандартных тулзов и приемов реверсера перестает работать "из коробки". Что, опять же, приближает этого самого потенциального реверсера к состоянию "Спасибо, с меня хватит". С точностью до деталей таким образом протектит Themida. В соответствии с написанным выше - если есть желание запротектить свою программу более-менее достойно, то напишите свою виртуалку и сгенерируйте для нее IL-код из имеющихся объектных файлов вашего приложения. Это действие поможет отсеять большую часть реверсеров, которым недавно рассказали и показали, что такое IDA и как применять patch. Quick test - для того, чтобы понять, сможете ли вы создать более-менее адекватную защиту с виртуализацией, попробуйте сломать CrackMe от ESET. Если поймете, причем здесь SSE и общую механику проверки, то можно браться за дело. Всегда есть набор готовых public и private пакеров, которыми можно воспользоваться. Themida, ASProtect, FSG. Понятно также, что всегда найдется набор людей, которые эти или иные протекторы в состоянии снять.

Точность при вычислении

#c


Решаю олимпиадные задачи различного рода, когда работал в Паскале никогда и не задумывался
над работой оператора"=" или ">=" в работе с вещественными числами, я думал, что с
точностью сравнений и проблем не может быть. Но вот я перешел на C++ и один учитель
мне сказал, что "==" или ">=" нельзя использовать при работе с вещественными числами
в Си, нужно писать fabs(a - b) > eps. И вот вопрос:

Правда ли это?
Как правильно подобрать eps?
И почему же могли некоторые задачи не проходить все тесты с такой фишкой, а когда
писал просто "==" они проходили.

Вот конкретный пример. Задача, которая прошла после того, как я изменил LessEqual
на "<=". Дано действительное число a и натуральное n. Вычислите корень n-й степени
из числа a. Программа должна вывести единственное число: ответ на задачу с точностью
не менее 6 знаков после запятой
#include 
#include 
#include 

using namespace std;
const double eps = 1e-8;
const double eps2 = 1e-12;

bool Equal(double a, double b)
{
    return fabs(a - b) < eps2;
}

bool lessEqual(double a, double b)
{
    return ((a < b) || Equal(a, b));
}

double a;
int n;

void solve()
{
    double l = 0,
           r = a + 1,
           mid = 0;
    while (r - l > eps)
    {
        mid = (l + r) / 2;
        if (lessEqual(pow(mid, n), a))
            l = mid;
        else
            r = mid;
    }
    printf("%.7lf", l);
}

int main()
{
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);

    scanf("%lf\n", &a);
    scanf("%d", &n);
    solve();

    return 0;
}
    


Ответы

Ответ 1



Действительно ничего хорошего из сравнения типа == при операциях с вещественными числами не выйдет. Можно попробовать простой код: double sum = 0; for ( int i = 0; i++; i < 1000000000 ) { sum += 0.000000001 } Гарантировать, что в итоге sum будет равным 1 в данном случаи невозможно. Может быть равен, а может и нет. Дело в машинной точности округления мат. операций. И ваш преподаватель все правильно говорит. Сравнение вида fabs ( 1.0 - sum ) < 0.0000000000000001; Даст верный результат всегда. ps Число 0.0000000000000001 взял просто так, но поверьте, такая ошибка вычислений очень мала, но все же точного результата ( sum == 1.0 ) вы не получите

Ответ 2



Проблема здесь не в "неточном" сравнении аппаратурой процессора, а в том, что некоторые десятичные дроби не могут быть точно преобразованы в двоичный формат чисел с плавающей точкой. Еще одна проблема заключается в потере младших разрядов мантиссы при вычислениях в циклах.

Ответ 3



В развитие ответа уважаемого @AVP. Если задача позволяет, преобразуйте свои числа к дробям, которые могут быть представлены двоичной дробью: не 0.1, а, например, 25/256 и т.д. Это обезопасит Ваши циклы от недохода или превышения заданной величины постоянной цикла. В С++ определена интересующая Вас константа epsilon в библиотеке float.h - DBL_EPSILON. Посмотрите ее значение именно для Вашего компилятора. Сравнение ">=" - всегда правомерно.

Ответ 4



Не совсем верно. eps зависит от того, насколько точно вы хотите посчитать те или иные показатели. Обычно точность указывается при постановке задачи. Например: Посчитать с точностью до седьмого знака после запятой, тогда eps = 0.0000001 Тут непонятно, нужно смотреть задачи. А вообще, точность достаточно условное понятие, как можно видеть из формулы fabs(a - b) > eps, и от задаче к задаче она будет меняться.

Ответ 5



На самом деле, в реальной жизни нельзя, например, сказать что две палки равны по длине, можно сказать что их длины различаются на очень небольшую величину, т.е. |длина1-длина2|

Как писать комментарии к параметрам метода?

#c_sharp #документация #комментарии


В каком виде следует писать комментарии к параметрам метода, чтобы при вызове метода
в его подсказке были эти комментарии?
    


Ответы

Ответ 1



Есть такая штука - xml-комментарии. Они отличаются от обычных тем, что предваряются тремя слэшами, а не двумя. Например: /// /// Описание метода /// /// Описание параметра /// Ogbcfybt возвращаемого значения public int SomeMethod(string arg)

Ответ 2



Ставите /// слеша перед именем члена, далее студия сгенерирует вам заглушку для комментариев. Заполнить ее можно как в примере. /// /// Некоторый метод. /// /// Количество /// public void Method(int count) { }

Как реализовать такой эффект параллакса?

#javascript #html #jquery #css


На сайте Apple (блок "Самый мощный iMac в истории") есть эффект параллакса. При прокрутке
до определенной точки картинка начинает прокручиваться медленнее текста, и в конце
медленная прокрутка сменяется стандартной. Как можно реализовать такой же эффект?

UPD:

Есть скрипт, который при прокрутке до определенной высоты замедляет прокрутку блока.
Сначала у нас блок с абсолютным позиционированием, при прокрутке определенного количества
пикселей блок получает фиксированное позиционирование и начинает прокручиваться медленнее
основного контента.

        // Наш элемент, который будет замедляться
var $element = $('.first'),
    /*
    * Последняя позиция скролла, нужна
    * для вычисления
    */
    lastScrollTop = 0,
    /*
    * Отступ сверху для нашего блока 
    * с фиксированным и абсолютным
    * позиционированием
    */
    defaultElementAbsoluteTop = 150,
    defaultElementFixedTop = 90,
    // Коэффициэнт замедления
    n = 4;

    // Отслеживаем скролл страницы
    $(window).scroll(function (event) {

    // Вычисляем текущее положение
    var scrollTop = $(window).scrollTop(),
        /*
        * Вычисляем положение нашего блока
        * от верхней части сайта/родителя.
        * Т.к. этот элемент до этого был абсолютным,
        * то у него отступ сверху всегда одинаков,
        * А когда подходит момент, когда нужно его фиксировать
        * отступ расчитывается от последнего, который был
        * 150 пикселей. Это неправильно. Я ввел проверку,
        * Если отступ стандартный абсолютный равен
        * текущему, то, при фиксировании блока
        * ставим ему оступ фиксированного блока
        * и отсюда начинаются правильные расчеты
        */
        elementTop = $element.position().top == defaultElementAbsoluteTop ? defaultElementFixedTop
: $element.position().top;

    if(scrollTop < 60) 
    {
        /*
        * Проскролили меньше, чем на 60 пикселей
        * То оставляем абсолютное позиционирование
        */
        $element.removeClass('fixed');
        // И ставим элементу абсолютный отступ сверху
        $element.css({
            top: defaultElementAbsoluteTop
        });
    }
    else
    {
        // Фиксируем элемент
        $element.addClass('fixed');
        // TODO: удалить!
        //return;

        /*
        * Если прошлое положение меньше,
        * чем текущее, значит двигаемся <вниз>
        */
        if (scrollTop > lastScrollTop){
            // Вычисляем разницу перемещения
            var diff = scrollTop - lastScrollTop;
            // Даем отступ сверху в n раз меньше, чем скролл
            $element.css({
                top: elementTop - diff/n + 'px'
            });
        // В противном случае, двигаемся <вверх>
        } else {
            // Вычисляем разницу перемещения
            var diff = lastScrollTop - scrollTop;
            /*
            * Вычисляем результирующее положение нашего элемента,
            * с учетом замедления n
            */
            resultElementTop = elementTop + diff/n;
            /*
            * Если конечный результат вышел больше,
            * чем отступ сверху по умолчанию,
            * то даем стандартный отступ.
            * Иначе даем результирующий отступ
            */
            resultElementTop = resultElementTop > defaultElementFixedTop ? defaultElementFixedTop
: resultElementTop;
            // Позиционируем элемент
            $element.css({
                top: resultElementTop + 'px'
            });
        }
    }
    // Запоминаем последнюю позицию скролла
    lastScrollTop = scrollTop;
});


Нужно, чтобы блок сначала был с position: absolute, при прокрутке до определенного
участка блок получает position:fixed и прокручиваетс медленнее. При прокрутке страницы
ещё ниже, блок опять становится абсолютно спизиционированным. При рокрутке обратно
вверх блок получает фиксированное позиционирование и прокручивается вниз с того момента,
на котором остановился при прокрутке вверх.
    


Ответы

Ответ 1



Поковырялся, вот что получилось. firstPosScroll = []; // позиция курсора, с которой объект видим windowH = $(window).height(); // высота окна getPosScroll(); // заполнение вышеуказанных позиций $(window).resize(function() { // при изменении размера окна пересчитываем позиции getPosScroll(); }) $(window).scroll(function() { //обработчик скролла posScroll = $(this).scrollTop(); // текущая позиция курсора posMiddle = windowH / 2; // середина окна $('.prlx').each(function(i, v) { // для каждого объекта offsetObj = $(this).offset().top; // положение объекта относительно верха документа posObj = offsetObj - posScroll; // текущая позиция объекта koef = 1 - ($(this).find('.logo').height() / $(this).find('.desc').height()); // коэффициент замедления обратно пропорционален разнице высот картинки и описания if (posObj < posMiddle && posObj + $(this).height() > posMiddle) { //условие видимости объекта $(this).find('.logo').css({ 'top': (posScroll - firstPosScroll[i] - posMiddle) * koef + 'px' }); // задаем высоту } }); }); function getPosScroll() { $('.prlx').each(function(i, v) { firstPosScroll[i] = $(this).offset().top - windowH < 0 ? 0 : $(this).offset().top - windowH; }); } section {position: relative;} section.left-logo>div.logo {left: 0;} section.left-logo>div.desc {float: right;width: 50%;} section.right-logo>div.logo {right: 0;} div.logo {position: absolute;width: 50%;} section.right-logo>div.desc {float: left;width: 50%;} header {height: 800px;background: #e6e6e6;} img {max-width: 100%;} div.p {margin: 20px 0;} div.clear {clear: both;width: 100%;}


Ответ 2



Мой вариант решения - пример здесь. Описание всего, что происходит, в принципе, есть в коде ниже. Отчасти использовал идею со страницы Apple, но обошелся без translate3D. Основной HTML:
Основной CSS: .content { position: relative; } .slow { position: absolute; top: 100px; } JS: var $window = $(window); var $parent = $('.content').eq(1); var $slow = $('.slow'); // сохраняем первоначальную позицию блока по отношению к родителю (100px) var initialTop = $slow.position().top; // эффект замедления // то, на сколько пикселей будет двигаться блок при position: fixed var translate = 1; // указываем расстояние в пикселях до/после родителя, чтобы знать // когда добавлять/убирать position: fixed // могут быть равны 0, тогда определяться будет по позиции родителя var parentBefore = 300, parentAfter = 100; // последнее значение $window.scrollTop(), для определения направления скролла var previousScrollTop = 0; // направление по умолчанию - вниз var direction = -1; // временные переменные var parentTop = null, parentBot = null; function onScroll() { // узнаем в каком направлении мы сейчас скроллим // "1" - вверх, "-1" - вниз direction = previousScrollTop > $window.scrollTop() ? 1 : -1; previousScrollTop = $window.scrollTop(); // вычисляем верхнюю и нижнюю границу того, когда нам нужно начинать эффект // верхняя граница: когда топ родителя + запас "before" достигает топа окна // нижняя граница: когда низ родителя + запас "after" появляется снизу var borderTop = $parent.offset().top - parentBefore - $window.scrollTop(); var borderBot = borderTop + parentAfter + $parent.height(); // если мы внутри границ if (borderBot > $window.height() && borderTop <= 0) { // достаем текущее положение элемента относительно окна var currentTop; // если скролим вверх, то при первом переключении на position: fixed, // восстанавливаем сохраненное значение (см. parentTop) if ($slow.css('position') === 'absolute') { currentTop = parentTop; } else { // иначе берем текущую фиксированную позицию currentTop = parseInt($slow.css('top'), 10); } // вычисляем новое значение со сдвигом в зависимости от направления var nextTop = currentTop + translate * direction; // проверка для того, чтобы не вылезать за пределы стартовой позиции if (nextTop < initialTop) { nextTop = initialTop; } // когда впервые попадаем в границы, добавляем запас "before" к позиции if (!parentTop) { nextTop += parentBefore; } $slow.css('position', 'fixed'); $slow.css('top', nextTop); $slow.css('bottom', 'auto'); // сохраняем позицию относительно окна сверху parentTop = $slow.position().top; // сохраняем позицию относительно окна снизу parentBot = $window.height() - $slow.position().top - $slow.height(); // если вышли за границу снизу, цепляем блок к низу родителя } else if (borderBot < $window.height()) { $slow.css('position', 'absolute'); $slow.css('top', 'auto'); // устанавливаем позицию блока относительно родителя из сохраненного // значения (см. parentBot), с вычетом запасов "before" и "after" $slow.css('bottom', parentBot - parentAfter + parentBefore + 'px'); // если вышли за границу сверху, восстанавливаем все состояния } else if (borderTop > 0) { $slow.css('position', 'absolute'); $slow.css('top', initialTop); $slow.css('bottom', 'auto'); parentTop = null; parentBot = null; } } $window.on('scroll', onScroll); Замеченные недостатки: нельзя замедлять перемещение фиксированного блока меньше чем на 1px (переменная translate) позиция блока при скролле всегда рандомная, т.к. перемещение выполняется при каждом событии scroll. Правка: JSBin в Firefox не видел функцию onScroll, которая была объявлена под $window.on('scroll', onScroll);. Также Firefox даже если у элемента стоит top:auto, возвращает числовое значение для вызова $el.css('top'), а не строку auto.

Ответ 3



Вот мой вариант: HTML:
CSS: .about .parallax { height: 400px; overflow: hidden; position: relative; } .about .parallax img { width: 100%; position: absolute; } JS: function parallax() { var $block = $('.parallax'); var $window = $(window); for (var i = 0; i<$block.length; i++) { var $item = $($block[i]), docViewTop = $window.scrollTop(), docViewBottom = docViewTop + $window.height(), elemTop = $item.offset().top, elemBottom = elemTop + $item.height(), img = $item.find('img'), heightParallax = img.height() - $block.height(); if ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)) { var show = docViewBottom - elemTop; var par = heightParallax / ($window.height() + $block.height()); var top = par * show * -1; if (top > 0) { img.css('top', '0px'); } else if (heightParallax < top * -1) { img.css('top', heightParallax + 'px'); } else { img.css('top', top + 'px'); } } else if (elemTop >= docViewBottom) { img.css('top', '0px'); } else if (elemTop <= elemTop) { img.css('top', heightParallax + 'px'); } } } $(window).scroll(function() { parallax(); }).resize(function() { parallax(); }); Результат: Piggy refer

Когда нужно начинать писать Unit тесты?

#тестирование #юнит_тесты #nunit


Дано: некая функция, которая пишется и отлаживается в LINQPad.
Отладочный вывод через Dump. Пока 4 вызова.

Вопрос: есть ли какие-нибудь эвристики, по которым можно определить, что уже нужно
начать писать юнит-тесты. Нужны какие-то критерии сложности, которые оправдывают применение
NUnit(Lite). Стабов и моков пока нет.
    


Ответы

Ответ 1



Unit tests Для начала, юнит-тесты - это тестирование в изоляции, когда класс тестируется отдельно от остального кода (то есть, от других классов). Для изоляции классов друг от друга используется IoC (Inversion of Control), и обычно это DI (Dependency Injection). Соответственно, чтобы это по настоящему работало, хорошо бы знать, что такое IoC и DI. Но, продолжая про юнит-тесты: следуя тестированию в изоляции, Вы не сможете написать тест, который тестирует один класс, если тот жестко зависит от другого. Вернее, конечно, сможете, но это будет не юнит-тест, а интеграционный (но, замечу, что есть некоторая путаница с определениями, что такое интеграционный тест). Если же Вы тестируете некую функцию на наборе реальных данных, то это - функциональное тестирование (но, опять же, есть некоторая путаница с определениями). И то, и другое, можно сделать при помощи того же NUnit, но не стоит путать их с юнит-тестами, они служат для разных целей! Для чего нужны юнит-тесты: для упрощения создания хорошей архитектуры. Которая, в свою очередь нужна для облегчения внесения изменений в код. Иными словами, для облегчения ведения гибкой разработки (agile), для облегчения поддержки и так далее. Для чего нужны функциональные тесты: для тестирования работы отдельных частей системы на реалистичных данных, чтобы избежать багов, связанных с вычислениями. Для чего нужны интеграционные тесты: для тестирования системы или ее подсистемы в сборе, чтобы убедиться, что она выполняет то, что от нее требуется ее пользователям. TDD TDD правильно было бы перевести на русский, дословно, как "разработка, приводимая в движение тестированием", это сделало бы понимание чуть проще. Делается оно примерно так: Вы осознаете, что Вам нужно написать класс. Вы пишете один юнит-тест (сразу нацеливаясь на IoC и DI) на метод класса. Вы пишете класс и тестируемый метод в объеме, достаточном, чтобы тест прошел. Повторяете пункты 2-3 до тех пор, пока класс не будет готов. Профит: класс, не связанный с другими классами - готов. Функциональный тест может писаться на этом этапе, если тестируемые методы не зависят от результата работы других классов. Интеграционные тесты можно писать, когда написана сама (под)система, которая уже может выполнять некую работу и обладает неким интерфейсом, к которому предполагается обращение "снаружи" этой системы, в том числе, и пользователем. Вот этот интерфейс и нужно тестировать, в том числе и на реалистичных данных. Когда стоит начинать писать тесты Если Вы пишете небольшой проект в течение 1-3 месяцев, а затем особое увеличение кода в нем не предполагается, то можно особо не заморачиваться с юнит-тестами. Проект достаточно мал, чтобы внесение изменений и правка багов не стали для него фатальны. Имеет смысл написать какие-то функциональные/интеграционные тесты на сложные алгоритмы. Но, тут важно грамотно оценить потенциал роста проекта. Если же предполагается достаточно длительная разработка, поддержка, возможно изменение требований и так далее, то тестирование необходимо, иначе Вы в итоге Вы получите кучу проблем на позднем этапе разработки проекта (обычно получается дикая лапша, в которой просто страшно что-то менять, так как сломаться после изменений может что угодно). В таком случае юнит-тесты стоит начинать писать сразу же. Единственное исключение - это прототипы (например, прототипы часто пишут в геймдеве, чтобы попробовать механику, посмотреть графику, показать инвесторам и т.п.). Важно помнить, что код прототипа не должен уйти в продакшн как есть, без переписывания по всем правилам! В Вашем случае, Вы можете написать функциональные тесты, и, возможно, интеграционные, если есть, с чем. Если, как Вы пишете в комментариях, функция будет встраиваться в большой проект, имеет смысл следовать правилам проекта.

Ответ 2



Всё просто: подумайте насколько крупным будет ваш проект, и как часто будет требоваться менять что-то в нем. Одноразовая утилита, написанная на коленке за 5 минут? Можете спокойно забыть про юнит-тесты! Это пустая трата времени. Средний или относительно крупный проект, который будет активно изменятся в будущем, и/или который кто-то кроме вас будет поддерживать? Начинайте писать юнит-тесты до ещё до начала работы над основным кодом проекта! Они очень упростят тестирование в момент разработки, да изменение кода после его перехода на поддержку.

Как применить метод clone() класса Object?

#java #объекты #клонирование


Код, написанный мной для тренировки: 

class Korobka {

    public double width, depth, height; //Объявление переменных
    public static int id = 4;

    Korobka(double w, double d, double h) {
        width = w;
        depth = d;
        height = h;
    }

    double volume() {
        return width * depth * height;
    }

    void measurement() {
        System.out.println("Длина коробки " + width);
        System.out.println("Ширина коробки " + depth);
        System.out.println("Высота коробки " + height);
        System.out.println("Объем коробки " + volume());
    }

    public static void main(String[] args) {
        Korobka k1 = new Korobka(4.5, 3.6, 3.7);
        Korobka k2 = new Korobka(4, 5, 6);
        k1.measurement();
        k2.measurement();
        int ID = Korobka.id;
        System.out.println(ID);
    }
}


Вздумалось мне метод clone() из класса Object применить.

Вопросы: 


Могу ли я применить этот метод, к примеру, к коробке k1 (для клонирования)?
Если да, то как это сделать?

    


Ответы

Ответ 1



В дополнение к предыдущим ответам хочу отметить, что лучше реализовать clone() вот так: class Korobka implements Cloneable { @Override public Korobka clone() { try { return (Korobka)super.clone(); } catch( CloneNotSupportedException ex ) { throw new InternalError(); } } //всё остальное } Так как вы интерфейс Cloneable указали, CloneNotSupportedException никогда случиться не должен, и пользователи вашего класса не должны мучаться с ним, оборачивая вызовы в try-catch. Кроме того вы можете быть уверены, что возвращаемый объект имеет тип Korobka и привести тип сами. Тогда пользователи смогут просто писать: Korobka copy = k1.clone(); Вообще у клонирования много проблем и оно не всегда хорошо (хотя бывают случаи, когда очень удобно). Альтернативой клонированию служит конструктор копирования: class Korobka { Korobka(double w, double d, double h) { width = w; depth = d; height = h; } Korobka(Korobka other) { this(other.width, other.depth, other.height); } } Пользоваться тогда немного по-другому: Korobka copy = new Korobka(k1);

Ответ 2



Да сможете. В java объекты передаются по ссылкам. Т.е. следующий код Object o1 = new Object(); Object o2 = o1; создаёт один объект, на который указывают две ссылки. Очень часто это бывает не удобно - изменяем объект о1 изменяется объект о2. А, к примеру, нужно было в объект о2 просто скопировать значения из о1, но никак не связывать их. Для этих целей был введён интерфейс Cloneable. В своём клаccе вам нужно реализовать его: class Korobka implements Cloneable { @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } //всё остальное }

Ответ 3



Для начала нужно, чтобы ваш класс Korobka имплементил маркерный интерфейс Cloneable. Далее, вам надо переопределить метод clone() и сделать его публичным. Тогда вы сможете где угодно в своем коде клонировать коробки. P.S. Прежде чем переопределять метод, почитайте про глубокое копирование объектов в Java. Хотя оно тут не пригодится, но всё равно почитайте.

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

#c_sharp #net #visual_basic


Для тестирования функционала своего приложения решил написать простенькую тестовую
программу с которой будет работать моё приложение. 

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

Вопрос: Как это сделать? Просто вызов throw new Exception() приводит к завершению
приложения.

Возможно мой вопрос не совсем понятен, поясню: я запускаю некоторую программу посредством
Process.Start(); И перенаправляю на себя StandardError stream. Как выглядит ситуация
когда запущенная программа выкидывает эксепшн и закрывается мне ясно и я его обрабатываю.
А вот как смоделировать ситуацию когда приложение выкидывает эксепшн и продолжает работу
мне неизвестно, собсна в этом и вопрос.

Пример эксепшена: http://blogsisadmina.ru/wp-content/uploads/2013/10/1.png 
В консольном приложении повторение финта с индексом всё равно приводит к завершению
работы приложения.
    


Ответы

Ответ 1



Все исключения должны быть отловлены. Это означает, что где-то в стеке вызовов должен быть try-catch, который проглотит исключение и, например, залогирует его. Хорошим тоном является отлавливание только исключений, которые вы предполагаете, а не просто базового типа исключения, потому что иначе вы можете прозевать проблемную ситуацию и получить повреждение данных где-то в другом месте, в результате поиск проблемы значительно усложнится. try { DoSomething(); } catch (FooException e) { Log.LogException(e); } // ... DoSomething() { throw new FooException(); } Если вы хотите запрятать от клиентов падучесть приложения и считаете, что важнее отсутствие падений, чем стабильная работа и отсутствие повреждений данных, то можете отлавливать разнообразные события unhandled exception (они есть у домена, задач, диспетчера) и отмечать исключения как обработанные, если это возможно. В этом случае приложение продолжит работать, но за состояние данных никто не будет отвечать. Dispatcher.CurrentDispatcher.UnhandledException += CurrentDispatcher_UnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; Если исключения не будет нигде отловлены, то приложение упадёт, и информация об ошибке попадёт с системный журнал. Это не самый удобный способ, но им тоже можно пользоваться.

Ответ 2



Используйте try {..} catch(){} В блоке try вбрасываете исключение, с catch его ловите. int a = 5; try { if (a == 5) { throw new Exception("a > 5!"); } } catch(Exception e) { Console.WriteLine("Возникла ошибка!"); } Обратите внимание, что тип ошибки вбрасываемой ошибки должен совпадать с типом перехватываемой ошибки. Подробнее про try/catch: MSDN

Ответ 3



В общем я видимо только всех запутал... Мне необходимо было сгенерить подобный эксепшн: http://blogsisadmina.ru/wp-content/uploads/2013/10/1.png Проблема заключалась в том, что в консольном приложении генерация любого не перехваченного эксепшена приводила к завершению работы. И связано это судя по всему с тем, в какой поток консоль пишет исключения. Решение проблемы: использовать не консольное а winforms/wpf приложение. В этом случае любой эксепшн (ну или почти любой, все не проверял) выдаст требуемое окно с вариантом "продолжить". PS:Ну а поскольку мой вопрос был весьма сумбурным и лейб мотивом всё же была обработка и перехват эксепшенов То в качестве верного ответа я, пожалуй, укажу самый популярный на текущий момент ответ. Для большинства приходящих судя из гугла это будет то, что нужно, а тем кто будет искать ответ на тот же вопрос что и я не составит труда прочесть все комментарии

Хранение значений List<List<string>> в файле

#c_sharp


Перед запуском приложения необходимо проинициализировать массив List>
значениями из внешнего источника, как наиболее "правильно" это сделать? Использовать
xml файл и сериализацию/десериализацию, текстовый файл или есть более красивые "традиционные"
решения хранения настроек?
    


Ответы

Ответ 1



Правильный, рекомендованный Microsoft путь — хранение данных в Settings. Единственная тонкость — в Settings непросто вставить нескалярные данные. Действуем следующим образом: Заходим в свойства проекта, вкладка Settings. Создаём Settings по умолчанию, кладём в них свойство ListOfListsOfStrings. Как тип мы не можем выбрать List>, поэтому временно выбираем просто string. Закрываем проект (важно!), заходим в каталог проекта, открываем файл Properties\Settings.settings текстовым редактором. Находим строку наподобие вбиваем правильный тип Поскольку мы редактируем XML, нам нужно кодировать < и > как < и >. Закрываем редактор, снова открываем проект. Находим в проекте файл Settings.settings в каталоге Properties, выбираем из контекстного меню Run custom tool, чтобы перегенерировать Settings.Designer.cs. Проект должен компилироваться. Добавляем код, который будет работать с Settings: static void Main(string[] args) { var settings = ListListSettings.Properties.Settings.Default; // при первом пробеге тут ничего нет, создаём if (settings.ListOfListsOfStrings == null) { settings.ListOfListsOfStrings = new List>() { new List() { "1", "2" }, new List() { "3", "4", "5" } }; settings.Save(); } } Всё! Обновление: вместо логики установки первоначального значения в Main можно прописать это самое начальное значение и в Settings.settings. Для этого нужно в качестве начального значения во вкладке Settings указать вот такую строку: 1 2 3 4 5 Её нужно именно скопировать в поле ввода Value, а не пытаться записать вручную в файл Settings.settings, потому что в файле значения < и > нужно менять на < и >. Должно получиться что-то такое: Откуда взять такую хитрую строку? Не придумывать же её самостоятельно? На самом деле, её можно найти, добавив такой код: var sample = new List>() // это тот список, который мы раньше { // записывали в settings.ListOfListsOfStrings new List() { "1", "2" }, new List() { "3", "4", "5" } }; var xs = new XmlSerializer(sample.GetType()); using (var sw = new StringWriter()) { xs.Serialize(sw, sample); var serialized = sw.ToString(); // (*) } В точке, обозначенной звёздочкой, посмотрите значение переменной serialized через отладчик — там будет именно то, что нужно: С учётом изменений, код программы упрощается до такого: static void Main(string[] args) { var settings = ListListSettings.Properties.Settings.Default; var listOfList = settings.ListOfListsOfStrings; } @Pavel Mayorov, спасибо за подсказку в комментариях.

Ответ 2



Очень удобный вариант хранения почти любых настроек предлагается проектом FSharp.Configuration. Есть несколько основных плюсов использования этого подхода, относительно способа, предложенного @VladD: Настройки будут строготипизированными - типы настроек будут проверяться при компиляции. Имеется в виду, что тип с настройками будет "создан" при компиляции по структуре дефолтного конфига. То есть числа - будут int'ами, 00:50:00 - превратится в TimeSpan и т.п. Можно использовать формат Yaml - который является понятным, чистым, поддерживает коллекции "из коробки" Не надо загружать и выгружать проект Если не "кэшировать" значение мембера в локальной переменной - то при обращении к Settings.SomeList - мы будем всегда иметь актуальное значение (статический экземпляр будет следить за файлом и перечитывать его содержимое). Пример использования из C# есть на страничке провайдера.

Размер MySQL базы

#php #mysql #sql


Если к примеру есть 200 стран и 5000 городов, и чтобы в таблице вида:

id | country | town | message


не использовать текст страны и города (повторяются), а вместо них использовать числа
(id) стран и городов из другой таблицы, к примеру:

id | country //table country

id | town //table town


Уменьшит ли это объем таблицы, если предположительно будет 500 миллионов записей,
правильно ли это и есть ли альтернативы?
    


Ответы

Ответ 1



Я бы сказал, что так просто необходимо делать. И дело даже не в объеме базы, хотя он так же имеет значение. Представим, что вы ошиблись в названии города. В случае если это название повторяется в базе более 1 раза вам будет необходимо поменять его во всех записях, в которых оно встречается, поэтому в реляционные базах данных всегда стараются придерживаться такого принципа, что все данные дложны хранится в единственном экземпляре, а во всех остальных местах просто идет ссылка по ID на требуемый объект. Посмотрите в гугле по запросу "Нормальная форма", там будет ссылка на вики, но на вики сухая теория, сложная для понимания, рекомендую походить по другим ссылкам, даваемых гуглом. Что касается Вашего случая, я примерно вижу структуру базы такой (я не знаю что такое message, но предположим оно действительно зависит и от страны и от города) Пишу все в нотации оракла, типы данных вибирайте согласно той БД с которой работаете Таблица стран: create table Countrys ( c_id number not null primaty key, -- ID страны name varchar(200) -- название страны ... -- возможно еще какие то данные о стране ); Таблица городов: create table Towns ( t_id number not null primaty key, -- ID города c_id number not null -- ID страны в которой расположен город, надо же знать -- это Москва - столица РФ или одноименная деревня -- в США name varchar(200) -- Название города -- Возможно еще какие то данные о городе ); Ну и ваша загадочная messages: create table Messages( msg_id number not null primary key, t_id number not null, -- Ссылка только на город, если будет нужно узнать страну - мы ее найдем по городу message varchar(200) ); Ну и напоследок немного SQL. С вставкой в общем то все просто, insert всегда идет только в одну таблицу, отдельно заполняем справочник стран, потом городов и уже ваши messages insert into Countrys(c_id, name) values(1, 'Россия'); insert into Towns(t_id, c_id, name) select 100, c_id, 'Москва' from Countrys as C where C.name='Россия'; -- Но работа по имени очень не приветствуется, когда вы будете так вставлять -- записи в messages как вы по имени зададите Москва, если в мире не 1 десяток -- городов с таким названием Опять же от базы зависит откуда берутся id. в MySQL вы можете просто при объявлении колонки сказать, что бы id автоматом назначались. Это сами поищите, я наизусть не помню. А в оракле совсем другие механизмы. Ну и выборка одного сообщения так, что бы получить по нему и город и страну select C.name as country_name, T.name as town_name, M.message from Messages as M, Towns as T, Countys as C where M.msg_id=1 and T.t_id=M.t_id and C.c_id=T.t_id Правда обычно используют нотацию запроса с оператором JOIN, но он громоздкий, мне не нравится. И еще почитайте о foreign key, это ссылки, показывающие базе данных связь поля id страны в таблице городов, с первичным ключем id в таблице стран. Их необходимо создавать. Сначала кажется, что они усложняют вашу жизнь, не давая вставить запись в таблицу городов с не существующим ID страны. Но именно этим они спасают вас от ошибок в коде, ведущим зачастую к тяжелым последствиям. Представьте, вы вставляете 10к записей messages с городом Нью-Васюки, а потом случайно удаляете город из справочника. У вас остаются записи message, но вы не знаете к какому городу они относятся и что с ними дальше делать (не говоря уже о том, что приведенный мной выше select просто не покажет эти строки). Так вот foreign key не позволит вам удалить город на который есть хоть одна ссылка и если вы действительно решили его удалить, то не забудете о тех messages которые на него ссылаются и примете решение, например поменять у них город на Олд-Васюки

Ответ 2



До момента "предположительно будет 500 миллионов записей" я бы ответил, что разводить данные на несколько таблиц необходимо, но вот после этого уточнения все не так очевидно. Вплоть до того, что уже стоит подумать о характере хранения данных и, возможно, отказаться от MySQL. Про нормализацию уже написали в других ответах, поэтому напишу кратко. Смысл ее в том, что вы храните страны, города и сообщения отдельно друг от друга. Это разные сущности и, по-хорошему, не нужно много раз писать в БД одно и то же (впрочем, есть исключения из правила и о них ниже). О организации данных подробно написано в ответе Mike. НО! это верно, если объем данных в "обозримых" пределах. Когда мы говорим о очень большом числе данных, тут надо учитывать характер работы с данными: эти данные больше пишутся или больше читаются? Если читаются, то равномерно или есть такие данные, которые нужны больше остальных (например, записи за последний месяц дергаются из БД чаще остальных)? При больших объемах данных имеет смысл подумать о партициях. А если данные очень часто дергаются пакетом (страна+город+сообщение), то допускаю, что хранение их в одной таблице будет более оптимальным решением, чем постоянное объединение трех таблиц особенно при таких объемах. Это - денормализация базы данных. Еще вариант: хранить данные, которые нужны чаще, отдельно от данных, к которым обращаются редко. Как вариант можно подумать о хранении данных из небольших таблиц на стороне клиента (например, в локальном хранилище браузера) и объединять данные уже при отрисовке страниц. Вариантов решений море. Не ищите единственно верное, ищите оптимальное для вашей конкретной ситуации.

Ответ 3



Да, уменьшит. Так и принято делать. Это называется нормализация

Telegram API - Отправка Emoji

#telegram_bot


как отправлять emoji смайлики через API Telegram?

В официальной документации ни слово про смайликов. Где-то пишут, что нужно отправлять
UTF-8 код смайлика....но все без толку

U+1F601
U1F601
#1F601;
F601;
\xF0\x9F\x98\x81



    


Ответы

Ответ 1



Посмотрите на Emoji Unicode Tables. Нужный вам код смайлика находится в колонке Bytes (UTF-8). Перед отправкой на сервер необходимо выполнять URL Encode. Например, \xF0\x9F\x98\x81 должен выглядеть так: %F0%9F%98%81.

Ответ 2



Я просто копировал emoji из таблицы выше обычным выделением мышкой (как выделяется текст) из колонки "Native" получается вот так: 😜

Ответ 3



На bash я использую этот ресурс для получения кода Строка "C/C++/Java source code" отображает необходимую кодировку. Запрос приобретает вид /usr/local/bin/curl -s --header 'Content-Type: application/json' --request 'POST' --data "{\"chat_id\":\"-432111111\",\"text\":\"\uD83D\uDC4C - Here is OK emoji\"}" "https://api.telegram.org/bot/sendMessage" где \uD83D\uDE31 и есть кодированный символ 👌

Ответ 4



Пишу бота на C#, работает в таком виде "\U0001F69A" для кода U+1F69A из таблицы.

Ответ 5



Для РНР там где смайл: hex2bin('f09f9880')
f09f9880 - код смайла без \х отсюда (колонка Bytes (UTF-8))

Ответ 6



Используйте средства для представления Unicode текста в вашей среде. Она сама выполнит преобразование из текста в октеты согласно utf-8 кодировке, а затем произведёт percent-encoding. Например, чтобы отправить флаг 🇷🇺, который состоит из Unicode символов U+1f1f7, U+1f1fa в restclient в Emacs: POST https://api.telegram.org/bot:token/sendMessage Content-type: application/x-www-form-urlencoded chat_id=:chat-id&text=ура 🇷🇺! Это выполняет http POST запрос по указанному url (bot идентифицируемый по :token отправляет сообщение ура 🇷🇺! в :chat-id чат). На Питоне это может выглядеть как: import requests requests.post(f'https://api.telegram.org/bot{token}/sendMessage', dict(chat_id=chat_id, text='ура 🇷🇺!')) Видно, что нет необходимости руками кодировать строку в ascii-представление: '\u0443\u0440\u0430 \U0001f1f7\U0001f1fa!' Питон автоматически кодирует сообщение. На сервер уходит (зашифрованное с помощью TLS), что-то вроде: POST /bot/sendMessage HTTP/1.1 Host: api.telegram.org User-Agent: python-requests/2.18.4 Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive Content-Length: 69 Content-Type: application/x-www-form-urlencoded chat_id=&text=%D1%83%D1%80%D0%B0+%F0%9F%87%B7%F0%9F%87%BA%21

Класс для перечисления с заданным типом C++

#cpp #qt #boost


Если в С++ сделать 

enum operation = {plus, minus, mult, div};


То перечисляемые константы буду иметь тип operation.

А если мне нужно, чтобы переменная operation была типа char, и могла принимать только
значения {'+', '-', '*', '/'} ?

Есть ли в std/Qt/boost/другой библиотеке какой-либо контейнер, который позволяет
делать что-то в духе:

Enumeration operation = {'+', '-', '*', '/'};


Или необходимо писать велосипед самому? Может, что-то есть на эту тему из области
шаблонов проектирования?

Upd:
Или, еще лучше, если перечисляемые значения могут быть разного типа. К примеру, при
разборе строки с арифметическим выражением на токены, токен может быть типов Operator,
Operand или Bracket. Как-то так:

Enumeration Token = {op, num, br};

    


Ответы

Ответ 1



Нет, ни в C++, ни в boost&Qt такого контейнера нет. Нет его по одной простой причине — в C++ нет одного общего типа как, скажем в C#&Java. Поэтому, просто невозможно создать контейнер, который будет принимать разнородные данные. Можно, конечно, создать std::vector(QList и вариации) но это, мягко говоря, не лучшее решение, т.к. всё равно придётся «помнить», что там за данные, иначе извлечь их не получится. Поэтому, такие задачи решаются введением одного общего предка, а все вариации являются его наследниками. Создаётся контейнер указателей на этого предка и в него помещаются нужные потомки. К примеру, у Вас может быть std::vector> vec; и в него Вы будете помещать Ваши конкретные объекты: vec.push_back(std::make_shared()); Но лучше это всё вынести в ещё одну абстракцию, которая будет представлять собой контейнер, а не использовать «голый» вектор. Вообще, это довольно обширная тема, которую в рамках ответа не так просто и раскрыть. Но если просто взять Ваш пример из вопроса, то его можно легко написать так: std::tuple Token = std::make_tuple(op, num, br); Хотя, я полагаю, Вам всё же нужен будет более широкий функционал и динамизм, который не достижим с помощью std::tuple. Если моё предположение верно, то для Вас подходит первая часть ответа.

Ответ 2



Вашу проблему касательно char можно решить достаточно просто: хранить коды символов в самом enum'e (ведь базовым типом перечисления может быть любой целочисленным тип, т.е. int, long, char и некоторые другие), а затем при обращении к элементам перечисления делать явное приведение к char: enum CharEnum: char { plus = '+', minus = '-', mult = '*', div = '/' }; int main() { std::cout << static_cast(CharEnum::plus); } Стоит заметить, что начиная с C++11 появился enum class (можно писать и enum struct, что то же самое), который обладает рядом преимуществ перед обычным enum: не экспортирует свои значения в окружающую область видимости, что могло бы приводить к конфликтам имен отсутствует неявное преобразование значений перечислимого типа к целочисленным типам как у обычного enum, что могло бы приводить к ошибкам Таким образом, в предыдущем примере достаточно поменять enum на enum class, а весь остальный синтаксис останется неизменным.

Таблица ASCII и её соответствие в c++

#cpp #ascii


Почему в таблице ASCII российская буква 'a' равна 160, а когда я пишу: 

int a = 'а';

cout << a << endl;


мне выводит -32?
    


Ответы

Ответ 1



Результат выполнения Вашего кода зависит от нескольких факторов. В частности от кодировки исходника, используемого компилятора и правил кодирования символьных и строковых литералов. Например, возможен вариант вывода числа 53424 и предупреждения: multi-character character constant [-Wmultichar] при использовании UTF-8 кодировки исходника и компилятора gcc. Т.о. 'а' это вовсе и не символ, а целое число (более подробно о мультисимвольных литералах можно почитать тут), в чем можно убедиться проверкой sizeof, которая вернет такое же значение, как и для int, а не для char (по определению 1). При использовании clang вообще получим ошибку компиляции: character too large for enclosing character literal type Чтобы избавиться от такой ошибки придется изменить тип символьного литерала (например на wchar_t, задав префикс L). В этом случае на выводе получим уже другое число: 1072, что соответствует UTF-16 коду русской буквы а. Чтобы получить такой же результат как у Вас, но с помощью онлайн-компилятора gcc можно использовать ключ -fexec-charset с кодовой страницей 1251. При этом, хочу заметить, что для буквы а код 160 (0xA0) соответствует кодировке cp866, а не cp1251, в которой он равен 224 (0xE0). Поэтому -32 в 160 превратиться не сможет путем обычного преобразования знакового числа в беззнаковое. Если уж очень хочется получить на выводе именно 160 помимо преобразования в беззнаковый тип надо ещё использовать кодовую страницу cp866. Т.е. собирать следующий код с ключом -fexec-charset=cp866: #include int main() { int a = static_cast('а'); std::cout << a << std::endl; }

Ответ 2



Потому что число больше 127 не влезает в знаковый char, у которого диапазон от -128 до 127. Зато влезает в беззнаковый, но, судя по всему, на вашей системе char является знаковым, поэтому происходит конвертация из знакового char в знаковый int. Т.к. любое число char всегда влазит в int, то получается, что в int попадает отрицательное число из char Чтобы получить положительное число, просто используйте любой unsigned тип в качестве приёмника значения, а исходный char преобразуйте к unsigned char: unsigned int a = static_cast('а');

Зачем нужен std::binary_search, если есть std::find?

#cpp


Зачем нужен std::binary_search, если есть std::find?
    


Ответы

Ответ 1



Бинарный поиск работает только на: контейнерах с произвольным доступом (например, массив) которые отсортированы Это довольно жесткие требования. Если они не выполняются, остается только линейный поиск. Скорость работы бинарного поиска - логарифмическая, линейного - сюрприз - линейная. Это означает, например, что среди четырех миллиардов отсортированных элементов (2^32), искомый гарантированно отыщется всего за 32 шага сравнения. Или же будет показано, что такого элемента нет. Для достижения такого же результата, линейный поиск будет выполнять все 4 миллиарда сравнений.

Ответ 2



std::binary_search некорректо сравнивать с std::find, последний скорее нужно сравнивать с std::lower_bound. Вкратце - std::lower_bound более эффективный, но имеет ограничение на последовательность, к которой может применяться. std::find же более общий, но менее эффективный.

Ответ 3



std::binary_search работает за сложность О(log2n), a std::find за О(n). std::binary_search применяется только к отсортированным по неубыванию контейнерам, кроме ассоциативных (другими словами контейнеры, которые поддерживают итераторы произвольного доступа). И она возвращает true, если элемент найден false, если нет.

Доступ за пределами размера массива

#cpp


Изучаю основные возможности С++ и вот такой код :

int mas[12];

mas[15]=15;
cout<<"15 element = "<


Ответы

Ответ 1



C++ — небезопасный язык. Правила языка говорят, что нельзя выходить за границы выделенной памяти. Ответственность за выполнение правил возлагается на вас, программиста. C++, в отличие от безопасных языков, не проверяет, следуете ли вы правилам, поэтому вы не получите ошибку непосредственно в этой точке. Но раз вы нарушили правила, может случиться любая неприятность. Стандарт подчёркивает, что при нарушении вами правил все гарантии языка снимаются. При чтении за границами массива, если вам повезёт, и память по смещению в 15 размеров элемента от начала массива доступна, и не содержит ничего плохого (на интеловской архитектуре «плохого» не бывает, но на других вполне) и если оптимизатор не очень умный, вы просто прочитаете какое-то непонятное значение. В случае, если вам повезёт меньше, программа просто упадёт. А в совсем плохом случае программа начнёт вести себя странно, причём в каком-то далёком, не связанном с этой точкой месте. При записи всё ещё хуже, по этому адресу может случайно оказаться какая-нибудь важная структура данных (например, это может быть адрес возврата из текущей функции), и вы перезапишете его каким-то непонятным значением по принципу «на кого бог пошлёт». Просто не делайте так, C++ доверяет вам.

Возможно ли инвертировать детектинг файлов в GIT?

#git #gitignore


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


Ответы

Ответ 1



В .gitignore можно инвертировать правила с помощью !: * !*.html Теперь git будет игнорировать все файлы, кроме тех, что попадают под паттерн *.html. Документация .gitignore

Ответ 2



Можно просто не пользоваться командами наподобие git add . и добавлять файлы только по-одному. Еще можно написать в .gitignore * (т.е. все файлы), а добавлять их по-одному через git add -f Не забывайте, что файл, который уже есть в репозитории, будет отслеживаться независимо от того что написано в .gitignore

Сохранение данных банковской/кредитной карты, как в приложении AliExpress /Yota /сбербанк_онлайн

#android #алгоритм


Суть такая: в приложении AliExpress есть возможность добавить данные банковской карточки
и дальше с него автоматически производить оплату.

Каким образом реализуется сам алгоритм?

Каким образом мы можем сохранить данные карты в приложении, или это не в приложении
сохраняется, а отправляется на сервер? 

Если отправляется на сервер, то наверное, с шифрованием? То есть сам алгоритм работы
при вот таком действии, с кодом сам уже попробую реализовать. 

Приложении AliExpress взял, как пример, так как с этим в нём и сталкивался
    


Ответы

Ответ 1



Хранить данные банковских карт в приложении Вы не имеете права по закону. Хранить эти данные на сервере Вы можете если имеете сертификат PCI DSS (для начала ссылка в википедии), получить который очень не просто и стоит это не малых денег. Единственный, простой, вариант - это использовать платежный системы к примеру Яндекс.Касса и тому подобные (ссылка на рейтинг). Большинство этих систем поддерживает рекуррентные платежи, т.е. данные карты хранит сама система и дальнейшие платежи (к примеру по подписке), делает автоматически по вашему запросу, без дополнительных действий со стороны пользователя.

Ответ 2



Не знаю кейса с отправкой инфы о карте на сервер - это как-то совсем не секьюрно и получается какой-то сбор карт. Все строго шифровать! Тут либо карту шифровать по пину/паролю - очень хорошая статья по этой теме. Либо использовать SQLCipher - читать тут. И будьте предельно внимательны и ответственны при разработке хранения этих важных данных.

Ответ 3



Хранить такие данные на телефоне небезопасно. Если все таки есть желание хранить, то можно использовать 3D шифрование(TripleDES) Вот пример: public class TripleDESHelper { private Context mContext; public TripleDESHelper(Context context) { mContext = context; } public String encrypt(String message) throws Exception { final MessageDigest md = MessageDigest.getInstance("md5"); final byte[] digestOfPassword = md.digest("H3423G583424232CR9" .getBytes("utf-8")); final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); for (int j = 0, k = 16; j < 8; ) { keyBytes[k++] = keyBytes[j++]; } final SecretKey key = new SecretKeySpec(keyBytes, getString(mContext.getContentResolver(), Secure.ANDROID_ID)); final IvParameterSpec iv = new IvParameterSpec(new byte[8]); final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, key, iv); final byte[] plainTextBytes = message.getBytes("utf-8"); final byte[] cipherText = cipher.doFinal(plainTextBytes); return Base64.encodeToString(cipherText, Base64.NO_WRAP); } public String decrypt(String message) throws Exception { final MessageDigest md = MessageDigest.getInstance("md5"); final byte[] digestOfPassword = md.digest("H3423G583424232CR9" .getBytes("utf-8")); final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24); for (int j = 0, k = 16; j < 8; ) { keyBytes[k++] = keyBytes[j++]; } final SecretKey key = new SecretKeySpec(keyBytes, getString(mContext.getContentResolver(), Secure.ANDROID_ID)); final IvParameterSpec iv = new IvParameterSpec(new byte[8]); final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); decipher.init(Cipher.DECRYPT_MODE, key, iv); final byte[] encData = Base64.decode(message, Base64.NO_WRAP); final byte[] plainText = decipher.doFinal(encData); Log.d(getClass().getSimpleName(),new String(plainText, "UTF-8")); return new String(plainText, "UTF-8"); } } Лучше всего передавать данные на сервер по HTTPS и при этом еще и шифровать алгоритмом 4-х рукопожатий. Асимметричные алгоритмы (RSA, El-Gamal)

Ответ 4



Я бы действовал так: По https на сервер бы отправлял все данные карты(номер, срок действия, CVC). На сервере использовал бы Stripe, чтобы привязять карту к конкретному юзеру. Stripe сам берет на себя вс нагрузку по защищенному хранению и использованию карты. На сервере бы хранил только идентификаторы карт, которые сформировал Stripe. Локально бы хранил только мета информацию(последние 4 цыфры и тд.)

Ответ 5



За хранение карточек без прохождение PCI DSS с вами совершат действия сексуального-насильственного характера. Пока я видел 2 метода - оба хранят данные в компании эквайринге. (aliexpress использует эквайринг alipay): Виртуальные счета - вы создаете виртуального пользователя в платежной системе. Связываете его со своим аккаунтом и выставляете ему счета. Например так делает monetka.ru (она же payanyway ). Пример документации https://payanyway.ru/info/p/ru/public/merchants/SDKphp.pdf стр 16 "Создание нового пользователя" Хранение виртуальных карт - по сути то же самое. Встречал у альфабанка. Но вы видите конкретную карту, часть информации скрыта. Пользователь через сервис привязывает карточку, вы видите "виртульную" карту или список карт и привязываете к его аккаунту. Потом при оплате даете ему выбор карты и подтверждение оплаты. Это называется подписки, рекурентные платежи или регулярные платежи. Можете пройти по платежным система и посмотреть как у них реализовано.

try/catch вместо if null

#java #if #try_catch


Часто бувает несколько и больше аргументов в условии которые необходимо проверить
на null. Мне надоело перечислять if(a!=null && b!=null || c!=null) и т.д. Я стал просто
обрамлять в try/catch и если что-то не так то просто вывожу сообщение, что одно из
условий отсутствует. Понятно что в некоторых случаях необходимо знать, что я получаю
и приходится использовать if.

Но все же является такая практика с t/c нормальной?
    


Ответы

Ответ 1



Примените что-то подобное: private boolean isNull(Object... objects) { if (objects != null) { for (Object object : objects) { if(object==null) return true; } } return false; } //использование if(isNull(a, b, c)) //blah-blah

Ответ 2



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

Ответ 3



Конструкция try/catch обходится дороже. Приведу тест замера времени для 1000000000 вызовов методов проверяющих аргумент на null явно и в попытке и выведу результат замера в консоль: public class Test { public static void main(String[] args) { long start, end; start = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) method(null); end = System.currentTimeMillis(); System.out.println("Check null: " + (end-start)); start = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) methodWithTry(null); end = System.currentTimeMillis(); System.out.println("Try/catch: " + (end-start)); } public static int method(String s) { if (s != null) { return s.length(); } return 0; } public static int methodWithTry(String s) { try { return s.length(); } catch (NullPointerException e) { return 0; } } } Результат: Check null: 15 Try/catch: 1404 UPD: Комментарий Artem Konovalov подтвердился. Судя по всему мой код был автоматически оптимизирован из-за того, что не был использован результат методов. Скорректированный код дает иные результаты: public class Test { public static void main(String[] args) { int c = 0; long start, end; start = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) if (i%2==0) { c += method(null); } else { c += method(i); } end = System.currentTimeMillis(); System.out.println("Check null: " + (end-start)); start = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) if (i%2==0) { c += methodWithTry(null); } else { c += methodWithTry(i); } end = System.currentTimeMillis(); System.out.println("Try/catch: " + (end-start)); } public static int method(Integer i) { if (i != null) { return i.intValue(); } return 0; } public static int methodWithTry(Integer i) { try { return i.intValue(); } catch (NullPointerException e) { return 0; } } Результат: Check null: 1702 Try/catch: 3654

Ответ 4



Однозначно, сказать нельзя, какой вариант лучше. В этой ситуации стоит учитывать несколько моментов. Исключения, как правило, используются для необычных ситуаций, когда выполнение программы пошло не так, как задумывал программист - получены некорректные параметры, внешние ошибки и пр. Из этого можно вывести, что: Если вы пишите код, который будет доступен для вызова сторонними разработчиками, то выкидывание NullPointerException вполне оправдано. Если этот код, является частью внутреннего компонента, то использование блока try-catch-finally, не вполне оправдано. Получение null, говорит о том, что код некорректен, т.е. такая ситуация ненормальна. В идеале, в процессе отладки null проверяется assert'ами и все подобные ситуации вылавливаются в программе. Еще один довод против исключений, это более худная производительность. В моем тесте, разница была порядка 2x.

Передача массива в функцию и range-based цикл

#cpp #массивы #указатели #cpp11


Весь мозг поломал, перечитал все об указателях и так и не понял как сделать этот
код работоспособным. Как прямо сказать циклу что я ему подсовываю именно массив (а
то он ругается что не найдена функция begin)?

void func (int * a)
{
     for (auto n : a) { std::cout << n; }   
}

int main() {

    int arr[] = { 4,7,3,4,7,8,9,0};
    func(arr);
}

    


Ответы

Ответ 1



Поскольку вы передаете указатель (да даже если бы вы передали массив без указания размера - все равно передался бы указатель), таким образом - никак. Указатель не несет в себе никакой информации, кроме адреса. func никак не может узнать, где конец массива. Поскольку в вопросе именно range-based цикл, то тривиальную передачу указателя, количества элементов и обычный цикл не рассматриваем. Но и тут можно выкрутиться - с помощью шаблонов: template void func(T (&a)[N]) { for (auto n : a) { std::cout << n << " "; } } int main() { int arr[] = { 4,7,3,4,7,8,9,0}; func(arr); }

Ответ 2



@Harry. Стоит отметить, что в Вашем, очень изящном решении, в функцию передается не указатель на массив (как в исходном вопросе), а ссылка на массив известного размера. Именно такую рекомендацию дает Страуструп в четвертом издании своей книги (12.2.2, page 318): If you really want to pass an array, rather than a container or a pointer to the first element of an array, you can declare a parameter of type reference to array. Если не использовать шаблоны, то получим набор перегруженных функций - по одной на каждый размер передаваемого массива (и каждого типа массива). В предложенном же решении размер массива, передаваемого в функцию, будет известен в результате выполнения процедуры конкретизации (instantiation) шаблона функции.

Ответ 3



Чтобы произвольные коллекции, а не только массивы в range-циклы передать, можно template-функцию использовать: #include template void func(Range&& range) { for(auto&& v : range) { std::cout << v; } } int main() { int arr[] = { 4,7,3,4,7,8,9,0}; func(arr); } Пример: $ make CXX='g++ -std=c++11' main && ./main g++ -std=c++11 main.cc -o main 47347890 See C++11: Defining Function With Container Parameter (like range-based for)?