Задать вопрос
  • Правильно ли я все понимаю?

    saboteur_kiev
    @saboteur_kiev
    software engineer
    include <stdio.h> // include - директива препроцессора/программа, которая копирует содержимое файла stdio.h

    Можно и так, но правильнее "инклюдит", то есть вставляет.

    int main(void) { // функция main, которая возвращает целочисленное значение. аргументов не принимает

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

    int x  = 10; // объявление переменной x, которой присваивается значение 10

    да, определение с присваиванием

    return 0; // возврат родительному процессу(операционная система/терминал). 0 - завершение без ошибок

    Да. В стандарте С при return из main функции автоматически вызывает exit с возвратом кода в ОС.
    Ответ написан
    4 комментария
  • Почему из функции возвращается временный объект?

    vt4a2h
    @vt4a2h Куратор тега C++
    Senior software engineer (C++/Qt/boost)
    Там будет не временный объект, а тот же самый объект, что вы создали внутри функции. Даже копирования не будет. Хотя, у вас тут объект срезаться может поэтому ещё вопрос. Почитайте про RVO/NRVO.
    Я немного поправил ваше решение:
    Foo get_foo(const char *msg)
    {
        return Foo_2(msg);
    }

    Так будет лучше.

    Но! Тут важно понимать, что делать так в реальном коде нельзя, т.к. объект класса Foo_2, при некоторых условиях, срежется до объекта класса Foo. В вашем случае -- это не проблема. Но можно переписать как-то так, например:
    const Foo &get_foo(const char *msg)
    {
        static Foo_2 foo2(msg);
        return foo2;
    }

    Этот код тоже не для всех случаев подходит, т.к. get_foo будет возвращать всегда один и тот же объект с одним и тем же сообщением.
    Ответ написан
    5 комментариев
  • Как описать указатель на двумерный массив?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    int i[2][2] = {{1, 2}, {3, 4}};
    int (*ii)[2] = i;
    ii[0][0];
    Ответ написан
    Комментировать
  • Что есть структура, а что оператор в C?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В стандарте языка используются термины "expression" (например, printf("something\n"), без точки с запятой -- это expression, а именно вызов функции) и "statement" (например if (expression) statement -- это statement), а иногда expression может быть statement'ом (например, printf("something\n");, с точкой с запятой), это называется "expression statement".

    "expression" обычно переводится как "выражение" и не вызывает трудностей. Со "statement" сложнее. Мне нравятся переводы "конструкция" ("конструкция if", "конструкция switch") или "инструкция" ("инструкция goto", "инструкция return").


    Как называть по-человечески строчки:
    if ( a > b )
      printf("something\n");

    Конструкция if с единственной инструкцией-выражением.

    А такое:

    if(condition) {
      printf("something1\n");
      printf("something2\n");
    }

    Конструкция if с составной инструкцией содержащей две инструкции-выражения.
    Ответ написан
    2 комментария
  • Что нужно знать чтобы перевести с big-endian в little-endian?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Что нужно знать чтобы перевести с big-endian в little-endian?

    Структуру данных нужно знать. Одно дело, если там идут подряд 32-битные целые, другое -- если 64-битные, и совсем другое, если там заголовок в котором есть и байтовые поля и двух- и четырёх- и восьми-байтовые и битовые поля впридачу.
    Ответ написан
    4 комментария
  • Не получается реализовать в классе записи и чтения в/из файла. Какие действия посоветуете?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Так, как вы написали в комментариях - не прокатит для сложных объектов, вроде Sport.

    Во-первых, вы записываете и читаете txt-файл в двоичном формате. Вы представляете вообще, как должен выглядеть файл, содержащий данные вашего типа?

    Во-вторых, у вас внутри объекта есть динамические члены (способные изменять свои размеры) - vector и string. Благодаря этому объект имеет многомерное представление в памяти и вам необходимо придумать, как спроецировать его на "плоскую" память, записать его почленно. Если с char, int, float все очевидно (их размеры известены на этапе компиляции: sizeof(char), sizeof(int), sizeof(float)), то для string, например, нужно сначала сохранить его размер (чтобы потом знать, сколько читать из файла), а потом записать содержимое. С vector - аналогично, за тем исключением, что это тот же Sport и вам нужно вызвать функцию сохранения для каждого ребенка текущего объекта (и для их детей, т.е. рекуррентно обойти дерево владения).

    Чтение производить в обратном порядке.
    Ответ написан
    Комментировать
  • Как работать текстовыми файлами?

    CityCat4
    @CityCat4 Куратор тега C
    //COPY01 EXEC PGM=IEBGENER
    Потому что нормальный алгоритм работы с мелкими текстовиками следующий:

    открыть файл на чтение (man open - внимание, не потоковый fopen, а простой open!)
    получить размер файла из элемента оглавления каталога (man stat)
    выделить память размером с файл (man calloc)
    прочитать весь файл целиком (man read)
    закрыть файл (man close)
    и после этого парсить полученный буфер как угодно вдоль и поперек, не забывая конечно, что портить его не надо :)

    Ну или вот так наверно понятнее будет:
    #define NUL 0
      #define ERR -1
      int i;
      short int handle;
      struct stat sb;
      char *name="/tmp/testfile.txt";
      char *data;
    
      if ((handle = open(name, O_RDONLY)) < NUL)
        return ERR;
    
      stat(name, &sb);
      data = (char *) сalloc(sb.st_size + 1);
      i = read(handle, data, sb.st_size);
      close(handle);

    На выходе - массив data с данными файла.
    Ищещь перевод строки ('\n') и переставляешь указатель ЗА него (если нужно конвертить число в цифру то после перестановки на место перевода строки пишешь '\0' и используешь atoi() - на выходе длина строки, которая идет в качестве контроля, чтобы на SIGSEGV случайно не выскочить.
    Потом от нового положения указателя цикл по длине строки с поиском по таблице замен.

    Вот блин...ведь мамой клялся, что подсказывать не буду...
    Ответ написан
    1 комментарий
  • Как скопировать данные с убитой флешки в Ubuntu?

    Radjah
    @Radjah
    Можно попробовать с помощью ddrescue сделать raw-образ и насиловать уже его.
    Ответ написан
    Комментировать
  • Почему QSerialPort считывает только первый символ?

    @D3Nd3R
    Используйте QSerialPort::waitForReadyRead() прежде чем читать из порта.
    Так же можно реализовать асинхронное чтение, написав обработчик для сигнала readyRead().
    Ответ написан
    1 комментарий
  • Как ускорить код с подсчетом похожести?

    @deliro
    1. Убери повторения (в моём примере это уже сделано), сравнивать id=5 с id=1 не надо, если ты уже сравнил id=1 с id=5. Они симметричны
    2. Если кэш поможет (в чём я сомневаюсь) — можно его оставить. Если ты уверен, что не будет двух неуникальных list_word_int — выбрасывай кэш смело.
    3. Это вроде можно распараллелить. Задействуй все ядра
    4. Перепиши это на быстрый компилируемый язык вроде Golang или Cython

    Однопоточный код
    import difflib
    from functools import lru_cache
    from itertools import combinations
    
    arr = [
        {"_id": 1, "list_word_int": (189, 114, 188, 90, 2, 68, 96, 0, 250, 168, 150, 126)},
        {"_id": 2, "list_word_int": (224, 26, 56, 153, 139, 128, 126, 220, 190, 137)},
        {"_id": 3, "list_word_int": (188, 241, 225, 134, 134, 30, 134, 187, 204, 227, 3)},
        {"_id": 4, "list_word_int": (224, 166, 159, 236, 82, 17, 82, 21, 227, 97)},
        {"_id": 5, "list_word_int": (98, 96, 38, 107, 142, 134, 13, 36, 23)},
    ]
    
    
    @lru_cache(maxsize=2 ** 13)
    def get_ratio(lst1, lst2):
        return difflib.SequenceMatcher(None, lst1, lst2).ratio()
    
    
    if __name__ == "__main__":
        for a, b in combinations(arr, 2):
            ratio = get_ratio(a["list_word_int"], b["list_word_int"])
            print(
                "id= ",
                a["_id"],
                "Сравниваемый id=",
                b["_id"],
                "Коэффициент похожести:",
                ratio,
            )
    
        print(get_ratio.cache_info())
    Параллельное выполнение, генерация комбинаций во всех процессах
    import difflib
    import multiprocessing as mp
    import os
    from itertools import combinations, cycle
    
    arr = [
        {"_id": 1, "list_word_int": [189, 114, 188, 90, 2, 68, 96, 0, 250, 168, 150, 126]},
        {"_id": 2, "list_word_int": [224, 26, 56, 153, 139, 128, 126, 220, 190, 137]},
        {"_id": 3, "list_word_int": [188, 241, 225, 134, 134, 30, 134, 187, 204, 227, 3]},
        {"_id": 4, "list_word_int": [224, 166, 159, 236, 82, 17, 82, 21, 227, 97]},
        {"_id": 5, "list_word_int": [98, 96, 38, 107, 142, 134, 13, 36, 23]},
    ]
    
    
    def target(id_, count):
        pid = os.getpid()
    
        for i, (a, b) in zip(cycle(range(count)), combinations(arr, 2)):
            if i != id_:
                continue
            ratio = difflib.SequenceMatcher(
                None, a["list_word_int"], b["list_word_int"]
            ).ratio()
            print(f"PID: {pid} id={a['_id']} & {b['_id']} ratio={ratio}")
    
    
    if __name__ == "__main__":
        processes = []
    
        for x in range(mp.cpu_count()):
            p = mp.Process(target=target, args=(x, mp.cpu_count()))
            p.start()
            processes.append(p)
    
        for p in processes:
            p.join()
    Один процесс генерирует комбинации в очередь, остальные обрабатывают
    import difflib
    import multiprocessing as mp
    import os
    from itertools import combinations
    
    arr = [
        {"_id": 1, "list_word_int": [189, 114, 188, 90, 2, 68, 96, 0, 250, 168, 150, 126]},
        {"_id": 2, "list_word_int": [224, 26, 56, 153, 139, 128, 126, 220, 190, 137]},
        {"_id": 3, "list_word_int": [188, 241, 225, 134, 134, 30, 134, 187, 204, 227, 3]},
        {"_id": 4, "list_word_int": [224, 166, 159, 236, 82, 17, 82, 21, 227, 97]},
        {"_id": 5, "list_word_int": [98, 96, 38, 107, 142, 134, 13, 36, 23]},
    ]
    
    
    def queue_creator(q, w_count):
        pid = os.getpid()
        print("Created queue generator PID", pid)
    
        for a, b in combinations(arr, 2):
            q.put((a, b))
        for _ in range(w_count):
            q.put(("stop", None))
    
    
    def worker(q):
        pid = os.getpid()
        print("Created worker PID", pid)
    
        while True:
            a, b = q.get()
            if a == "stop":
                break
    
            ratio = difflib.SequenceMatcher(
                None, a["list_word_int"], b["list_word_int"]
            ).ratio()
            print(f"PID:{pid} {a['_id']} & {b['_id']} ratio={ratio}")
    
    
    if __name__ == "__main__":
        queue = mp.Queue()
        # 1 воркер на генерацию комбинаций, остальные на обработку
        workers_count = (mp.cpu_count() - 1) or 1
        q_process = mp.Process(target=queue_creator, args=(queue, workers_count))
        q_process.start()
        processes = [q_process]
    
        for x in range(workers_count):
            p = mp.Process(target=worker, args=(queue,))
            p.start()
            processes.append(p)
    
        for process in processes:
            process.join()

    Ответ написан
    22 комментария
  • Можно ли на "C" написать приложения под андроид?

    GavriKos
    @GavriKos
    Гуглите в сторону Android NDK. Правда все равно вам нужно будет немного джавы.
    Вкратце схема такая. Делается либа на c/c++ (насколько я помню чистый c там тоже можно). Делается ядро приложения на java - всякие там activity, интерфейсец и прочее. Джава умеет вызывать методы вашей либы, и ваша либа обратно умеет вызывать методы джавы. Все это красиво архитектурно (на самом деле нет, ибо там геммора много) связываете и вуаля. Логика на сях, обертка на java.
    Ответ написан
    2 комментария
  • Как сократить число в периоде?

    @Wexter
    1) Тип выбирайте double
    2) если уж делите числа то делите числа с точкой, а не целые

    double U = 3./180.;
    Ответ написан
    Комментировать
  • Как сократить число в периоде?

    0xD34F
    @0xD34F
    Ну так 3/180 - это вы целыми числами оперируете. Отсюда и 0 в результате. Попробуйте 3.0/180. Или 3/180.0.
    Ответ написан
    Комментировать
  • Стоит ли устанавливать Windows 10 на данную конфигурацию?

    @Derzhuk
    Руководитель ИТ отдела
    Пользуюсь Windows 10 уже несколько лет. Жалоб нету есть проблемы но с выходом новых обновлений они их закрывают.
    Я бы ставил и не думал.
    Если есть возможность купить SSD, будет круто.
    Можно и без SSD тогда надо отключать ряд служб для уменьшение дисковой активности.
    Ответ написан
    Комментировать
  • Можно ли и создать экземпляр класса (с++) с проинициализированными полями?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    $ cat > test.cpp <<EOF
    class type_class {
            int field1;
            int field2;
    public:
            constexpr type_class (int f1, int f2): field1(f1), field2(f2) {
            }
    };
    extern const type_class var;
    const type_class var(12, 34);
    EOF
    $ g++ -S -O2 test.cpp
    $ cat test.s
            .file   "test.cpp"
            .globl  var
            .section        .rodata
            .align 8
            .type   var, @object
            .size   var, 8
    var:
            .long   12
            .long   34
            .ident  "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
            .section        .note.GNU-stack,"",@progbits

    Т.е. constexpr конструктор, в результате -- готовый инициализированный объект в секции .rodata, что и требовалось.
    Ответ написан
    1 комментарий
  • Какая разница в цикле for между "i ++" и "++ i"?

    dom1n1k
    @dom1n1k
    В данном случае присваивания не делается, поэтому никакой разницы в смысле результата работы нет.
    Есть разница в смысле скорости (++i работает немного быстрее), но она настолько микроскопическая, что на неё нужно смело забивать в 99.(9)% случаев. Возможно даже, что сейчас компиляторы ловят эту ситуацию и тогда разница исчезает вовсе.
    Сам я пишу ++i, но не ради перфоманса, это просто моя исторически сложившаяся вкусовщина.
    Нужно просто выбрать один кодстайл (личный или корпоративный) и придерживаться его. Смешивать два варианта в пределах одной программы - это плохо.
    Ответ написан
    Комментировать
  • Какая разница в цикле for между "i ++" и "++ i"?

    SerafimArts
    @SerafimArts
    Senior Notepad Reader
    Как уже верно было сказано - в алгоритме отличий нет. Отличия лишь в выходном коде которые могут гененрировать компиляторы. Могут, просто потому, что эта инструкция допускает оптимизации во время компиляции. Так что всё зависит от самого компилятора.

    Ещё с универа помню, объясняли, что на уровне ассемблера ++i превращается в одну инструкцию инкремента, i++ же в две (или одну, но не инкремемента, а обычного add), отсюда и отличия в производительности. P.S. Эта информация не точная и могу наврать, но в целом как-то так.
    Ответ написан
    1 комментарий
  • С чего начать писать задание?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Ответ написан
    Комментировать
  • Что выбрать: Django или Flask?

    sim3x
    @sim3x
    джанго
    По книге: two scoops of django
    Или по туториалу
    Ответ написан
    7 комментариев
  • Си. Какой из вариантов высчитывает более точное значение?

    "Помните, что не все десятичные числа имеют двоичное представление с плавающей запятой. Например, число «0,2» будет представлено как «0,200000003» в одинарной точности. Соответственно, «0,2 + 0,2 ≈ 0,4». Абсолютная погрешность в отдельном случае может и не высока, но если использовать такую константу в цикле, можем получить накопленную погрешность."
    (C) Что нужно знать про арифметику с плавающей запятой
    Ответ написан
    1 комментарий