среда, 29 февраля 2012 г.

engmod-2.0.0

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

UPD
Пример данных для обработки и результатов расчета - https://sites.google.com/site/pa2311/engmod.

воскресенье, 26 февраля 2012 г.

Релиз r49-12.02

  • libtoxic v6.3.0
  • cr49 v1.0.2
  • Qr49 v3.2.0
Изменения:
  1. Увеличен размер шрифта в окне отчетов, размер при выводе на печать и генерации PDF оставлен прежним;
  2. Автоматическое создание файла конфигурации с параметрами по умолчанию в случае его отсутствия (ищется в каталоге программы и каталоге пользователя);
  3. Исправления во встроенной справке cr49;
  4. Улучшение структуры дерева исходных кодов проекта и упрощение сборки (см. файл README).
Исходный код, а также сборка для ОС на базе GNU/Linux (64 бит) доступна на github.com. Сборка для ОС MS Windows (32 бит) будет доступна позже.

UPD 27.02.2012
На github.com добавлена сборка для ОС MS Windows (32 бит).

вторник, 21 февраля 2012 г.

Релиз biblref-1.0.0

По просьбе товарищей и коллег, написал программу для создания библиографических ссылок. Это первый релиз. Программа уже умеет создавать ссылки для следующих источников:
  • книга;
  • статья;
  • диссертация;
  • автореферат;
  • депонированная рукопись;
  • тезис доклада;
  • патент;
  • авторское свидетельство.
Жду отзывов и, возможно, замечаний )

Исходный код и сборки - традиционно на github.com. Сборка для виндовс будет добавлена завтра.

UPD 22.02.2012
На github.com добавлена сборка для виндовс.

пятница, 17 февраля 2012 г.

Qt. Функционал Undo/Redo для QTableWidget

Решил поделиться своей реализацией функционала Отмена/Повтор для приложения, использующего несколько QTableWidget-ов.
undoredotable.h
#ifndef UNDOREDOTABLE_H
#define UNDOREDOTABLE_H

#include <QVector>
#include <QString>
#include <QTableWidget>

class UndoRedoTable {

public:

    UndoRedoTable(QTableWidget *);
    virtual ~UndoRedoTable();

    void saveState();
    void undoTable();
    void redoTable();
    ptrdiff_t undoTableNumber() const;
    ptrdiff_t redoTableNumber() const;
    void freeMemory();

private:

    QTableWidget *table;
    QVector< QVector< QVector<QString> > > data;
    ptrdiff_t position;

};

#endif /* UNDOREDOTABLE_H */
undoredotable.cpp
#include "undoredotable.h"
#include "tablewidgetfunctions.h"

#include <QVector>
#include <QString>
#include <QTableWidget>

UndoRedoTable::UndoRedoTable(QTableWidget *tbl) :
    position(-1) {

    table = tbl;
}

UndoRedoTable::~UndoRedoTable() {
}

void UndoRedoTable::saveState() {

    if ( (data.count() - position) > 1 ) {

        for ( ptrdiff_t i=(data.count()-1); i>position; i-- ) {

            data.remove(i);
        }
    }

    QVector<QString> row;
    QVector< QVector<QString> > matrix;

    for ( ptrdiff_t i=0; i<table->rowCount(); i++ ) {

        for ( ptrdiff_t j=0; j<table->columnCount(); j++ ) {

            row.push_back(table->item(i, j)->text());
        }

        matrix.push_back(row);
        row.clear();
    }

    data.push_back(matrix);
    matrix.clear();

    position++;
}

void UndoRedoTable::undoTable() {

    position--;

    if ( table->rowCount() < data[position].count() ) {

        addRows(table, data[position].count());
    }
    else if ( table->rowCount() > data[position].count() ) {

        table->setRowCount(data[position].count());
    }

    for ( ptrdiff_t i=0; i<data[position].count(); i++ ) {

        for ( ptrdiff_t j=0; j<data[position][i].count(); j++ ) {

            table->item(i, j)->setText(data[position][i][j]);
        }
    }
}

void UndoRedoTable::redoTable() {

    position++;
    position++;

    undoTable();
}

ptrdiff_t UndoRedoTable::undoTableNumber() const {

    return position;
}

ptrdiff_t UndoRedoTable::redoTableNumber() const {

    return data.count() - position - 1;
}

void UndoRedoTable::freeMemory() {

    data.clear();
}

четверг, 16 февраля 2012 г.

std::vector. Освобождение памяти

Собственно решение.
vector<double> v;

// какая-то работа с вектором

// освобождение памяти, занимаемой вектором
v.clear();
vector<double>().swap(v);

C++. Чтение CSV файла в двумерный массив

В качестве примера использования предложенных ранее функций разбивки строки и конвертирования строки в число привожу листинг программы, которая читает данные из файла формата CSV в двумерный массив и выводит полученное на консоль.
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>

using std::string;
using std::vector;
using std::ifstream;
using std::istringstream;
using std::cout;

void splitString(const string &fullstr,
                 vector<string> &elements,
                 const string &delimiter) {

    string::size_type lastpos =
        fullstr.find_first_not_of(delimiter, 0);
    string::size_type pos     =
        fullstr.find_first_of(delimiter, lastpos);

    while ( (string::npos != pos) || (string::npos != lastpos) ) {

        elements.push_back(fullstr.substr(lastpos, pos-lastpos));

        lastpos = fullstr.find_first_not_of(delimiter, pos);
        pos = fullstr.find_first_of(delimiter, lastpos);
    }
}

double stringToDouble(const string &str) {

    istringstream stm;
    double val = 0;

    stm.str(str);
    stm >> val;

    return val;
}

void readData(const string &filename,
              const string &csvdelimiter,
              vector< vector<double> > &sarr) {

    ifstream fin(filename.c_str());

    string s;
    vector<string> selements;
    vector<double> delements;

    while ( !fin.eof() ) {

        getline(fin, s);

        if ( !s.empty() ) {

            splitString(s, selements, csvdelimiter);

            for ( size_t i=0; i<selements.size(); i++ ) {

                delements.
                    push_back(stringToDouble(selements[i]));
            }

            sarr.push_back(delements);
            selements.clear();
            delements.clear();
        }
    }

    fin.close();
}

int main(int argc, char** argv) {

    vector< vector<double> > sarr;
    
    readData("data.csv", ";", sarr);

    for ( size_t i=0; i<sarr.size(); i++ ) {

        for ( size_t j=0; j<sarr[0].size(); j++ ) {

            cout << sarr[i][j] << "\t";
        }

        cout << "\n";
    }

    return 0;
}
Дабы не раздувать приведенный в качестве примера код, проверка доступности файла, возможности его открытия, а также однородности массива в файле с данными были опущены. Не забывайте о подобных проверках в реальных программах!

среда, 15 февраля 2012 г.

C++. Замена в строке

Решением может быть такая функция:
#include <string>

using std::string;

...

void replaceInString(string &str,
                     const string &str1,
                     const string &str2) {

    size_t n = 0;

    while ( (n = str.find(str1)) != string::npos ) {

        str.replace(n, str1.length(), str2);
    }
}

...
UPD 25.02.2015
Хотя можно просто воспользоваться std::replace. Приведем пример с заменой запятой на точку.
#include <algorithm>
...
using std::replace;
...
replace(str.begin(), str.end(), ',', '.');
...

C++. Разбивка строки

Решением может быть такая функция:
#include <string>
#include <vector>

using std::string;
using std::vector;

...

void splitString(const string &fullstr,
                 vector<string> &elements,
                 const string &delimiter) {

    string::size_type lastpos =
        fullstr.find_first_not_of(delimiter, 0);
    string::size_type pos     =
        fullstr.find_first_of(delimiter, lastpos);

    while ( (string::npos != pos) || (string::npos != lastpos) ) {

        elements.push_back(fullstr.substr(lastpos, pos-lastpos));

        lastpos = fullstr.find_first_not_of(delimiter, pos);
        pos = fullstr.find_first_of(delimiter, lastpos);
    }
}

...

C++. Конвертирование числа в строку

Решением может быть функция:
#include <string>
#include <sstream>

using std::string;
using std::ostringstream;

...

string numberToString(double x) {

    ostringstream stm;
    stm << x;

    return stm.str();
}

...

UPD 06.01.2021
Давно следовало дописать, что стандарт C++11 подарил нам такую функцию как std::to_string.

C++. Конвертирование строки в число

Решением может быть такая функция:
#include <string>
#include <sstream>

using std::string;
using std::istringstream;

...

double stringToDouble(const string &str) {

    istringstream stm;
    double val = 0;

    stm.str(str);
    stm >> val;

    return val;
}

...


UPD 06.01.2021
Новые функции в C++11.

Повседневные вопросы и их решения на C++

Планирую начать публикацию коротких заметок с решениями различных, скажем так, подзадач, с которыми может столкнуться инженер, при использовании C++ в своей работе - при создании расчетных приложений и обработке экспериментальных данных. Надеюсь, что кому-нибудь найденные мной решения пригодятся, а в комментариях, возможно, будут предложены более эффективные способы. Будем делиться опытом )

понедельник, 13 февраля 2012 г.

std vector iterator

Стало интересно, насколько много мы теряем, когда с дуру и не к месту перебираем элементы вектора не по индексу, а используя итератор.

Вариант 1 - доступ к значениям элементов вектора по индексу.
#include <iostream>
#include <vector>

using namespace std;

int main() {

    size_t vsize = 200000000;

    vector<double> v;
    v.resize(vsize, 0);

    for ( size_t i=0; i<vsize; i++ ) {

        v[i] = i/0.23;
    }

    double x = 0;

    for ( size_t i=0; i<vsize; i++ ) {

        x = v[i] / 283746.40596837 * 0.92386936827364;
    }

    return 0;
}
Среднее по 5-ти замерам время работы программы составило 4.7136 сек.

Вариант 2 - доступ к значениям элементов вектора с использованием итератора.
#include <iostream>
#include <vector>

using namespace std;

int main() {

    size_t vsize = 200000000;

    vector<double> v;
    v.resize(vsize, 0);

    for ( size_t i=0; i<vsize; i++ ) {

        v[i] = i/0.23;
    }

    double x = 0;

    for ( vector<double>::iterator it=v.begin(); it!=v.end(); ++it ) {

        x = *it / 283746.40596837 * 0.92386936827364;
    }

    return 0;
}
Среднее по 5-ти замерам время работы программы составило 7.196 сек.

Итак, производительность во втором случае упала почти на 34.5%... Честно говоря, я не думал, что итераторы настолько круто снижают производительность.
Для справки: компиляция осуществлялась с флагом -O0.

UPD: 09.01.2013

А теперь вариант 3 (с использованием возможностей C++11).
#include <iostream>
#include <vector>

using namespace std;

int main() {

    size_t vsize = 200000000;

    vector<double> v;
    v.resize(vsize, 0);

    for ( size_t i=0; i<vsize; i++ ) {

        v[i] = i/0.23;
    }

    double x = 0;

    for ( size_t z : v ) {

        x = z / 283746.40596837 * 0.92386936827364;
    }

    return 0;
}
Производительность практически та же, что и в варианте 2.

понедельник, 6 февраля 2012 г.

Arch Linux. Hibernation (suspend to disk)

"Из коробки" в Арче на ура работает ждущий режим (он же suspend to ram), чего не скажешь о режиме спящем (он же hibernate, он же suspend to disk). Машина прекрасно засыпает, а вот при повторном включении просто заново загружается. Как же настроить спящий режим в Арче? А вот как:
  1. В файле /boot/grub/menu.lst в строки, начинающиеся с kernel, дописать resume=/dev/sda2 (у кого swap раздел не /dev/sda2 - откорректируйте, у кого диски по uuid - получите идентификатор и запишите как положено);
  2. В файле /etc/mkinitcpio.conf в строку с параметрами HOOKS добавить resume;
  3. Переустановить ядро (pacman -S linux) или просто пересобрать initrd образ ядра;
  4. Перезагрузка.
Все. Теперь отлично работают и ждущий и спящий режимы.

UPD: 23.04.2014

Порядок действий в данной заметке явно требует актуализации. Освежим же его.
  1. В файле /etc/default/grub, в список значений параметра GRUB_CMDLINE_LINUX_DEFAULT добавить resume=/dev/sda2 (у кого swap раздел не /dev/sda2 - откорректируйте, у кого диски по uuid - получите идентификатор и запишите как положено). У меня эта строка выглядит так:
  2. GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=/dev/sda2"
  3. Заново сгенерировать файл конфигурации grub
  4. # grub-mkconfig -o /boot/grub/grub.cfg
  5. В файле /etc/mkinitcpio.conf в строку с параметрами HOOKS добавить resume
  6. Сгенерировать заново образы ядра
  7. # mkinitcpio -p linux
  8. Перезагрузить систему.

UNIX. История

Опубликована еще одна замечательная статья об истории UNIX. Не могу не поделиться ссылкой.

vlc и screensaver

Есть в Arch Linux, при использовании gnome-screensaver, небольшая проблема, связанная с отсутствием его блокировки плеером vlc. Предлагается 2 варианта для обхода этой неприятности.
  1. Вариант предложен моим коллегой и товарищем Дмитрием Епанешниковым и заключается в следующем:
    • Удалить gnome-screensaver;
    • Установить xscreensaver;
    • Поместить xscreensaver в автозагрузку, добавив в каталог /etc/xdg/autostart файл xscreensaver.desktop следующего содержания
        [Desktop Entry]
        Name=Xscreensaver
        Comment=Screensaver daemon
        Exec=/usr/bin/xscreensaver -nosplash
        Terminal=false
        Type=Application

    • В dconf-editor в разделе org->gnome->settings-daemon->plugins->power отключить всяческие манипуляции с монитором;
    • Настроить xscreensaver с помощью утилиты xscreensaver-demo;
    • Убедиться, что в vlc отмечен соответствующий чекбокс в расширенных настройках;
    • Насладиться просмотром любимого видео )
  2. Мой вариант:
    • Продолжать использовать gnome-screensaver, просто отключив автоблокировку экрана и используя для этого горячие клавиши по надобности.
Я не пережил страшилищного вида окна ввода логина и пароля при разблокировке в случае использования xscreensaver, потому и остался при своих )

четверг, 2 февраля 2012 г.

dd. Варианты использования

Очень понравилась статья Команда dd и все, что с ней связано, описывающая различные варианты использования команды dd для решения администраторских и пользовательских задач. И несмотря на то, что лично для себя я ничего нового не узнал, иметь закладочку на такую статью будет не лишним.

среда, 1 февраля 2012 г.

Распараллеливание сборки проекта

Для повышения эффективности сборки проекта путем ее распараллеливания необходимо запускать make с ключом -jX, где X - количество процессоров в системе плюс один.
В Qt Creator это указывается в разделе Проекты -> Этапы сборки -> Сборка -> Подробнее -> Параметры make.
Говорят, что в виндовсах этого мало и нужно еще использовать ключ -f Makefile.Release (или Makefile.Debug).

Подробности см. здесь.

Справка по git с картинками

Опубликован перевод на русский язык интересной справки по git с картинками.

Qt Creator 2.4.1 и Qt SDK 1.2

Релизы Qt Creator 2.4.1 и Qt SDK 1.2.