Исключение, выполняемое при выполнении кода [duplicate]

Я предполагаю, что вы имеете в виду «приложение X11» - из вашего описания не совсем ясно, что вы планируете делать. Ниже фрагмент кода отправит код «паузы» в приложение, которое в настоящее время имеет фокус ввода с клавиатуры в X11, используя расширение XTest. Из того, что я прочитал, это наиболее совместимый способ «подделать» события клавиатуры. Посмотрите, можете ли вы применить это к вашему сценарию (нет ошибки проверки правильности XOpenDisplay, чтобы сделать его проще).

  #include & lt; X11 / Xlib.h & gt;  #include & lt; X11 / keysym.h & gt;  #include & lt; X11 / extensions / XTest.h & gt;  ... Показать * дисплей;  unsigned int keycode;  display = XOpenDisplay (NULL);  ... keycode = XKeysymToKeycode (отображение, XK_Pause);  XTestFakeKeyEvent (отображение, keycode, True, 0);  XTestFakeKeyEvent (отображение, код ключа, False, 0);  XFlush (дисплей);   

Вам нужно будет связать с -lX11 -lXtst.

Очевидно, что firefox должен был иметь фокус в это время.

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

13
задан iwasinnamuknow 12 August 2011 в 21:57
поделиться

7 ответов

Я сериализую, отбрасывая класс в char * и записывая его в файл с файлом fstream. Чтение, конечно, только наоборот.

К сожалению, это работает только при отсутствии указателей. Вы можете указать свои классы void MyClass::serialize(std::ostream) и void MyClass::deserialize(std::ifstream) и вызвать их. Для этого случая вам нужно

std::ostream& MyClass::serialize(std::ostream &out) const {
    out << height;
    out << ',' //number seperator
    out << width;
    out << ',' //number seperator
    out << name.size(); //serialize size of string
    out << ',' //number seperator
    out << name; //serialize characters of string
    return out;
}
std::istream& MyClass::deserialize(std::istream &in) {
    if (in) {
        int len=0;
        char comma;
        in >> height;
        in >> comma; //read in the seperator
        in >> width;
        in >> comma; //read in the seperator
        in >> len;  //deserialize size of string
        in >> comma; //read in the seperator
        if (in && len) {
            std::vector<char> tmp(len);
            in.read(tmp.data() , len); //deserialize characters of string
            name.assign(tmp.data(), len);
        }
    }
    return in;
}

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

std::ostream &operator<<(std::ostream& out, const MyClass &obj)
{obj.serialize(out); return out;}
std::istream &operator>>(std::istream& in, MyClass &obj)
{obj.deserialize(in); return in;}
10
ответ дан Mooing Duck 15 August 2018 в 18:36
поделиться
  • 1
    Выглядит интересно и не слишком разрушительно для существующего кода / рабочего процесса. У меня будет игра. благодаря – iwasinnamuknow 12 August 2011 в 22:24
  • 2
    (1) Ваши потоки должны быть переданы по ссылке, исключаемые конструкторы istream и ostream. (2) ширину и высоту, а размер строки будет объединен вместе на выходе, поэтому при чтении их в результате будет получен один номер. – Benjamin Lindley 12 August 2011 в 22:41
  • 3
    in.read(&name[0], len);, что, безусловно, неправильно. Вы не можете обрабатывать строку как вектор. И даже в качестве вектора он потерпит неудачу, если len == 0. – john 12 August 2011 в 22:43
  • 4
    @john: согласился. Кажется, что требуется промежуточное char *nameValue = new char[len + 1];. – Rudy Velthuis 12 August 2011 в 22:56
  • 5
    @Benjamin Lindley: кричит, я забыл сделать их по ссылке. Виноват. – Mooing Duck 12 August 2011 в 23:08

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

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

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

2
ответ дан 6502 15 August 2018 в 18:36
поделиться

Просто запись двоичного содержимого объекта в файл не только не переносима, но, как вы признали, не работает для данных указателя. В основном у вас есть два варианта: либо вы пишете настоящую библиотеку сериализации, которая правильно обрабатывает std :: strings, например. используя c_str () , чтобы вывести фактическую строку в файл, или вы используете отличную библиотеку boostization . Если это вообще возможно, я бы рекомендовал последнее, вы можете сериализовать с помощью простого кода следующим образом:

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>

class A {
    private:
        std::string s;
    public:
        template<class Archive>
        void serialize(Archive& ar, const unsigned int version)
        {
            ar & s;
        }
};

Здесь функция serialize работает для сериализации и десериализации данных, в зависимости от как вы это называете. Дополнительную информацию см. В документации.

10
ответ дан Joe Gauterin 15 August 2018 в 18:36
поделиться
  • 1
    Отличная идея. Однако похоже, что вы показываете пример «последнего» - использование boost, в то время как вы советуете «бывший» ... – xtofl 12 August 2011 в 22:11
  • 2
    Правильно, спасибо за это. – Antti 12 August 2011 в 22:18
  • 3
    Я еще не вырыл, чтобы увеличить, но я проверю его дальше. благодаря – iwasinnamuknow 12 August 2011 в 22:19

Я долго не кодировал C ++, но, возможно, вы могли бы сериализовать массив из char.

Затем, когда вы открываете файл, ваш string будет просто указывать на массив.

Просто идея.

-1
ответ дан jp2code 15 August 2018 в 18:36
поделиться
  • 1
    LPTSTR недоступен (только для окон). – osgx 12 August 2011 в 22:03
  • 2
    Однако он не хотел возвращаться к использованию массивов. – Seth Carnegie 12 August 2011 в 22:03
  • 3
    std :: string не является LPTSTR – osgx 12 August 2011 в 22:04
  • 4
    Я не умер против массивов символов, но я много работал над использованием std :: strings, устал, когда мне сказали, что я старомодный. Если они облегчат ситуацию, мне, возможно, придется вернуться. – iwasinnamuknow 12 August 2011 в 22:07
  • 5
    Они, конечно, не облегчают ситуацию. Но почему бы не прочитать в массив символов, а затем присвоить свой массив символов строке? Это очень сложно? – john 12 August 2011 в 22:15
/*!
 * reads binary data into the string.
 * @status : OK.
*/

class UReadBinaryString
{
    static std::string read(std::istream &is, uint32_t size)
    {
        std::string returnStr;
        if(size > 0)
        {
            CWrapPtr<char> buff(new char[size]);       // custom smart pointer
            is.read(reinterpret_cast<char*>(buff.m_obj), size);
            returnStr.assign(buff.m_obj, size);
        }

        return returnStr;
    }
};

class objHeader
{
public:
    std::string m_ID;

    // serialize
    std::ostream &operator << (std::ostream &os)
    {
        uint32_t size = (m_ID.length());
        os.write(reinterpret_cast<char*>(&size), sizeof(uint32_t));
        os.write(m_ID.c_str(), size);

        return os;
    }
    // de-serialize
    std::istream &operator >> (std::istream &is)
    {
        uint32_t size;
        is.read(reinterpret_cast<char*>(&size), sizeof(uint32_t));
        m_ID = UReadBinaryString::read(is, size);

        return is;
     }
};
0
ответ дан legion 15 August 2018 в 18:36
поделиться
  • 1
    В чем смысл иметь union без данных? – RocketR 12 August 2011 в 22:07
  • 2
    @RocketR. Я написал объединение. Хорошо исправлено. Вы знаете, что это было быстрое прохождение фрагментов кода из старых файлов проекта. – legion 12 August 2011 в 22:11
  • 3
    Я решил, что это был трюк :) – RocketR 12 August 2011 в 22:14
  • 4
    Ну магия происходит :) – legion 12 August 2011 в 22:19

Почему не просто что-то вроде:

std::ofstream ofs;
...

ofs << my_str;

, а затем:

std::ifstream ifs;
...

ifs >> my_str; 
0
ответ дан Oliver Charlesworth 15 August 2018 в 18:36
поделиться
  • 1
    Разве это не предполагало бы, что строка отделена от чего-либо еще? Я стараюсь, чтобы весь класс и его содержимое записывались / читались за один раз. – iwasinnamuknow 12 August 2011 в 22:03
  • 2
    Ну, это не работает, если у my_str есть место в нем. – john 12 August 2011 в 22:03
  • 3
    Если это чередуется с другими данными, или если в строке есть пробелы, вход не будет точным. – Benjamin Lindley 12 August 2011 в 22:04
  • 4
    Будет ли это работать со строкой, содержащей пробелы и / или символы новой строки? – 6502 12 August 2011 в 22:04
  • 5
    @Oli: Это точно, OP утверждает, что сериализация std :: string как-то сложнее, чем сериализация массива char. Это немного, чего я не понимаю, и пока он не объяснит себя, я не думаю, что мы скоро заберемся. – john 12 August 2011 в 22:11

Вам придется использовать более сложный метод сериализации, чем приведение класса к char* и запись его в файл, если ваш класс содержит любые экзогенные данные (string). И вы правы в том, почему вы получаете ошибку сегментации.

Я бы сделал функцию-член, которая будет принимать fstream и читать данные из нее, а также обратную функцию, которая возьмите fstream и напишите его содержимое для его восстановления позже, например:

class MyClass {
pubic:
    MyClass() : str() { }

    void serialize(ostream& out) {
        out << str;
    }

    void restore(istream& in) {
        in >> str;
    }

    string& data() const { return str; }

private:
    string str;
};

MyClass c;
c.serialize(output);

// later
c.restore(input);

Вы также можете определить operator<< и operator>> для работы с istream и ostream для сериализации и восстановления вашего класса, если вы хотите использовать этот синтаксический сахар.

1
ответ дан Seth Carnegie 15 August 2018 в 18:36
поделиться
  • 1
    Могут ли действия записи / чтения действовать по-разному, если они используются в качестве функций-членов? Я не понимаю, как это будет писать фактические символы вместо адреса указателя. – iwasinnamuknow 12 August 2011 в 22:05
  • 2
    Это не работает, если в нем есть пробел. – john 12 August 2011 в 22:08
  • 3
    @iwasinnamuknow: Никакие действия записи и чтения не действуют по-разному, когда используются в качестве функции-члена, что дает вам эту идею? – john 12 August 2011 в 22:09
  • 4
    @iwasinnamuknow Он использует operator<< и >> of (i|o)stream на string, который определен для записи содержимого строки в файл. У вас, очевидно, было бы больше членов данных, чем одна строка, поэтому вы просто записывали их все в выходной файл, а затем читали их из входного файла в том же порядке. – Seth Carnegie 12 August 2011 в 22:09
  • 5
    @john это был просто быстрый пример. – Seth Carnegie 12 August 2011 в 22:10
Другие вопросы по тегам:

Похожие вопросы: