Страницы

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

понедельник, 9 марта 2020 г.

Как активировать EditText

#java #android #android_dialog


У меня есть EditText  который при создании активити скрытый editText.setVisibility(View.GONE)
, после чего при выполнении некого условия это текстовое поле должно появиться и что
бы курсор в нем уже мигал , вместе с этим -  должна появится и  клавиатура. Я пробовал
делать так, поле появляется,  но курсор в нем и клавиатура  - нет.  Что я не так делаю?

@Override
public void onQuestionDialogItemClick(int which) {
    messageCompose.setVisibility(View.VISIBLE);
    etInputMsg.setEnabled(true);
    etInputMsg.setSelected(true);
}

    


Ответы

Ответ 1



Это покажет клавиатуру InputMethodManager inputManager = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); ((InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(view, 0); Это даст фокус твоему EditText etInputMsg.requestFocus();

Ответ 2



Возможно как-то так @Override public void onQuestionDialogItemClick(int which) { messageCompose.setVisibility(View.VISIBLE); etInputMsg.setSelected(true); InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.toggleSoftInputFromWindow(linearLayout.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0) }

Обработчик нажатия правой кнопки мыши

#cpp #c #winapi


На winApi пишу сапер. 

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


Ответы

Ответ 1



Смотря, что за кнопка. Если кнопка - отдельное окно, то обрабатывайте сообщения мыши в WndProc. Создайте массив типа HWND и заполните его окнами(которые будете использовать, как кнопки), у которых один общий WndProc.Идентифицируйте, какая кнопка нажата с помощью цикла.Ниже код HWND hwnds[100]={NULL}; hwnds[0]=CreateWindow(...); hwnds[1]=CreateWindow(...); LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wp,LPARAM lp) { switch(message) { case WM_RBUTTONDOWN: for(int i(0);i<100;i++) if(hwnds[i]==NULL) { break; } else if(hwnd==hwnds[i]) { ...//Окно найдено } break; } } Если кнопка стандартная, Шиндоусовская(но это тоже окно, насколько я помню), то через WM_COMMAND.Не пользуюсь, этим убожеством, поэтому код подсказать не могу. Но дам ссылку http://www.firststeps.ru/mfc/winapi/r.php?62 Бонус Рисуете прямоугольник, который будет Вашей кнопкой. При нажатии на окно(на котором Вы нарисовали прямоугольник) обрабатываете WM_RBUTTONDOWN\UP. Если коодрдинаты клика подходят, значит - кнопка нажата. Как это сделать: LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wp,LPARAM lp) { POINT cp; GetCursorPos(&cp);//ну Вы поняли switch(message) { case WM_PAINT: ... Rectangle(hdc,10,10,50,30); ... break; case WM_RBUTTONUP: {//не забудьте про скобки, если хотите объявить переменные внутри case`a RECT r; GetWindowRect(hwnd,&r); int x=cp.x-r.left;//делаем координаты клика, относительно окна int y=cp.y-r.top;//делаем координаты клика, относительно окна if(x>10 && x<50 && y>10 && y<30) { ...//тык } } break; } }

Нет подходящего конструктора по умолчанию

#cpp


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

Integer.h

    class Integer {
private:
    int *_mass;
    int _system;
    int _size;
public:
    Integer(const int *mass, const int system, const int size);
    Integer(const Integer &);
    ~Integer() {
        delete[] _mass;
        _mass = nullptr;
    }
    Integer & operator=(const Integer &);


IntegerCalc.h

class IntegerCalc: public Integer {
private:
    Integer _a;
    Integer _b;
public:
    IntegerCalc(Integer &a, Integer &b) :
        _a(a), _b(b) {}; // ВОТ ТУТ ВЫДАЁТ ОШИБКУ
    ~IntegerCalc() {};

    


Ответы

Ответ 1



Ваш класс IntegerCalc наследуется от Integer - а значит, любой конструктор IntegerCalc должен вызывать конструктор Integer. Не конструктор поля, которые вы вызываете - а конструктор базового класса. Поскольку вы его не вызываете - компилятор автоматически добавляет вызов конструктора по умолчанию. Получается как-то так: public: IntegerCalc(Integer &a, Integer &b) : Integer(), _a(a), _b(b) {}; Но конструктора по умолчанию в базовом классе-то и нет! Отсюда и ошибка. Как такую ошибку исправить - зависит от задачи. Я не очень хорошо понимаю что вы хотели своим кодом сделать. UPD Подкласс калькулятор наследует класс чисел для того, чтобы иметь возможность использовать операторы и методы. Так делать не следует. Для того, чтобы "использовать операторы и методы", надо использовать простой friend, а не наследование. А еще лучше - не делать отдельного интерфейса для калькулятора. Почему калькулятор не может пользоваться открытыми методами?

Подскажите где ошибка в моем коде удаления вершины из бинарного дерева?

#java


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

private static Node delete(Node n, int x) {
        if(n == null) return n;
        if (x > n.x) n.r = delete(n.r, x);
        else if (x < n.x) n.l = delete(n.l, x);
        else if (n.r != null && n.l != null) {
            n.x = n.r.minimum().x;
            n.r = delete(n.r, n.r.x);
        }
        else {
            if (n.r != null) n = n.r;
            else n = n.l;
        }
        return n;
    }
    public void remove(int x){
        delete(this, x);
    }

    


Ответы

Ответ 1



В книге "Алгоритмы построение и анализ" Томас Кормен. Разобран алгоритм удаления узла из бинарного дерева поиска. Процедура удаления разделена на две подпрограммы, являющиеся псевдокодом. Первая: И вторая: Где T- ссылка на ваше дерево, z- ссылка на узел который нужно удалить. Полагаю, зная этот алгоритм, для вас не составит труда написать его реализацию.

Ответ 2



Нужно строку n.r = delete(n.r, n.r.x); заменить на n.r = delete(n.r, n.x); т.к. иначе вы удаляете не искомое, а ноду справа

Залогинивание в приложении. Оптимальный вариант. Шифрование

#c_sharp


Есть приложение на подобии чата. На сервере есть бд, где хранятся пароли (хэши) и
логины. Как лучше всего организовать залогинивание? Я могу сохранять логин и пароль
в бд у пользователя (sqlite), а потом подставлять, но это мне не очень нравится, так
как можно легко угнать данные. Можно как-нибудь зашифровать, но зная алгоритм, можно
расшифровать. Как лучше всего сделать? Где безопаснее всего хранить?

Тот же хром просто надругательство. Пароли шифруются стандартным методом, что позволят
без труда их угнать.
    


Ответы

Ответ 1



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

Как переустановить Ubuntu и не потерять данные на RAID 1 (mdadm)?

#linux #массивы #ubuntu #debian #raid


Добрый день, Имеется программный raid1, необходимо переустановить линукс. Не будут
ли форматированы диски при создании нового рейда?
    


Ответы

Ответ 1



Бекап важный файлов никогда не мешает. Загрузитесь с LiveCD/LiveUSB. Если Файловая система видна корректно, то значит все получится. Если у Вас разбито правильно (то есть /home и / (корень) лежат в отдельных разделах), то просто отформатируйте корень и устанавливайте систему (при этом лучше поискать там возвожность расширенной установки). Если же система поставленна по виндовому (то есть, все в один раздел), то загрузившись с лайва, поудаляйте все, кроме /home и устанавливайте систему, при этом, не забудьте снять галочки "форматировать раздел".

Ответ 2



Я надеюсь, что ОС установлена на отдельном жестком диске, не имеющем отношения к массиву. Этот диск можно отформатировать и поставить новую ОС. После переустановки ОС запустите поиск созданных ранее массивов: mdadm --assemble --scan Так можно посмотреть текущее состояние массива: cat /proc/mdstat Создайте конфиг-файл для массива: mdadm --detail --scan --verbose > /etc/mdadm.conf Создайте точку монтирования для массива: mkdir /home/myRAID Для того, чтобы массив загружался при каждой загрузке ОС, Добавим строчку в /etc/fstab: /dev/md0 /home/myRAID ext4 defaults 0 0 Эта запись подразумевает, что адрес устройства вашего массива /dev/md0 (уточните это, сделайте ls /dev/md*); а так же, что у вас файловая система ext4. Если у вас другая, впишите другое соответствующее значение (например, ext3, NTFS, итд.) Далее даны стандартные параметры, подробне можно прочитать тут. Монтируем массив: mount -a Эта команда монтирует всё, что ещё не примонтировано в системе, но указано в /etc/fstab. p.s. так же, посмотреть на текущее состояние массива можно командой: mdadm -D /dev/md0 Перед переустановкой ОС убедитесь, что с вашим массивом всё в порядке.

Установка приложения через ADB

#java #android


Дано:  название пакета из Google Play к примеру (details?id=com.whatsapp)

Задача: установить это приложение на устройство автоматически, т.е. написал имя пакета
и приложение установилось на устройство, как можно это реализовать? 
    


Ответы

Ответ 1



Этот вопрос уже задавался здесь (англ) Если подытожить то что сказано в ответах, то нельзя установить ничего из маркета автоматически. Но можно открыть маркет из командной строки: adb shell am start -a android.intent.action.VIEW -d 'market://details?id=com.myapp' Либо скачать .apk файл при помощи apk downloader и установить используя adb install

Оптимальное использование статических полей при проектировании классов

#c_sharp #классы


Есть базовый абстрактный класс и 3 других класса, которые последовательно наследуют
реализацию предыдущего (BaseAbstract->A->B->C). При создании нового экземпляра одного
из этих трех классов, задействуется статическое поле (счетчик) в соответствующем классе
для подсчета суммарного количества экземпляров конкретного класса, вывод которого осуществляется
через статический метод.

abstract class BaseAbstract
{
    public BaseAbstract()
    {
        //инициализация полей абстрактного класса

        IncStaticField();   //вызов абстрактного метода в конструкторе абстрактного
класса
    }
    protected abstract void IncStaticField();
}

class A : BaseAbstract 
{
    private static int instNo = 0;  //стат. поле

    protected override void IncStaticField()
    {
        A.instNo = A.instNo + 1;   //тип указываю здесь лишь для "пояснения" собственных
намерений
    }

    public static string Info()     //вывод кол-ва созданных экземпляров конкретного
класса
    {
        return "Общее количество созданных экземпляров класса A: " + instNo;
    }
}

class B : A
{
    private static int instNo = 0;

    protected override void IncStaticField()
    {
        B.instNo = B.instNo + 1;
    }

    public static new string Info()     // замещение
    {
        return "Общее количество созданных экземпляров класса B: " + instNo;
    }
}

class C : B
{
    //аналогичная реализация, как в классе B
}


Данная реализация успешно подсчитывает кол-во созданных экземпляров для каждого класса
и выводит их значения через вызов метода Info() конкретного класса.

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

2) Можно ли упростить реализацию метода IncStaticField(), дабы не приходилось объявлять
его в каждом классе лишь для указания класса статического поля которое следует увеличить?
    


Ответы

Ответ 1



Для начала пару слов про ваш код: public static new string Info() // замещение new в данном случае не требуется, т.к. CLR, вообще, и C#, в частности, не поддерживают наследование статических членов, соответственно никакой проблемы с одноименными статическими методами в классах наследниках не возникнет. 1) Насколько безопасным является вызов абстрактного (виртуального) метода в конструкторе, благодаря которому и происходит увеличение статического поля конкретного класса? Если абстрактный/виртуальный метод корректно реализован/переопределен с использованием override, то все будет нормально. Но проблема с вероятностью возникнет, если виртуальный метод не переопределен в классе и вызывает метод базового класса, который еще не был инстанцирован. Поэтому в целом такой подход не желателен, т.к. мы не можем заставить производный класс принудительно переопределить виртуальный метод. 2) Можно ли упростить реализацию метода IncStaticField(), дабы не приходилось объявлять его в каждом классе лишь для указания класса статического поля которое следует увеличить? Если метод используется исключительно для увеличения счетчика объектов, то почему бы не заменить его на обычный instNo++ в конструкторе? Таким образом определять метод в каждом классе не нужно. А вот более сложную логику, если она есть/нужна, уже можно выпилить в отдельный метод, и переопределять его по мере необходимости. Ну и напоследок полезная статья про статические члены классов и классы: Эрик Браун Семь советов по применению статических полей, методов и классов

Ответ 2



Как вариант, могу предложить завести в самом базовом классе одно статическое поле -- словарь (Dictionary) с ключом -- тип класса либо название типа класса, и значением int. И один метод (невиртуальный), который и будет всё делать. В метод передаём Type. Принцип работы метода такой: увеличить счётчик в словаре для переданного типа, затем по reflection взять для этого типа тип-родитель, увеличить счётчик в словаре для него итд. Ну и обеспечить вызов этого метода-счётчика из конструктора каждого порождённого класса. Плюсы -- никаких виртуальных вызовов в конструкторе. Минусы -- использование рефлексии, снижающее производительность.

Деактивация input'a через время

#javascript #html #jquery


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




$("input[type='text']").focus(function (){
    setTimeout(function () {
        $(this).attr("disabled", "disabled");
    }, 3000);
});


Пробовал так, но не получилось
    


Ответы

Ответ 1



setTimeout вызывает функцию в глобальном контексте, где this это window. $("input[type='text']").focus(function (){ var thisInput = this; setTimeout(function () { $(thisInput).attr("disabled", "disabled"); }, 3000); });

Какова сложность алгоритма и как она подсчитана?

#python #алгоритм #python_3x


Какова сложность алгоритма поиска подстроки в строке, и как она подсчитана? Прошу
объяснить. (алгоритм сыроват, но упрощён в качестве примера и для понимания)

text='bla-bla-this-bla'
subtext='this'
for i,element in enumerate(text):
    if element == subtext[0]:
        if subtext == text[i:i+len(subtext)]:
            print(i)

    


Ответы

Ответ 1



Пусть: n = len(text) m = len(subtext) Очевидно что цикл for сделает в худшем случае n итераций, внутри каждой итерации в худшем случае мы делаем слайс text[i:i+len(subtext)], который выполняется за O(m), а затем сравнение за те же O(m), в итоге получаем O(nm).

В чем преимущества выделения контроллера в mvc?

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


У меня сразу несколько вопросов по mvc. Спрашивать буду на примере игрушечной программки,
которую специально для этого написал:

public class View implements Observer {

private Model model;
private IController controller;

private JLabel firstNumber = new JLabel();
private JLabel secondNumber = new JLabel();
private JLabel resultLabel = new JLabel();

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            Model model = new Model();
            IController controller = new Controller();
            View view = new View();
            view.setModel(model);
            view.setController(controller);
            view.createAndShowGUI();
        }
    });
}

public void setModel(Model model) {
    this.model = model;
    model.addObserver(this);
}

public void setController(IController controller) {
    this.controller = controller;
}

public void createAndShowGUI() {
    JFrame frame = new JFrame("mvc train");
    frame.setSize(400, 400);
    frame.getContentPane().add(createMainPanel());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}

private Component createMainPanel() {
    JPanel mainPanel = new JPanel();
    mainPanel.add(firstNumber);
    mainPanel.add(secondNumber);
    mainPanel.add(resultLabel);
    JButton inc1 = new JButton("increment first");
    inc1.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            controller.execute("inc1", model);
        }
    });
    JButton dec1 = new JButton("decrement first");
    dec1.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            controller.execute("dec1", model);
        }
    });
    mainPanel.add(inc1);
    mainPanel.add(dec1);
    JButton inc2 = new JButton("increment second");
    inc2.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            controller.execute("inc2", model);
        }
    });
    JButton dec2 = new JButton("decrement second");
    dec2.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            controller.execute("dec2", model);
        }
    });
    mainPanel.add(inc2);
    mainPanel.add(dec2);
    return mainPanel;
}

@Override
public void update(Observable arg0, Object arg1) {
    firstNumber.setText("" + model.getA());
    secondNumber.setText("" + model.getB());
    resultLabel.setText("" + (model.getA() + model.getB()));
}

}


Это класс представления. Получается такая картинка:


Кнопка increment first увеличивает на единицу первое число, increment second - второе,
decrement first уменьшает первое число на единицу, decrement secomd - второе. В общем,
после двух нажатий на increment first и одного нажатия на increment second получаем
такую картинку:



Два числа хранятся в модели. Вот она:

public class Model extends Observable {

private int a;
private int b;

public void incrementA() {
    a++;
    setChanged();
    notifyObservers();
}

public void incrementB() {
    b++;
    setChanged();
    notifyObservers();
}

public void decrementA() {
    a--;
    setChanged();
    notifyObservers();
}

public void decrementB() {
    b--;
    setChanged();
    notifyObservers();
}

public int getA() {
    return a;
}

public int getB() {
    return b;
}

@Override
public void addObserver(Observer observer) {
    super.addObserver(observer);
    setChanged();
    notifyObservers();
}

}


Мой контроллер:

public class Controller implements IController {

@Override
public void execute(String action, Model model) {
    switch (action) {
    case "inc1":
        model.incrementA();
        break;
    case "inc2":
        model.incrementB();
        break;
    case "dec1":
        model.decrementA();
        break;
    case "dec2":
        model.decrementB();
    }
}

}


Теперь вопросы.
Самый главный вопрос собственно в названии.


Чем нам помог контроллер? Код из веток case оператора switch в
контроллере мог бы с таким же успехом находится в слушателях. На
каждую ветку по слушателю. В итоге слушателей все равно приходится
создавать, что бы вызвать метод контроллера. А потом в этом методе в
операторе switch прописывать тот же самой код, что мог бы быть в
слушателях. Может быть я вообще неправильно реализовал mvc?
Подозреваю что именно так. Причем именно в части контроллера. Потому
что по нему в сети мало информации. Если это так то прошу подсказать
как правильно. Слышал что можно создавать контроллеры для каждого
элемента (в данном случае для каждой кнопки). Но ситуация не сильно
поменяется.
В моем примере все методы, которые вызывается в ветках case не имеют параметров.
В реальных программах это скорее всего будет не так. Некоторые кнопки могли бы требовать
вызовов методов с параметрами, причем с разным количеством параметров. Что делать в
такой ситуации?
Где лучше вычислять самое правое число? В моем примере я делаю это в функции update().
Не лучше ли это делать в модели?

    


Ответы

Ответ 1



Контроллер помогает структурировать код. Весь код, реагирующий на пользовательский ввод, принадлежит контроллеру. Можно было бы всё слить в один класс, и делать всю логику в OnClick, и код получился бы наверное даже короче. Но вашей целью должен быть не самый короткий, а самый понятный и легко поддерживаемый код. Мне кажется, ваша диспетчеризация команд по строкам — неправильна. Команды должны быть не строками, а объектами. (У нас же ООП, в конце-концов, да?) И вместо длинного свитча у вас должен быть всего лишь вызов Invoke. [Но это практика из MVVM, общепринятого паттерна в WPF, а традиции в MVC могут быть и другими.] Вычисления принадлежат модели и только ей. Представление должно не выполнять работу модели (а сложение в реальной программе превратится в серьёзное, длинное вычисление), а лишь только отображать её.

Uncaught TypeError: jQuery(…).datepicker is not a function

#javascript #jquery #ruby_on_rails #jquery_ui


В проекте написанном на ruby on rails установлна библиотека для jquery ui. 

На следующем скрипте через консоль гугл хром выдает ошибку 


  Uncaught TypeError: jQuery(...).datepicker is not a function





Полазив в интернете на форумах и поговорив с программистами, все говорят, что это
из конфликта скриптов. Где то два раза запускается один и тот же скрипт или конфликт имен. 

У меня вопрос следующий. Как и с помощью каких инструментов можно проверить где и
что именно конфликтует? Проект очень большой, толком понять где этот скрипт конфликтует
очень сложно. Заранее спасибо за ответ.   
    


Ответы

Ответ 1



Проблема была связана с конфликтом нескольких скриптов jquery. Через консоль хрома показала ошибку плагина. Удалил дублирующий и все стало на свои места.

Скрыть выпадающее меню при клике куда угодно JQuery

#javascript #jquery #меню


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

$(document).ready(function() {
    $(hidden).slideUp();

    $('.switch').click(function() {
        $(hidden).slideDown(300);
        $('#drop-but').removeClass('switch');
        return false;
    });

    $(document).click(function() {
        $(hidden).slideUp(300);
        $('#drop-but').addClass('switch');
    });
});

    


Ответы

Ответ 1



Как вариант: $(function() { $('.menu-wrap').on('click', function() { var $this = $(this); if ($this.hasClass('active')) { $this.removeClass('active'); $(document).off('click.menu'); } else { $this.addClass('active'); $(document).on('click.menu', function(e) { if ($(e.target).closest('.menu-wrap').length === 0) { $('.menu-wrap').removeClass('active'); $(document).off('click.menu'); } }); } }); }); .menu-wrap { position: relative; width: 100px; } .menu-title { width: 100%; border: 1px solid black; cursor: pointer; transition: all .5s; } .menu-wrap.active .menu { visibility: visible; opacity: 1; } .menu { border: 1px solid black; border-top: none; width: 100%; visibility: hidden; opacity: 0; transition: all .5s; } ul { list-style-type: none; margin: 0; padding: 0; } li:hover { cursor: pointer; background: #eee; }

Ответ 2



Дело в том, что этот обработчик: $('.switch').click(function() { $(hidden).slideDown(300); $('#drop-but').removeClass('switch'); return false; }); Отменяет все обработчики на .switch, что идут после него. Чтобы не отменять вместо return false; сделайте e.preventDefault(); Соответственно e надо указать как входящий параметр $('.switch').click(function(e) {

Поиск всех значений в TreeMap c “неполным” ключом

#java #android


Доброго времени суток. Нужен совет, как найти все значения в TreeMap с "неполным"
ключом. Допустим имеются какие то значения с ключами "Book","Boom","Trap"... При ключе
"Boo" должен выводить значения у которых ключ начинается на этот кусок. 

Пробовал использовать методы ceilingKey(), floorKey(), higherKey(), lowerKey(), но
столкнулся с проблемой, выводит лишь одно значение. Попробовал удалять элементы после
получения, тогда он выводит весь TreeMap пока не опустеет. 

Может есть какой то более подходящий подход для этой задачи ?
    


Ответы

Ответ 1



На англоязычном SO есть несколько таких вопросов с ответом Идея такая: используем метод subMap, первым параметром передаем наш префикс (или как вы говорите "неполный ключ"), вторым параметром передаем этот же неполный ключ, только с измененным последним символом, который на единицу больше предыдущего (либо можно просто в конец "неполного ключа" дописать Character.MAX_VALUE).

Ответ 2



Судя по en-SO можно так: public SortedMap getByPreffix(NavigableMap myMap, String preffix ) { return myMap.subMap( preffix, preffix + Character.MAX_VALUE ); }

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

#cpp #алгоритм #очередь


Попалась такая задача: «при помощи очереди изъять лишние скобки из арифметического
выражения». Изначально она показалась очень простой, но на практике вызвала много затруднений.

Добавление @mymedia:

Лишними скобками считаются те, которые можно убрать, сохранив смысл выражения. Например,
(5*7)+3 → 5*7+3, ((a+b)) → a+b.
    


Ответы

Ответ 1



Задача действительно не самая простая и через стек ее не решить. Через стек решается задача определения правильности/неправильности скобочной последовательности. Лишние скобки так не убрать. ВОТ можно почитать про обратную польскую нотацию. Раскладываете выражение, собираете обратно и где надо ставите скобки. Тогда лишних уже не будет. P.S. очередь/стек там используется для сохранения операций.

Узнать имя класса во время исполнения программы

#cpp #boost


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

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

Это можно реализовать? Можно и boost`ом.
    


Ответы

Ответ 1



Функция typeid(object) возвращает объект типа type_info с информацией о типе объекта, для которого она вызывается (собственно, о классе). У этого объекта(type_info) есть метод name(), который и возвращает имя класса. Для использования нужно подключить . Так что в итоге для получения имени класса нужно использовать typeid(*this).name() Или, если функция не является методом класса, передать в typeid сам объект или разыменованный указатель.

Ответ 2



Собственные средства c++ не позволяют ничего узнать о контектсте вызова функции. Стек вызова можно проанализировать с помощью некоторых внешних библиотек / API операционной системы. Например: http://man7.org/linux/man-pages/man3/backtrace.3.html https://msdn.microsoft.com/en-us/library/ms680650%28VS.85%29.aspx . Но для применение этих средств может налагать дополнительные ограничения на собираемый код (сборка с отладочной информацией и т.д.). Более разумно, ИМХО, передавать контекст вызова явно: это позволит использовать "штатные" средства c++: __FILE__, __LINE__, __func__, .... Извлечение контекста можно замаскировать макросом: struct Context{ const char* file; unsigned line; const char* function; }; // Work around MSVS #ifndef __func__ #define __func__ __FUNCTION__ #endif #define CONTEXT() Context({ __FILE__, __LINE__, __func__}) void foo( int a, int b, Context c ); #define FOO(a, b) foo( a, b, CONTEXT() ) Имя класса можно извлечь либо разобрав имя __FUNCTION__, либо из указателя this : typeid(this).name() Но не хочется включать этот обращение к this в макрос, поскольку функции может быть вызвана из контекста, статической функции. С другой стороны для целей разделения логов может быть достаточно __FILE__.

Почему упал сайт? 500

#php #mysql #битрикс #администрирование


Ребят, не очень шарю в администрировании, есть такая проблема: сайт выдаёт 500 ошибку,
глянул логи там спамит вот такая ошибка: 


  ri Apr 22 04:07:31.657989 2016] [:error] [pid 16512] [client
  85.14.245.175:48527] PHP Fatal error: Namespace declaration statement has to be
the very first statement in the script in
  /var/www/maxkondaurov/data/www/maxkondaurov.ru/bitrix/modules/main/lib/db/mysqlcommonconnection.php
  on line 2 [Fri Apr 22 04:07:33.244247 2016] [:error] [pid 16513]
  [client 85.14.244.114:48794] PHP Fatal error: Namespace declaration
  statement has to be the very first statement in the script in
  /var/www/maxkondaurov/data/www/maxkondaurov.ru/bitrix/modules/main/lib/db/mysqlcommonconnection.php
  on line 2


Зашел в этот файлик на второй строчке там
namespace Bitrix\Main\DB;

В чем может быть проблема? это же стандартный файл битрикса, при чем сайт работал,
но что то произошло и стала 500 ошибка вылетать, могу кинуть полный код файла mysqlcommonconnection.php

вот начало кода,в 3 строке убрал пробел, не помогло


 * 
  • host *
  • database *
  • login *
  • password *
  • initCommand *
  • options *
  • engine * * * @param array $configuration Array of Name => Value pairs. */ public function __construct(array $configuration) { parent::__construct($configuration); $this->engine = isset($configuration['engine']) ? $configuration['engine'] : ""; } /** * Checks if a table exists. * * @param string $tableName The table name. * * @return boolean */ public function isTableExists($tableName) { $tableName = preg_replace("/[^a-z0-9%_]+/i", "", $tableName); $tableName = trim($tableName); if (strlen($tableName) <= 0) { return false; } $result = $this->query("SHOW TABLES LIKE '".$this->getSqlHelper()->forSql($tableName)."'"); return (bool) $result->fetch(); } /** * Checks if an index exists. * Actual columns in the index may differ from requested. * $columns may present an "prefix" of actual index columns. * * @param string $tableName A table name. * @param array $columns An array of columns in the index. * * @return boolean * @throws \Bitrix\Main\Db\SqlQueryException */ public function isIndexExists($tableName, array $columns) { return $this->getIndexName($tableName, $columns) !== null; } /** * Returns the name of an index. * * @param string $tableName A table name. * @param array $columns An array of columns in the index. * @param bool $strict The flag indicating that the columns in the index must exactly match the columns in the $arColumns parameter. * * @return string|null Name of the index or null if the index doesn't exist. * @throws \Bitrix\Main\Db\SqlQueryException */ public function getIndexName($tableName, array $columns, $strict = false) { if (!is_array($columns) || count($columns) <= 0) return null; $tableName = preg_replace("/[^a-z0-9_]+/i", "", $tableName); $tableName = trim($tableName); $rs = $this->query("SHOW INDEX FROM `".$this->getSqlHelper()->forSql($tableName)."`"); if (!$rs) return null; $indexes = array(); while ($ar = $rs->fetch()) { $indexes[$ar["Key_name"]][$ar["Seq_in_index"] - 1] = $ar["Column_name"]; } $columnsList = implode(",", $columns); foreach ($indexes as $indexName => $indexColumns) { ksort($indexColumns); $indexColumnList = implode(",", $indexColumns); if ($strict) { if ($indexColumnList === $columnsList) return $indexName; } else { if (substr($indexColumnList, 0, strlen($columnsList)) === $columnsList) return $indexName; } } return null; } /** * Returns fields objects according to the columns of a table. * Table must exists. * * @param string $tableName The table name. * * @return Entity\ScalarField[] An array of objects with columns information. * @throws \Bitrix\Main\Db\SqlQueryException */ public function getTableFields($tableName) { if (!isset($this->tableColumnsCache[$tableName])) { $this->connectInternal(); $query = $this->queryInternal("SELECT * FROM ".$this->getSqlHelper()->quote($tableName)." LIMIT 0"); $result = $this->createResult($query); $this->tableColumnsCache[$tableName] = $result->getFields(); } return $this->tableColumnsCache[$tableName]; } /** * @param string $tableName Name of the new table. * @param \Bitrix\Main\Entity\ScalarField[] $fields Array with columns descriptions. * @param string[] $primary Array with primary key column names. * @param string[] $autoincrement Which columns will be auto incremented ones. * * @return void * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\Db\SqlQueryException */ public function createTable($tableName, $fields, $primary = array(), $autoincrement = array()) { $sql = 'CREATE TABLE '.$this->getSqlHelper()->quote($tableName).' ('; $sqlFields = array(); foreach ($fields as $columnName => $field) { if (!($field instanceof Entity\ScalarField)) { throw new ArgumentException(sprintf( 'Field `%s` should be an Entity\ScalarField instance', $columnName )); } $sqlFields[] = $this->getSqlHelper()->quote($columnName) . ' ' . $this->getSqlHelper()->getColumnTypeByField($field) . ' NOT NULL' // null for oracle if is not primary . (in_array($columnName, $autoincrement, true) ? ' AUTO_INCREMENT' : '') ; } $sql .= join(', ', $sqlFields); if (!empty($primary)) { foreach ($primary as &$primaryColumn) { $primaryColumn = $this->getSqlHelper()->quote($primaryColumn); } $sql .= ', PRIMARY KEY('.join(', ', $primary).')'; } $sql .= ')'; if ($this->engine) { $sql .= ' Engine='.$this->engine; } $this->query($sql); } /** * Creates index on column(s) * @api * * @param string $tableName Name of the table. * @param string $indexName Name of the new index. * @param string|string[] $columnNames Name of the column or array of column names to be included into the index. * @param string[] $columnLengths Array of column names and maximum length for them. * * @return Result * @throws \Bitrix\Main\Db\SqlQueryException */ public function createIndex($tableName, $indexName, $columnNames, $columnLengths = null) { if (!is_array($columnNames)) { $columnNames = array($columnNames); } $sqlHelper = $this->getSqlHelper(); foreach ($columnNames as &$columnName) { if (is_array($columnLengths) && isset($columnLengths[$columnName]) && $columnLengths[$columnName] > 0) { $maxLength = intval($columnLengths[$columnName]); } else { $maxLength = 0; } $columnName = $sqlHelper->quote($columnName); if ($maxLength > 0) { $columnName .= '('.$maxLength.')'; } } unset($columnName); $sql = 'CREATE INDEX '.$sqlHelper->quote($indexName).' ON '.$sqlHelper->quote($tableName).' ('.join(', ', $columnNames).')'; return $this->query($sql); } /** * Renames the table. Renamed table must exists and new name must not be occupied by any database object. * * @param string $currentName Old name of the table. * @param string $newName New name of the table. * * @return void * @throws \Bitrix\Main\Db\SqlQueryException */ public function renameTable($currentName, $newName) { $this->query('RENAME TABLE '.$this->getSqlHelper()->quote($currentName).' TO '.$this->getSqlHelper()->quote($newName)); } /** * Drops the table. * * @param string $tableName Name of the table to be dropped. * * @return void * @throws \Bitrix\Main\Db\SqlQueryException */ public function dropTable($tableName) { $this->query('DROP TABLE '.$this->getSqlHelper()->quote($tableName)); } /********************************************************* * Transaction *********************************************************/ /** * Starts new database transaction. * * @return void * @throws \Bitrix\Main\Db\SqlQueryException */ public function startTransaction() { $this->query("START TRANSACTION"); } /** * Commits started database transaction. * * @return void * @throws \Bitrix\Main\Db\SqlQueryException */ public function commitTransaction() { $this->query("COMMIT"); } /** * Rollbacks started database transaction. * * @return void * @throws \Bitrix\Main\Db\SqlQueryException */ public function rollbackTransaction() { $this->query("ROLLBACK"); } /********************************************************* * Type, version, cache, etc. *********************************************************/ /** * Sets default storage engine for all consequent CREATE TABLE statements and all other relevant DDL. * Storage engine read from .settings.php file. It is 'engine' key of the 'default' from the 'connections'. * * @return void * @throws \Bitrix\Main\Db\SqlQueryException */ public function setStorageEngine() { if ($this->engine) { $this->query("SET storage_engine = '".$this->engine."'"); } } } ?>

  • Ответы

    Ответ 1



    Вероятнее всего дело в символах в начале файла. По нормальному, код должен начинаться с

    Entity Framework не удаляется связанная по внешнему ключу запись

    #c_sharp #entity_framework

    
    Пытаюсь удалить элемент из коллекции UsersVaults объекта типа User, но получаю Exception
    (текст ошибки и код ниже). Подскажите, где я повернул не туда?
    
    Метод изменения объекта:
    
    [HttpPost]
        public ActionResult Edit(int id, FormCollection form)
        {
            try
            {
                using (var db = new AccessControlSystemDatabaseModel())
                {
                    var user = db.Users.Find(id);
                    var tempData = form.AllKeys.ToDictionary(key
    => key, key => form[key]);
    
                    user.RoleID = Convert.ToInt32(tempData["RoleID"]);
                    user.Username = tempData["Username"].ToString();
                    user.Password = tempData["Password"].ToString();
                    user.Email = tempData["Email"].ToString();
    
                    if (!tempData["GrantAccess"].ToString().Equals("false") && user.UsersVaults.Where(
                        d => d.VaultID == AuthenticationController.CurrentUser.UsersVaults.ToList()[0].VaultID)
                        .ToList()
                        .Count == 0)
                    {
                        user.UsersVaults.Add(new UsersVault
                        {
                            UserID = id,
                            VaultID = AuthenticationController.CurrentUser.UsersVaults.ToList()[0].VaultID,
                        });
                    }
                    else
                    {
                        var tt =
                            user.UsersVaults.Where(
                                d => d.VaultID == AuthenticationController.CurrentUser.UsersVaults.ToList()[0].VaultID).ToList()[0];
    
                        user.UsersVaults.Remove(tt);
                    }
    
                    db.Entry(user).State = EntityState.Modified;
                    db.SaveChanges();
    
                    return RedirectToAction("Index");
                }
            }
            catch(Exception e)
            {
                return RedirectToAction("Index");
            }
        }
    
    
    Модель:
    
    public partial class AccessControlSystemDatabaseModel : DbContext
    {
        public AccessControlSystemDatabaseModel()
            : base("name=AccessControlSystemDatabaseModel")
        {
        }
    
        public virtual DbSet Roles { get; set; }
        public virtual DbSet Users { get; set; }
        public virtual DbSet UsersVaults { get; set; }
        public virtual DbSet Vaults { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity()
                .HasMany(e => e.UsersVaults)
                .WithRequired(e => e.User)
                .WillCascadeOnDelete(true);
    
            modelBuilder.Entity()
                .HasMany(e => e.UsersVaults)
                .WithRequired(e => e.Vault)
                .WillCascadeOnDelete(true);
        }
    }
    
    
    public partial class Role
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Role()
        {
            Users = new HashSet();
        }
    
        public int ID { get; set; }
    
        [Required]
        [StringLength(255)]
        public string RoleName { get; set; }
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection Users { get; set; }
    }
    
    public partial class User
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public User()
        {
            UsersVaults = new HashSet();
        }
    
        public int ID { get; set; }
    
        [Required]
        [StringLength(255)]
        public string Username { get; set; }
    
        [Required]
        [StringLength(255)]
        public string Password { get; set; }
    
        public int? RoleID { get; set; }
    
        [StringLength(255)]
        public string Email { get; set; }
    
        public virtual Role Role { get; set; }
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection UsersVaults { get; set; }
    }
    
    public partial class UsersVault
    {
        public int ID { get; set; }
    
        public int UserID { get; set; }
    
        public int VaultID { get; set; }
    
        public virtual User User { get; set; }
    
        public virtual Vault Vault { get; set; }
    }
    
    public partial class Vault
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
        public Vault()
        {
            UsersVaults = new HashSet();
        }
    
        public int ID { get; set; }
    
        [Required]
        [StringLength(255)]
        public string VaultName { get; set; }
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public virtual ICollection UsersVaults { get; set; }
    }
    
    
    
    
    Текст исключения:
    
    
      "Операция завершилась с ошибкой. Не удалось изменить связь, поскольку один или
    несколько свойств внешнего ключа не допускают значения NULL. При изменении связи соответствующему
    свойству внешнего ключа присваивается значение NULL. Если внешний ключ не поддерживает
    значений NULL, должна быть определена новая связь, свойству внешнего ключа должно быть
    присвоено другое значение, отличное от NULL, либо необходимо удалить несвязанный объект."
    
        
    


    Ответы

    Ответ 1



    В EF, к сожалению, операции Add и Remove для навигационных коллекций не всегда симметричны - первая операция устанавливает связь между сущностями и при необходимости добавляет их в базу, вторая же только разрывает связь. Но разорвать связь между UsersVault и User невозможно, отсюда и ошибка. Поэтому надо вместо удаления объекта из коллекции явно удалить его из базы: var tt = user.UsersVaults.Single(...); db.Entry(tt).State = EntityState.Deleted; или db.UsersVaults.Remove(tt); Для сохранения симметричности операций, можно при добавлении UsersVault точно так же сразу добавлять его в базу: db.UsersVaults.Add(new UsersVault { UserID = id, VaultID = ..., }) Кстати, в вашем текущем коде есть дублирование - UserID присваивать не обязательно если вы добавляете объект через навигационную коллекцию - EF проставит его сама. В качестве альтернативного решения могу предложить вообще удалить сущность UsersVault - она не нужна! EF умеет самостоятельно отображать связи "многие-ко-многим" на промежуточные таблицы, просто создайте mtm-связь между Users и Vaults.

    Как работать с TCP в Swift?

    #ios #swift #tcp_ip

    
    У меня есть TCP сервер, который слушает входящие команды и общается с БД. Как мне
    слать к нему запросы из ios приложения? Работаю со swift 2.
    
    Другими словами, нужно реализовать следующее:
    Пользователь вводит логин и пароль, пытается войти в свой аккаунт. В это время посылается
    запрос на сервер - "Проверь, есть ли такой юзер в БД". Он это делает, и шлет ответ
    обратно на ios приложение. 
    
    Никак не могу понять, как мне такое реализовать. Насколько я понимаю, мне нужно работать
    с потоками, но ничего путного про это на ios я не нашел.
        
    


    Ответы

    Ответ 1



    Если я Вас правильно понял, то потоки Вам вовсе не нужны. Тут надо использовать блоки. Скажем Вы отправляете запрос и включаете индикатор загрузки, а когда приходит ответ Вы прекращаете загрузку и в зависимости от результата с сервера используете success или же failure блок. Советую использовать AFNetworking. Что-то на подобии let manager = AFHTTPRequestOperationManager() manager.GET( "http://myServerUrl.com", parameters: ["email":"myemail@gmail.com", "password":"1234Password"], success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in //TODO - make login action }, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in // TODO - show error message } )

    Ответ 2



    На сколько я понимаю вам необходимо выполнить HTTP запрос авторизации пользователя к вашему серверу и получить какой то ответ. Для работы с сетью на Swift вам подойдет Alamofire. Самый простой пример выполнения GET запроса: Alamofire.request(.GET, "https://yourserver.org/get", parameters: ["name": "user", "pass": "12345"]) .responseJSON { response in print(response.result) // result of response serialization } Более подробные примеры запросов приведены в описании либы.

    Обтекание текста под углом

    #html #jquery #css #вёрстка

    
    
    
    Как сделать такое обтекание текста под углом?
        
    


    Ответы

    Ответ 1



    https://css-tricks.com/almanac/properties/s/shape-outside/ .block{ overflow: hidden; margin: 10px; padding: 15px; } .pict{ float:left; width:100px; height:150px; margin:10px; background-color: #ccc; -webkit-shape-outside: polygon(100% 50%, 0 0, 0 100%); shape-outside: polygon(100% 50%, 0 0, 0 100%); -webkit-clip-path: polygon(100% 50%, 0 0, 0 100%); clip-path: polygon(100% 50%, 0 0, 0 100%); -webkit-shape-margin: 10px; shape-margin: 10px; }
    text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text
    или .block{ overflow: hidden; margin: 10px; padding: 15px; } .pict{ float:left; width:100px; height:150px; margin:10px; background-color: #ccc; -webkit-shape-outside: polygon(0 0, 100% 50%, 100% 100%, 0% 100%); shape-outside: polygon(0 0, 100% 50%, 100% 100%, 0% 100%); -webkit-clip-path: polygon(0 0, 100% 50%, 100% 100%, 0% 100%); clip-path: polygon(0 0, 100% 50%, 100% 100%, 0% 100%); -webkit-shape-margin: 10px; shape-margin: 10px; }
    text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text


    Как добавить в приложение уже заполненную базу?

    #android #sqlite

    
    Есть приложение, в нем есть список чего-то на 200 итемов.
    
    Как мне поставлять приложение с уже заполненной базой ?
    т.е. чтобы после установки приложения этот список заполнился из базы.
        
    


    Ответы

    Ответ 1



    Схематично: В assets кладете Вашу БД Создаете БД в приложении (стандартно SQLiteOpenHelper) Копируете при первом запуске БД из assets в БД приложения. Работаете с заполненной БД. После очистки данных приложения пользователем повторить п.3

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

    #java #android #xml

    
    есть два активити , одно открывается сверху другого и на нём gridview, хочу чтобы
    верхнее было полупрозрачным (не полностью прозрачное, не android:style/Theme.Translucent)
    , как загрузить фоновую картинку я понял android:background="@drawable/picture" . 
    И вот везде на вопрос как сделать его прозрачным, говорят поставить android:alpha="0.5"
    , ну и что ? получается просто СВетлая картинка, но не прозрачная , через неё не видно
    элементов нижнего активити.. Еще говорят установить color ARGB , где A отвечает за
    прозрачность, но получается такая же Светлая картинка, не прозрачная.. 
    
    
    
    
    
    В манифесте я даже не знаю  , что еще пробовать , пока вот 
        введите  
         сюда код
        
    


    Ответы

    Ответ 1



    Для реализации того что хотите лучше использовать фрагменты (либо другие варианты, PopupWindow например). UPD. А действительно, Вы правы. Добавил стиль: В colors.xml #55000000 В таком случае получился результат: Можно и android:alpha="0.5" в разметку добавить. Но по жизненному циклу не вызвался onStop у первой Activity. Логи: E/onPause: onPause E/onCreate2: onCreate2 E/onResume2: onResume2 При повороте экрана: E/onPause2: onPause2 E/onStop2: onStop2 E/onDestroy2: onDestroy2 E/onCreate2: onCreate2 E/onResume2: onResume2 E/onStop: onStop E/onDestroy: onDestroy E/onCreate: onCreate E/onResume: onResume E/onPause: onPause

    Свой toolbar для каждого Fragment'a

    #android #android_fragment

    
    Использую несколько фрагментов, для которых есть отдельный тулбар. При добавлении
    тулбара подсвечивается в студии ошибка "activity.getSupportActionBar.setTitle() may
    produce java.nullpointerexeption". При этом фрагмент грузится, но все действия залипают,
    на другие фрагменты он не переходит. Прошу подсказать в чем ошибка? 
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_three,container,false);
        Toolbar profile_toolbar = (Toolbar)view.findViewById(R.id.profile_toolbar);
        AppCompatActivity activity = (AppCompatActivity)getActivity();
        activity.getSupportActionBar().setTitle("dgdfg");
    return view;
    }
    
    
    UPD. Ошибка крылась в использовании FragmentTabHost, почему-то вид с фрагментом залипал
    на фрагменте с использование тулбара. Пришлось заменить FragmentTabHost на TabHost
        
    


    Ответы

    Ответ 1



    Это не ошибка, а предупреждение Android Studio т.к. при определенных условиях метод getSupportActionBar() может вернуть null и вот тогда уже случится NullPointerException в вашем приложении. Чтобы это исключить, достаточно выполнить проверку на null. Тогда и студия перестанет пугать этим сообщением. ActionBar actionBar = activity.getSupportActionBar(); if(actionBar!= null) { //какой то код } Из-за этого скорей всего и залипают ваши фрагменты, т.к. вы только нашли ToolBar, но не установили его, потому getSupportActionBar() возвращает null. Попробуйте сделать так: @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_three,container,false); Toolbar profile_toolbar = (Toolbar)view.findViewById(R.id.profile_toolbar); AppCompatActivity activity = (AppCompatActivity)getActivity(); activity.setSupportActionBar(profile_toolbar); ActionBar actionBar = activity.getSupportActionBar(); if(actionBar!= null) { actionBar.setTitle("dgdfg"); } return view; }

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

    #java

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


    Ответы

    Ответ 1



    Есть такой термин "Метапрограммирование". Определение из википедии: "вид программирования, связанный с созданием программ, которые порождают другие программы как результат своей работы(в частности, на стадии компиляции их исходного кода), либо программ, которые меняют себя во время выполнения (самомодифицирующийся код)." Первое позволяет получать программы при меньших затратах времени и усилий на кодирование, чем если бы программист писал их вручную целиком, второе позволяет улучшить свойства кода (размер и быстродействие). https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%B0%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5 А вот статья про метапрограммирование конкретно на Java: https://habrahabr.ru/post/91239/ Почитайте и погуглите еще материалы про метапрограммирование, думаю, что что-то интересное для себя найдете.

    Ответ 2



    Есть еще интересная техника изменения логики программы на лету называется аспекты, программирование с помощью аспектов называется аспектно-ориентированным программированием.

    Узнать относительный адрес внутри проекции PE-файла

    #cpp #winapi #pe

    
    Есть один известный крэкми. После его изучения оказывается, что для его взлома достаточно
    пропатчить два байта по адресу 40138B (забить условный переход NOP'ами) и два байта
    по адресу 401243 (прописать там безусловный переход). Я хочу написать программу, которая
    делает это автоматически.
    
    #include 
    #include 
    #include 
    #include 
    
    enum {OK, CANT_OPEN};
    
    int patch (TCHAR* fname)
    {
        char first_patch[2]  = {0x90, 0x90};    // NOP NOP
        char second_patch[2] = {0xEB, 0x07};    // JMP 40124C
        HANDLE hFile = CreateFile(fname,
                                  FILE_ALL_ACCESS, NULL,
                                  NULL, OPEN_EXISTING,
                                  FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE)
            return CANT_OPEN;
    
        int SizeFile  = GetFileSize(hFile, NULL);
        HANDLE MhFile = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, SizeFile, 0);
        HANDLE View   = MapViewOfFile(MhFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    
        UnmapViewOfFile(View);
        CloseHandle(hFile);
        CloseHandle(MhFile);
        return OK;
    }
    
    int main (int argc, char *argv[])
    {
        TCHAR* default_fname = "CRACKME.EXE";
    
        if (argc > 1)
        {
            default_fname = argv[1];
        }
    
        patch(default_fname);
    
        std::cout << default_fname << std::endl;
        return 0;
    }
    
    
    Я спроецировал исполняемый файл в адресное пространство процесса и получил адрес
    этой проекции. Теперь надо пропатчить этот образ, после чего процедура UnmapViewOfFile
    сохранит изменения на диск.
    
    Как в этой проекции найти адреса типа 40138B и 401243? Где можно посмотреть теорию
    и примеры по редактированию PE-файлов?
    
    Далее пишу хрень, можно не читать.
    Успешно напечатал сигнатуру MZ, это значит, что при помощи View можно заполнять структуры
    заголовков, используя, возможно, для выравнивания макросы Криса Касперски.
    
    char M = *((char *) View);
    char Z = *((char *) View + 1);
    std::cout << M << Z << std::endl;
    
    
    Проверка того, что заголовок дос успешно загружен. Потом добавлю код для отлавливания
    возможных ошибок.
    
    unsigned myRVAtoRAW(HANDLE pe_image, unsigned rva)
    {
        IMAGE_DOS_HEADER dos_header;
        std::memcpy(reinterpret_cast(&dos_header), pe_image, sizeof(dos_header));
    
        std::cout << (dos_header.e_magic == 'ZM') << std::endl;
        return 0;
    }
    
        
    


    Ответы

    Ответ 1



    Можно пойти двумя путями: Разобраться и написать самому. Тогда рекомендую почитать статью: Разработка функций RvaToRaw и RawToRva. Либо воспользоваться функций из известной dbghelp.dll. Я бы посоветовал разобраться, благо это не сложно. Также следует отметить знаменитую статью Об упаковщиках в последний раз: Часть первая - теоретическая

    Ответ 2



    Что касаемо патчинга: int main() { HWND hWnd = FindWindow(0, "Calculator"); if(hWnd == 0){ MessageBox(0, "Error cannot find window.", "Error", MB_OK|MB_ICONERROR); } else { DWORD proccess_ID; GetWindowThreadProcessId(hWnd, &proccess_ID); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proccess_ID); if(!hProcess){ MessageBox(0, "Could not open the process!", "Error!", MB_OK|MB_ICONERROR); } else { DWORD newdatasize = sizeof(newdata); if(WriteProcessMemory(hProcess, (LPVOID)0x40138B , "0x90", newdatasize, NULL)){ MessageBox(NULL, "WriteProcessMemory worked.", "Success", MB_OK + MB_ICONINFORMATION); } else { MessageBox(NULL, "Error cannot WriteProcessMemory!", "Error", MB_OK + MB_ICONERROR); } CloseHandle(hProcess); } } return 0; } Адреса искать по паттерну(уникальной сигнатуре), сделать ее можно в любом отладчике

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

    #java #android #activity #android_asynctask

    
    Есть окно с элементом spinner, который должен заполняться значениями из базы данных
    MS SQL. Для связи с БД использую jtds 1.2.8 в асинхронных запросах, но никак не выходит
    найти способ чтобы переправить данные результата запроса в активность, которая послала
    асинхронный запрос. Как реализовать заполнение spinner после выполнения запроса?
    
    UA.java
    
    public class UA extends AppCompatActivity{
    
    private QueryItem Item = new QueryItem();
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ua);
        Item.setId(Search_Page.id_intent);
        Search_Page.id_intent = 0;
        String[] query = new String[2];
        query[1] = "get_dish_links";
        query[0] = "EXEC " + query[1] + "" + Item.getId();
        new AsyncRequest().execute(query);
        final SeekBar seekbar = (SeekBar) findViewById(R.id.seekBar);
    }
    
    public void onClick(View view) {
        final Spinner spinner = (Spinner)findViewById(R.id.spinner);
        //Item.setUnit(spinner);
    }
    
    public void fill_spinner(List links){
        final Spinner spinner = (Spinner)findViewById(R.id.spinner);
        ArrayAdapter possible_units = new ArrayAdapter(this, android.R.layout.simple_list_item_1,
    links);
        spinner.setAdapter(possible_units);
        spinner.setSelection(0);
        possible_units.notifyDataSetChanged();
    }
    
    
    AsyncRequest.java
    
    public final class AsyncRequest extends AsyncTask {
    
        public final static String MSSQL_DB = "jdbc:jtds:sqlserver://localhost:1433;
    DatabaseName=Lazycook";
        public final static String MSSQL_LOGIN = "lazyuser";
        public final static String MSSQL_PASS = "12344321";
        public final static JSONConverter conv = new JSONConverter();
        public String action;
    
        @Override
        protected JSONArray doInBackground(String[] query) {
            JSONArray resultSet = new JSONArray();
            action = query[1];
            try {
                Class.forName("net.sourceforge.jtds.jdbc.Driver");
                Connection con = null;
                Statement st = null;
                ResultSet rs = null;
                try {
                    con = DriverManager.getConnection(MSSQL_DB, MSSQL_LOGIN, MSSQL_PASS);
                    if (con != null) {
                        st = con.createStatement();
                        rs = st.executeQuery(query[0]);
                        if (rs != null) {
                            int columnCount = rs.getMetaData().getColumnCount();
                            // Сохранение данных в JSONArray
                            while (rs.next()) {
                                JSONObject rowObject = new JSONObject();
                                for (int i = 1; i <= columnCount; i++) {
                                    rowObject.put(rs.getMetaData().getColumnName(i),
    (rs.getString(i) != null) ? rs.getString(i) : "");
                                }
                                resultSet.put(rowObject);
                            }
                        }
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (rs != null) rs.close();
                        if (st != null) st.close();
                        if (con != null) con.close();
                    } catch (SQLException e) {
                        throw new RuntimeException(e.getMessage());
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return resultSet;
        }
    
        @Override
        protected void onPostExecute(JSONArray result) {
            switch (action){
                case "get_dish_links" : {
                    List links = conv.JSONtoLink(result);
                    // вот здесь думал использовать вызов fill_spinner
                    // нужного объекта, передав ему результат
                }
    
    
            }
        }
    
    
    }
        
    


    Ответы

    Ответ 1



    Создайте интерфейс public interface MyInterface { void doSmth(JSONArray result); } Реализуйте его в активити public class UA extends AppCompatActivity implements MyInterface{ @Override public void doSmth(JSONArray result) { System.out.println("вызван doSmth в Активити"); //вот и ваш результат из задачи в актвити } ... } Передавайте его в задачу через конструктор и вызывайте его метод, передавая туда результат из onPostExecute: public final class AsyncRequest extends AsyncTask { MyInterface myInterface; public AsyncRequest(MyInterface myInterface){ this.myInterface = myInterface; } @Override protected void onPostExecute(JSONArray result) { System.out.println("вызван onPostExecute"); myInterface.doSmth(result); } } В активити запускайте так: new AsyncRequest(UA.this).execute(query);

    Как при помощи метода изменить шрифт у всех activity

    #java #android #textview #typeface

    
    String fontPath ="fonts/smartoff.net_verdana.ttf";
        int[] array_id_font=new int[]{R.id.umivanie_text,R.id.eda_text,R.id.son_text};
     Typeface verdana;
    
    
    Хочу при помощи метода менять шрифт во всех активностях.
    Делаю так:
    
     public void setFont()
        {
              verdana = Typeface.createFromAsset(getAssets(), fontPath);
           for (int i=0;i


    Ответы

    Ответ 1



    создать базовый класс для активити public class BaseActivity extends AppCompatActivity { protected String fontPath ="fonts/smartoff.net_verdana.ttf"; private Typeface typeface; protected int[] getTextViewsResIds() { return new int[0]; } public void setFont() { typeface = Typeface.createFromAsset(getAssets(), fontPath); for (int i = 0; i

    Показатели производительности и “здоровья ” СУБД postgres

    #postgresql

    
    Подскажите какие показатели производительности и здоровья БД стоит мониторить в postgresql?
        
    


    Ответы

    Ответ 1



    В первую очередь конечно нужно мониторить основные параметры ОС. Загрузка ЦПУ, Память, Своп, Диски. В случае с Линуксом помогут утилиты (top, htop, iostat, free) Далее нужно смотреть какие запросы отнимают наибольшее количество процессорного времени, и конечно же стараться их оптимизировать. В этом помогут pg_stat_statements, powa (http://dalibo.github.io/powa/) Далее очень важно мониторить статистику таблиц такие как index_scan, sequential_scan и локи (в идеале должно быть меньше seq_scan-ов). Эти данные можно снимать с таблиц pg_stat_user_tables, pg_locks. Если используется connection polling то нужно следить за количеством соединений. Ну и по хорошему нужно прикрутить мониторинг фреймворк для сборки и хранения статистики. Лично я использую sensu (http_s://sensuapp.org/ ) уже с готовыми коммьюнити плагинами (http_s://github.com/sensu-plugins/sensu-plugins-postgres). Ну и конечно же powa. В случае проблем можно конечно еще много что посмотреть, но вот это основные параметры и в основном их хватает.

    Регулярное выражение, которое проверяет чётность количества появлений символа в строке

    #регулярные_выражения

    
    Допустим, есть строка |дядя |Вася |23 . Нужно, чтобы регулярное выражение нашло совпадение
    только в том случае, если символов | будет чётное количество. Можно ли такое сделать
    чисто регулярным выражением, без привлечения средств языков программирования?
        
    


    Ответы

    Ответ 1



    Можно, вот: ^(([^|]*\|){2})*[^|]*$

    Python. Вывод текста по середине терминала

    #python #python_3x #текст #форматирование #терминал

    
    Как можно вывести текст в центре экрана терминала, используя shutil.get_terminal_size().columns
    и shutil.get_terminal_size().lines?
    
    
        
    


    Ответы

    Ответ 1



    Если текст уже разбит на строки, то достаточно просто отформатировать: >>> import shutil >>> lines = ['String right here', 'And here', 'Here', 'A-a-a-and here'] >>> width = shutil.get_terminal_size().columns >>> position = (width - max(map(len, lines))) // 2 >>> for line in lines: # left justtified ... print(' '*position + line) ... String right here And here Here A-a-a-and here >>> for line in lines: # right justified ... print(line.rjust(width // 2)) ... String right here And here Here A-a-a-and here >>> for line in lines: # center ... print(line.center(width)) ... String right here And here Here A-a-a-and here

    Ответ 2



    Если хочется в произвольном месте экрана в терминале печатать, то можно blessings модуль использовать: #!/usr/bin/env python from blessings import Terminal # $ pip install blessings lines = ['String right here', 'And here', 'Here', 'A-a-a-and here'] term = Terminal() with term.hidden_cursor(), term.fullscreen(): for i, line in enumerate(lines): x = (term.width - max(map(len, lines))) // 2 y = (term.height - len(lines)) // 2 + i with term.location(x, y): print(term.bold_white_on_black(line)) with term.location(0, term.height - 1): input('press to exit..') Терминал выглядит так: String right here And here Here A-a-a-and here press to exit.. В этом случае, содержимое терминала на время исполнения программы очищается—при выходе из программы терминал восстанавливается. Совместно с colorama модулем, некоторые возможности могут работать также и на Windows. Для забавы можно asciimatics модуль попробовать: #!/usr/bin/env python from asciimatics.effects import Print # $ pip install asciimatics from asciimatics.renderers import FigletText, SpeechBubble, Rainbow from asciimatics.scene import Scene from asciimatics.screen import Screen from asciimatics.exceptions import ResizeScreenError def demo(screen): lines = ['String right here', 'And here', 'Here', 'A-a-a-and here'] renderers = [Rainbow(screen, FigletText(line, font='small')) for line in lines] x = (screen.width - max(r.max_width for r in renderers)) // 2 H = max(r.max_height for r in renderers) - 1 # text height effects = [Print(screen, renderer, y=(screen.height - H * len(renderers)) // 2 + i * H, x=x) for i, renderer in enumerate(renderers)] effects.append(Print(screen, SpeechBubble("Press X to exit"), screen.height - 5, speed=1, transparent=False, start_frame=100)) screen.play([Scene(effects, -1)], stop_on_resize=True) if __name__ == "__main__": while True: try: Screen.wrapper(demo) except ResizeScreenError: continue else: break На другие доступные эффекты можно в samples папке посмотреть.

    Переход на PostgreSQL

    #php #postgresql #symfony2

    
    В общем есть сайт на symfony меняю драйвер на pdo_pgsql, фэйлится фиксура которая
    создает юзера default. 
    
    
      INSERT INTO user (Usr_Username, Usr_Email,
      
      ERROR:  syntax error at or near "user"
    
    
    В общем система хочет чтобы user был в кавычках так как есть такая же переменная 
    
    Так написана фикстура
    
     $entity = new User();
                $entity->setUsername("root");
                $manager->persist($entity);
     $entity
                ->setPassword("bla")
                ->setEmail("bla@gmail.com")
                ->setFirst("root")
                ->setLast("root")
                ->setOfficePhone("1")
                ->setMobilePhone("1")
                ->setTimeZone("11")
                ->setEnabled(true);
     $manager->flush();
    
    
    В общем как бы это можно было исправить?
        
    


    Ответы

    Ответ 1



    В общем оставлю для себя заметку, в User Entity нужно название таблицы написать в 3х кавычках /** * @ORM\Table(name="""user""") */ Дальше по аналогии в общем, если есть проблемы, у меня была только в этом месте.

    Ответ 2



    user - ключевое слово в Postgresql, на мой взгляд, лучше было бы использовать иное название таблицы или префикс. /** * @ORM\Table(name="users") */

    Моргающее в панели задач окно

    #c_sharp #wpf #xaml #mvvm

    
    Подскажите пожалуйста как заставить окно моргать в панели задач? Ну так часто делают
    типа какое то событие в окне произошло, а оно свернуто и вот такое извещение.
    
    @VladD хз я может что то не так делаю, но у меня никак не хочет это работать. Я ставил
    точку останова у меня при попытке создать экземпляр WindowInteropHelper выходит из
    функции вообще. Тестирую вот так:
    
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var t = new Timer(5000);
            t.Elapsed += Elapsed;
            t.Start();
        }
    
        [DllImport("user32.dll")]
        public static extern int FlashWindow(IntPtr Hwnd, bool Revert);
    
        private void Elapsed(object sender, ElapsedEventArgs e)
        {
            var hwnd = new WindowInteropHelper(this).Handle;
            FlashWindow(hwnd, true);
        }
    }
    
        
    


    Ответы

    Ответ 1



    Попробуйте так: [DllImport("user32.dll")] public static extern int FlashWindow(IntPtr Hwnd, bool Revert); // ... var hwnd = new WindowInteropHelper(window).Handle; FlashWindow(hwnd, true); Вызывать эту функцию на таймере не стоит, т. к. он доставляет сообщения в непонятно какой поток. Используйте DispatcherTimer, он выполняет события в главном потоке: var dt = new DispatcherTimer(); dt.Tick += (s, e) => { dt.Stop(); var hwnd = new WindowInteropHelper(this).Handle; FlashWindow(hwnd, true); }; dt.Interval = TimeSpan.FromSeconds(5); dt.Start();

    Шаблонная хэш-функция

    #cpp #хеширование

    
    Допустим, мне нужно сделать некий шаблонный контейнер Map на хэш-таблице. Контейнер,
    естественно, может принимать ключем значение любых типов  - как, в таком случае, написать
    хэш-функцию? Как привести произвольный тип T (для которого может быть не перегружен
    оператор приведения) к целочисленному типу? 
    Вроде как должен помочь reinterpret_cast, который приводит к указателю, но конструкция вида
    
    reinterpret_cast  (key);
    
    
    Отказывается компилироваться, когда key имеет не-целочисленный тип.
    
    Если же приводить указатель к указателю (как в примере на msdn)
    
    reinterpret_cast  (&key);
    
    
    то теряется смысл хэш таблицы - поиск по ней не будет работать, поскольку ключ с
    идентичным значением будет иметь другой адрес, и результат хэш-функции будет тоже другой.
    
    Можно ли как-то насильно интерпретировать байты произвольного объекта в памяти как
    целочисленный тип?
    Вообще, какое решение будет правильным? Как эта проблема решена в std::unordered_map
    или QMap?
        
    


    Ответы

    Ответ 1



    Классы наподобие unordered_set вычисляют хеш не сами, а используют std::hash (а также дают возможность пользователю указать свою реализацию хеширования, если он недоволен стандартной, или если её не существует). std::hash, в свою очередь, тоже не пользуется никакой особой магией, а просто имеет шаблонные специализации для примитивных типов, строк и указателей (обычных и «умных»). Мне кажется, вам стоит не изобретать велосипед, а воспользоваться той же идеей. А ещё проще, просто используйте std::hash. Поверьте, в написании контейнера есть много сложностей помимо этой. Таким образом, просто используйте size_t hash_value = std::hash()(t);

    Способы мультиязычности программ на Python?

    #python #python_2x #локализация

    
    При разработке приложения с поддержкой нескольких языковых локализаций, я использую
    файл, в котором храню все строковые данные программы. Раньше я обходился простым -
    
    exec(open("файл/языковой/локолизации").read())
    
    
    инициализируя таким образом все переменные со строковыми значениями в основной код
    приложения.
    
    Сейчас exec как-то не хочется использовать. Я приспособил для этих целей модуль ConfigParser.
    Сейчас это выглядит вот так:
    
    from ConfigParser import ConfigParser
    
    
    config = ConfigParser()
    config.read("locale.ini")
    language = config.get("LOCALE", "language")  # устанавливаем локаль
    section = language.upper()
    config.read("{}.ini".format(language))  # читаем файл строковых данных
    
    # Таким образом я получаю строковые значения для приложеничя.
    program_title = config.get(section, "program_title")
    
    
    locale.ini
    (файл текущей локализации приложения):
    
    [LOCALE]
    language = english
    
    
    english.ini
    (файл со строковыми данными):
    
    [ENGLISH]
    program_title = Clean Master
    
    
    Теперь, скажем, если мне нужно сменить язык на русский, я добавляю файл russian.ini
    со строками русской локализации, а в файле locale.ini устанавливаю значение "language"
    в "russian".
    
    Получается следующее:
    
    locale.ini 
    (файл текущей локализации приложения):
    
    [LOCALE]
    language = russian
    
    
    english.ini 
    (файл со строковыми данными):
    
    [RUSSIAN]
    program_title = Мастер Очистки
    
    
    Может быть в Python есть другие варианты вышеописанного велосипеда?
        
    


    Ответы

    Ответ 1



    Вообще, есть довольно стандартный вариант - использовать библиотеку gettext, для которой есть биндинги в том числе и для Python (причем, в стандартной библиотеке, не исключено, что это реализация gettext на Python). Принцип работы примерно такой: все строки, подлежащие переводу оборачиваются в вызов специальной функции _(). Далее, программа обрабатывается утилитой pygettext, вытаскивающей все переводимые строки, в результате получается файл .pot (шаблон перевода), в который в дальнейшем можно добавить перевод. Это текстовый файл с относительно простой внутренней структурой, его можно редактировать чем-то блокнотоподобным, но есть и специализированные утилиты, например, poedit, также его можно загрузить на какой-нибудь из сервисов онлайн-перевода типа crowdin.com или transifex.com, и редактировать там совместно с другими переводчиками. Из файла .pot получается файл .po (по сути тот же .pot, но с заполненным переводом строк на нужный язык), который потом компилируется в файл .mo (бинарный файл, хотя тоже с довольно простой внутренней структурой) с помощью утилиты msgfmt из пакета gettext или утилиты msgfmt.py из пакета Python. Далее, перевод импортируется в переводимую программу при помощи команды gettext.install('mary', './locale', unicode=True) (пример отсюда, реальные параметры могут быть другими). Парочка нагугленных руководств: Международные ягнята / Хабрахабр Локализация Python-скриптов при помощи gettext Если потребуется редактировать перевод онлайн совместно с другими переводчиками, могу сказать, что упомянутые выше crowdin и transifex бесплатны для Opensource продуктов, но в crowdin с этим довольно строго, в то время как в transifex достаточно того, чтобы перевод был доступен публично, и в настройках проекта была ссылка на исходный код. При этом субъективно у crowdin более дружелюбный интерфейс.

    Ввод данных в С. Не определяется GetString() из cs50

    #c #gcc #make #cs50

    
    Почему у меня не определяется string s = GetString();?
    
    hell.c
    
    #include 
    #include 
    
    int main(void)
    {
        printf("State our name: ");
        string s = GetString();
        printf("hello, %s\n", s);
    }
    
    
    
      cc hell.c -o hell
    
    /tmp/ccHZXs2m.o: In function `main'
    hell.c:(.text+0x16): undefined reference to `GetString'
    collect2: error: ld returned 1 exit status
    make: *** [hell] Error 1
    
    
        
    


    Ответы

    Ответ 1



    Почему бы тебе не воспользоваться методом scanf() для чтения с консоли? int main(void) { string name; printf("Введите ваше имя"); scanf("%s", name); printf("Привет, %s\n!", name); return 0; }

    Ответ 2



    Нужно скомпилировать и слинковать с файлом cs50.c cc -c help.c -o help.o cc -c cs50.c -o cs50.c cc -o help help.o cs50.o

    Ответ 3



    Потому что у тебя нету такой функции GetString(). Добавь например выше.. string GetString(void) { return "test"; }

    Ответ 4



    Могу предположить, что у вас слетели или не были настроены переменные среды CFLAGS и LDLIBS. Попробуйте создать в этой же папке файл с названием makefile и поместить в него данные строки: CC=clang CFLAGS=-ggdb3 -O0 -std=c99 -Wall -Werror LDLIBS=-lcs50 -lm После чего просто вызовите make: make hell for ABC ;)

    Ответ 5



    Потому что cs50 это библиотека курса гарварда cs50. А у Вас она не установлена. Запустите в их удаленной линуксовой среде и там подцепится.

    Ответ 6



    Используйте консоль в редакторе (отдельная иконка рядом с gedit). Тогда независимо от того, подключите ли вы библиотеку string.h или нет, функция GetString сработает.

    Ответ 7



    .h файл только декларирует список функций, для их использования в программу должен быть вкомпилирован их код находящийся скорее всего в .cшных файлах (но может оказаться в .asm .haskell ... .lib .dll .so .a) в самом простейшем случае у вас где-то должен лежать файл cs50.c, который тоже нужно скомпилировать: gcc -o ./hello[.exe] hello.c cs50/lib/src/cs50.c PS: описание принципа использования модулей, раздельной компиляции и использования ключевого слова static неплохо объяснено в курсе Евгения Линского

    Ответ 8



    В окружении CS50 на c9.io начиная с 2016 эту функцию переименовали в: get_string() Используйте её или найдите более свежие видео-лекции.

    Ответ 9



    Потому, что ты не читал нормально начало к заданиям - ТАМ ТАК ЖИРНО написано ЦТ Дополнительные материалы reference.cs50.net/ — разъяснение функций библиотек, используемых во время обучения. На английском. http://computer.howstuffworks.com/c.htm стр. 11 – 14 и 39 И вот если пройти в разъяснение функций библиотек - и поискать поиском string - то будет чудо, выяснится что надо подключать библиотеку string.h - а она не прописана в cs50 - ребята не на все делали костыль! Зачем костыль на библиотеку готовую?

    Как правильно работать с экземпляром класса на двух страницах? C#/UWP

    #c_sharp #uwp

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


    Ответы

    Ответ 1



    Я нашел решение, воспользовавшись передачей объекта класса как параметра во время перехода на другую страницу. Frame.Navigate(typeof(Page), DS); Где DS это то, что мы хотим передать, а Page та страница на которую переходим.

    Регулярные выражения. Поиск слов по набору букв

    #регулярные_выражения #поиск

    
    Помогите составить регулярное выражение для поиска слов только по определённому набору
    букв. Т.е. Есть слово "зажигалка" в результате в искомых словах могут использоваться
    только буквы из этого слова и в том же количестве.
    
    Нужно найти все слова, состоящие из этих букв. Т.е. "глаз", "газ", "галка" и т.д.
    В общем, как в игре "Слова из слова"
        
    


    Ответы

    Ответ 1



    Если речь о перестановке букв, то: ^(?=.*з)(?=.*а.*а.*а)(?=.*ж)(?=.*и)(?=.*г)(?=.*л)(?=.*к)[зажиглк]{9}$ Если речь просто о подмножестве, то так: ^(?!.*з.*з)(?!.*а.*а.*а.*а)(?!.*ж.*ж)(?!.*и.*и)(?!.*г.*г)(?!.*л.*л)(?!.*к.*к)[зажиглк]+$

    Ответ 2



    условие «в том количестве» (точнее, как понятно из комментария к другому ответу, «в количестве, не большем заданного») с помощью известных мне стандартов регулярных выражений выполнить невозможно. если, конечно пользоваться только движком регулярных выражений, без дополнительного кода (см. ниже). если условие про количество опустить и если слова идут по одному в строке, то, например, так: $ echo -e 'глаз\nгаз\nмозг\nгалка' | grep '^[зажигалка]\+$' глаз газ галка под дополнительным кодом я имею ввиду: преобразование искомой строки в отсортированный список букв с квантификатором количества для букв, встречающихся более одного раза. например: зажигалка преобразовать в ^а{1,3}?г?ж?з?и?к?л?$ (или чуть по-другому, только с квантификаторами количества и без квантификатора ?: ^а{0,3}г{0,1}ж{0,1}з{0,1}и{0,1}к{0,1}л{0,1}$) преобразование слова на входе в отсортированный список букв. например: мозг → гзмо, глаз → агзл, заза → аазз. если такие преобразования выполнить, то движок, понимающий bre (basic regular expressions), вполне справится: $ echo -e 'гзмо\nагзл\nаазз' | grep '^а\{1,3\}\?г\?ж\?з\?и\?к\?л\?$' агзл пример выполнения описанных преобразований средствами posix-утилит: преобразование исходного слова в регулярное выражение bre: $ echo 'зажигалка' | sed 's/./&\n/g;s/.$//' | sort | uniq -c | \ sed -r 's/\s*([0-9]+)\s*(.*)/\2\\{0,\1\\}/;1s/^/^/;$s/$/$/' | \ sed ':a;N;s/\n//;ta' ^а\{0,3\}г\{0,1\}ж\{0,1\}з\{0,1\}и\{0,1\}к\{0,1\}л\{0,1\}$ сортировка букв: $ echo 'глаз' | sed 's/./&\n/g;s/.$//' | sort | sed ':a;N;s/\n//;ta' агзл обновление: в своём ответе Qwertiy продемонстрировал, что без второго из описанных мною преобразований можно обойтись, если использовать стандарт pcre (perl compatible regular expressions), в котором есть функция предпросмотра (look-ahead). первое преобразование в таком случае может быть сделано средствами posix-утилит, например, так: $ w='зажигалка'; echo $w | sed 's/./&\n/g;s/.$//' | sort | uniq -c | \ sed -r 's/^\s*([0-9]+)\s*(.)$/echo \\(?!\\(.*\2\\)\\{$((\1+1))\\}\\)/e;1s/^/^/;$s/$/['$w']+$/' | \ sed ':a;N;s/\n//;ta' ^(?!(.*а){4})(?!(.*г){2})(?!(.*ж){2})(?!(.*з){2})(?!(.*и){2})(?!(.*к){2})(?!(.*л){2})[зажигалка]+$ полученное регулярное выражение работает корректно: $ echo -e 'мозг\nглаз\nзаза' | grep -P '^(?!(.*а){4})(?!(.*г){2})(?!(.*ж){2})(?!(.*з){2})(?!(.*и){2})(?!(.*к){2})(?!(.*л){2})[зажигалка]+$' глаз

    Библиотеки для графиков

    #java #android

    
    Есть ли какие-нибудь библиотеки для работы с графиками на Android?
        
    


    Ответы

    Ответ 1



    Open source библиотека Graph View. Сайт | GitHub MPAndroidChart - open source, поддерживаем множество видов графиков. GitHub Androidplot - open source, также поддерживает множество видов графиков. Сайт | GitHub | Bitbucket HelloCharts. GitHub Платная библиотека Chart. Сайт Платная библиотека aiCharts. Сайт

    Проблема при установке Oracle JDK на Debian

    #debian #java

    
    Возникла ошибка при установке Oracle JDK на Debian 8 Jessie:
    
    rostislav@Rostislav-PC:~/Загрузки$ sudo dpkg -i jdk1.8.0-91_1.8.091-1_amd64.deb
    Выбор ранее не выбранного пакета jdk1.8.0-91.
    (Чтение базы данных … на данный момент установлено 119167 файлов и каталогов.)
    Подготовка к распаковке jdk1.8.0-91_1.8.091-1_amd64.deb …
    Распаковывается jdk1.8.0-91 (1.8.091-1) …
    Настраивается пакет jdk1.8.0-91 (1.8.091-1) …
    Unpacking JAR files...
        tools.jar...
        plugin.jar...
        javaws.jar...
        deploy.jar...
        rt.jar...
        jsse.jar...
        charsets.jar...
        localedata.jar...
        jfxrt.jar...
    /var/lib/dpkg/info/jdk1.8.0-91.postinst: line 641: /usr/sbin/alternatives: Нет такого
    файла или каталога
    /var/lib/dpkg/info/jdk1.8.0-91.postinst: line 653: /usr/sbin/alternatives: Нет такого
    файла или каталога
    dpkg: ошибка при обработке пакета jdk1.8.0-91 (--install):
     подпроцесс установлен сценарий post-installation возвратил код ошибки 127
    При обработке следующих пакетов произошли ошибки:
     jdk1.8.0-91
    
    
    Процесс установки был таким (инструкцию нашел тут):
    
    
    Скачал официальную версию JDK с сайта Oracle.
    Установил alien из официального репозитория.
    Перегнал .rpm в .deb командой sudo alien --scripts
    jdk-8u91-linux-x64.rpm
    Установил .deb пакет командой sudo dpkg -i
    jdk1.8.0-91_1.8.091-1_amd64.deb, во время чего и возникла ошибка
    
    
    Из-за чего произошла ошибка и как ее исправить?
    
    
    
    UPD_0 (kvm): При попытке удалить JDK: 
    
    rostislav@Rostislav-PC:~$ dpkg --remove --force-remove-reinstreq jdk1.8.0-91
    dpkg: ошибка: запрошенная операция требует привилегий суперпользователя
    rostislav@Rostislav-PC:~$ sudo dpkg --remove --force-remove-reinstreq jdk1.8.0-91
    (Чтение базы данных … на данный момент установлено 116630 файлов и каталогов.)
    Удаляется jdk1.8.0-91 (1.8.091-1) …
    /var/lib/dpkg/info/jdk1.8.0-91.postrm: line 586: /usr/sbin/alternatives: Нет такого
    файла или каталога
    /var/lib/dpkg/info/jdk1.8.0-91.postrm: line 598: /usr/sbin/alternatives: Нет такого
    файла или каталога
    dpkg: ошибка при обработке пакета jdk1.8.0-91 (--remove):
     подпроцесс установлен сценарий post-removal возвратил код ошибки 127
    При обработке следующих пакетов произошли ошибки:
     jdk1.8.0-91
    rostislav@Rostislav-PC:~$ sudo dpkg --purge --force-remove-reinstreq jdk1.8.0-91(Чтение
    базы данных … на данный момент установлено 116630 файлов и каталогов.)
    Удаляется jdk1.8.0-91 (1.8.091-1) …
    /var/lib/dpkg/info/jdk1.8.0-91.postrm: line 586: /usr/sbin/alternatives: Нет такого
    файла или каталога
    /var/lib/dpkg/info/jdk1.8.0-91.postrm: line 598: /usr/sbin/alternatives: Нет такого
    файла или каталога
    dpkg: ошибка при обработке пакета jdk1.8.0-91 (--purge):
     подпроцесс установлен сценарий post-removal возвратил код ошибки 127
    При обработке следующих пакетов произошли ошибки:
     jdk1.8.0-91
    
        
    


    Ответы

    Ответ 1



    Установить JDK из rpm это целое приключение, лучше воспользоваться java-package. Убедитесь, что подключены contrib архивы в /etc/apt/sources.list: deb jessie main contrib non-free Установите java-package: apt install java-package. Скачайте JDK с сайта Oracle, но не rpm, а tar.gz. Запустите создание deb-пакета JDK: fakeroot make-jpkg jdk-8u91-linux-x64.tar.gz Возможно, появятся ошибки о неудовлетворенных зависимостях, установите пакеты, о которых говорится в ошибках, затем заново запустите создание пакета. В моем случае было: sudo apt install libgl1-mesa-glx libxslt1.1 libxtst6 libxxf86vm1 Удалите старый некорректно установленный пакет JDK. Установите созданный пакет sudo dpkg -i oracle-java8-jdk_8u91_amd64.deb UPD1. Если снести кривой пакет JDK через apt remove jdk1.8.0-91 не удается, удаляем его принудительно: sudo dpkg --remove --force-remove-reinstreq jdk1.8.0-91 sudo dpkg --purge --force-remove-reinstreq jdk1.8.0-91 UPD2. Создайте симлинк sudo ln -s /usr/sbin/update-alternatives /usr/sbin/alternatives и еще раз попробуйте снести. Потом удалите симлинк.