• Как сделать дерево обьектов из массива?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function createTreeFromArray(arr, key, parentKey) {
      const tree = Object.fromEntries(arr.map(n => [ n[key], { ...n } ]));
      return Object.fromEntries(Object
        .entries(tree)
        .filter(([ , n ]) => !(tree[n[parentKey]] && ((tree[n[parentKey]].children ??= {})[n[key]] = n)))
      );
    }
    
    
    const tree = createTreeFromArray(arr, 'uid', 'parentUID');
    Ответ написан
    1 комментарий
  • Как в C определить размер двумерного массива?

    wisgest
    @wisgest
    Не ИТ-специалист
    sizeof arr / sizeof arr[0]
    Ответ написан
    2 комментария
  • Как передать массив в функцию С++ ( пишет no matching function to call)?

    @res2001
    Developer, ex-admin
    Написал опус на вопрос, который вы удалили, хорошо сохранился в буфере обмена :-) а то было бы обидно.

    Ваш массив пожно просто привести к указателю, по старинке (int*)a или используя касты.

    Но у вас тут на самом деле 2 проблемы.
    Первая - обращение к элементам массива в average используя [i][j]. Вторая - VLA.
    По первой проблеме:
    В С/С++ оператор индексации (array[i]) выполняет следующее действие: *(array+i).
    Отсюда должно быть понятно, что раз array у вас это int*, то после array[i] вы получите int, от которого уже нельзя взять второй индекс, т.к. это просто 1 int, а не массив.

    Отсюда есть несколько выходов:
    1. дурацкий (самый долгий по исполнению и затратам памяти): использовать динамический массив массивов
    Выглядит примерно так:
    int **array = new int*[rowCount];
    for(int i=0; i < rowCount; ++i)
       array[i] = new int[colCount];

    Как видите array превратился в двойной указатель, теперь каждый элемент в первом измерении - это указатель на одномерный массив. Всего у вас получается rowCount + 1 выделений памяти. Не забудьте столько же раз вызвать оператор delete.
    В average теперь передавайте int** и у вас будет работать оператор [][], т.к. первая индексация уже будет возвращать int*.
    Не рекомендую использовать этотт способ.

    2. Вычислять индекс массива вручную (не использовать индексацию):
    *(array + i*colCount + j)
    Это такой хардкорный стиль. Но зато работает быстро и масштабируется на массивы любой размерности без особых проблем.

    3. использовать std::vector<std::vector<int>> - это то же самое, что и вариант 1, но закамуфлированный под вектор :-)

    Вторая проблема это VLA (Variable Length Array).
    Статические (автоматические) массивы в С++ вы можете определять, только константным размером (размером известным на этапе компиляции).
    У вас же размерность массива динамическая (вводится пользователем во время выполнения программы). Отсюда следует, что вы должны использовать динамические массивы, выделенные с помощью new.
    В стандарте С++ нет VLA. VLA есть только в Си и то начиная с С99.
    Ваша функция task3 компилируется, только потому что в gcc/clang по умолчанию включены расширения. В расширения входит так же и возможность использовать VLA. Если задать опциями более строгое соответствие стандарту С++, то функция не соберется.
    И кстати, например в микросовтовский компилятор VLA до сих пор не завезли.

    Но если уж у вас есть VLA, то вы можете преобразовывать указатель в VLA массив с помощью такой кучерявой конструкции:
    int (*array2)[colCount] = (int(*)[colCount]) array;

    В этом случае обращаться к элементам массива можно как обычно через двойную индексацию: array2[i][j]
    Когда-то делал тест на эту тему: https://ideone.com/4i6lRw
    Кстати, если в average сначала передать размерности, и последним параметром массив, то по идее массив можно сразу объявить двумерным, используя ранее переданные размерности:
    void average(int rowcount, int colcount, int aarray[rowCount][colCount])

    Это то же VLA.

    Вообще не рекомендую в С++ использовать VLA, т.к. программа становится не переносимой и зависимой от компилятора.
    Ответ написан
    4 комментария
  • Как передать массив в функцию С++ ( пишет no matching function to call)?

    Adamos
    @Adamos
    Используя Кресты, стоит использовать и их удобства.
    std::vector< std::vector< int > > a(rowCount, std::vector< int >(colCount, 0));
    void average (std::vector< std::vector< int > > &a){

    Так вы не нарветесь на промахи в индексах массива, например. Если умеючи.

    А в вашем коде int[][], конечно, не может самопроизвольно превратиться в int*
    Ответ написан
    2 комментария
  • Как разобраться с выводом valgrind?

    shurshur
    @shurshur
    При попадании в блок:
    if (!result)
    память реально НЕ выделена и free от неё - это попытка освободить память по адресу NULL. Разумеется, это не будет работать.

    upd: Прочитал вопрос ещё раз внимательнее. Надо не забывать делать free в конечном месте использования этого result:

    result = get_next_line();<br>
    ...do_something_with_result...<br>
    free(result);


    Иначе да, при каждом вызове get_next_line будет выделяться новый блок на 2 байта.
    Ответ написан
    3 комментария
  • Как получить значения из массива объектов по id?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сделать из teamNames объект, где ключами будут id:

    const teamNamesObj = Object.fromEntries(teamNames.map(n => [ n.id, n.name ]));

    Доставать из этого объекта имена:

    const eplWithNames = epl.map(n => ({ ...n, name: teamNamesObj[n.team_id] }));
    Ответ написан
    Комментировать
  • Как найти расстояние между двумя отрезками?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Задача разбивается на две более простые подзадачи.

    1) Проверить пересечение отрезков. Если пересекаются, то расстояние равно 0. Можно посчитать площади треугольников, образованных вершинами отрезков. Пересечение будет, если они имеют разный знак +-.

    2) если не пересекаются, то найти 4 расстояния, от каждого конца отрезка до другого отрезка. Это вреде обсуждалось тут ранее, поищи.
    Ответ написан
    Комментировать
  • Что передается с bind'ом?

    gbg
    @gbg
    Любые ответы на любые вопросы
    Acceptor::handleAccept - это нестатический метод класса Acceptor.

    У настатических методов первым параметром должен быть передан указатель на экземпляр класса. Когда вы вызываете методы класса напрямую, компилятор делает такую подстановку неявно. Когда вы это делаете через bind - нужно своими руками передать такой указатель, в данном случае - this.
    Ответ написан
    Комментировать
  • Как принять пробел в строку из пользовательского ввода?

    nowm
    @nowm
    В C++ есть getLine, и он читает всю строку:

    #include <string>
    #include <iostream>
    
    int main()
    {
       std::string words;
       
       std::cout << "Введите слова: ";
       std::getline(std::cin, words);
       
       std::cout << "Слова: " << words << "\n";
    }
    Ответ написан
    1 комментарий
  • Почему берутся проблемы с совместимостью массивов и контейнеров?

    @Mercury13
    Программист на «си с крестами» и не только
    Учите матчасть!
    Версия для буфера памяти предполагает, что данные хранятся в непрерывном буфере nm×double (то есть длина mn, элемент double).
    Но vector<vector> — он НЕ непрерывный буфер.
    Есть непрерывный буфер n×vector<double> — центральный вектор. И каждая из n строчек по отдельности — непрерывный буфер m×double. Относительно друг друга в памяти они могут располагаться как угодно.

    Как исправить? — проще всего
    double s = 0;
    for (i...) {
      s += Sum(m, &a[i][0]);
    }

    Можно через шаблоны работать, но это уже сложнее и я сам не смогу это с листа написать, что уж говорить про первокура.
    Ответ написан
    Комментировать
  • Почему strcat() останавливает работу программы?

    includedlibrary
    @includedlibrary
    Потому что в strcat нужно передать указатель на строку, вы передаёте переменную z с типом int. В результате z интерпретируется, как адрес, по которому лежит строка и происходит ошибка сегментирования.
    Ответ написан
    Комментировать
  • Почему дружественная функция, определённая внутри класса с первым параметром встроенного типа, недоступна вне определения класса?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Согласно стандарту, дружественная функция может быть определена по месту объявления только для нелокального класса и только если имя функции не является квалифицированным.
    Первое ограничение нас мало интересует, а второе - является довольно существенным.

    Первично объявленная дружественной функция, согласно стандарту, становится участником пространства имен того типа, для которого объявлена дружественной.
    Получаем такую ситуацию. У нас есть пространство имен, пусть даже глобальное, в котором определяется тип. Во время определения этого типа делается первичное объявление функции как дружественной этому типу. В результате этого функция, как бы, объявляется принадлежащей пространству имен в котором определяется тип, но не совсем.

    Функция f5 не просто первично объявлена, она и определена по месту объявления дружественности. Ее имя является однозначно неквалифицированным в следствии своего определения.

    Еще из стандарта мы можем узнать о том, что первично объявленное дружественное имя не может быть найдено средствами стандартного поиска квалифицированных или неквалифицированных имен.
    Именно этот результат мы и можем наблюдать в вопросе. Имя f5 не находится.

    Все потому что т.н. имена скрытых друзей могут быть найдены только средствами ADL.
    Если коротко, Argument-Dependent Lookup опирается на типы аргументов при вызове функции, пространства их имен и пространства имен, в которых эти типы объявлены.
    ADL не выполняет поиск в пространствах имен в отношении фундаментальных типов. Поэтому код f5(5); буквально обречен на ошибку трансляции.

    Первично объявленная дружественной функция будет исключительно ADL-доступной до момента своего объявления или определения в том же пространстве имен, в котором определен тип друга. В этом случае функция станет доступна для поиска квалифицированных или неквалифицированных имен.
    Для f5 доступен только способ с повторным объявлением, т.к. она уже определена.
    Да только в этом случае f5 окончательно потеряет всякий смысл быть дружественной для A и станет просто сильно спрятанной и сбивающей с толку глобальной функцией.
    Суть дружественности в раскрытии доступа, которым f5 относительно A не пользуется, т.к. среди ее параметров нет ни одного с типом A.

    В результате.
    Чтобы ADL нашел функцию f5, среди ее параметров обязан быть параметр и с типом A.
    Чтобы UNL или QNL смогли найти функцию f5, ее надо дополнительно объявить за пределами типа A в его пространстве имен.
    Ответ написан
    1 комментарий
  • Что такое указатели в С++?

    Adamos
    @Adamos
    Написана дичь, не имеющая никакого отношения к реальности.
    Причем стиль написания говорит о низкой грамотности автора.
    Читайте нормальные учебники, а не отсебятину.
    Ответ написан
    Комментировать
  • Как решить данную задачу?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    3*64
    Начните с простого. Сколько будет однозначных чисел, состоящих из цифр 0, 1, 2, 3, 4, 5?
    А сколько из них чётных?
    А сколько будет двузначных чисел из тех же цифр, если первая всегда 2?
    А чётных?
    А трёхзначных?
    И т.д.
    Ответ написан
    2 комментария
  • Как теперь вернуться обратно? Как узнать уравнение параболы в старом базисе?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    1. Сместим систему координат вниз на 1.
    x' = x
    y' = y + 1
    Обратное преобразование:
    x = x'
    y = y' - 1
    Уравнение прямой: y = x − 1, y' − 1 = x' − 1, y' = x'
    Переход точек: (0, 0) → (0, 1), (0, 1) → (0, 2)

    2. Повернём систему координат по часовой стрелке на π/4.
    x'' = x'⋅cos(π/4) − y'⋅sin(π/4) = x'⋅√2/2 − y'⋅√2/2
    y'' = x'⋅sin(π/4) + y'⋅cos(π/4) = x'⋅√2/2 + y'⋅√2/2
    Обратное преобразование:
    x' = x''⋅cos(π/4) + y''⋅sin(π/4) = x''⋅√2/2 + y''⋅√2/2
    y' = −x''⋅sin(π/4) + y''⋅cos(π/4) = −x''⋅√2/2 + y''⋅√2/2
    Уравнение прямой: y' = x', x''⋅√2/2 + y''⋅√2/2 = −x''⋅√2/2 + y''⋅√2/2, x'' = 0
    Получили, что прямая стала осью ординат.
    Переход точек: (0, 1) → (−√2/2, √2/2), (0, 2) → (−√2, √2)

    Уравнение параболы, симметричной оси ординат: y'' = a⋅x''2 + b
    a/2 + b = √2/2
    2⋅a + b = √2
    Отсюда a = √2/3, b = √2/3
    y'' = √2/3⋅x''2 + √2/3
    x'⋅√2/2 + y'⋅√2/2 = √2/3⋅(x'⋅√2/2 − y'⋅√2/2)2 + √2/3
    x'2 + y'2 − 2⋅x'⋅y' − 3⋅x' − 3⋅y' + 2 = 0
    x2 + (y + 1)2 − 2⋅x⋅(y + 1) − 3⋅x − 3⋅(y + 1) + 2 = 0
    x2 + y2 − 2⋅x⋅y − 5⋅x − y = 0
    Ответ написан
    5 комментариев
  • Односвязные списки. Удаление элемента?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Если это не последний элемент, то присваиваем в него значение из следующего, потом удаляем следующий
    Ответ написан
    2 комментария
  • Как связать javascript, работающий в браузере, с программой, работающей в windows?

    yarkov
    @yarkov Куратор тега JavaScript
    Проект "Жизнь после смерти" - lifeafterdeath.ru
    Поднять http/websocket сервер в программе и общайтесь наздоровье со скриптом.
    Ответ написан
    1 комментарий
  • Как разбить числа по группам так, чтобы в группах находились близкие по значению числа?

    @Mercury13
    Программист на «си с крестами» и не только
    Это называется кластеризация, и самый ходовой метод для неё — K-means.
    Ответ написан
    2 комментария
  • Возможно ли изменить компиляцию С++?

    @Vindicar
    Ответ написан
    Комментировать
  • Как объяснить данный фрагмент кода?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    В данном коде демонстрируется типичная ошибка подмены типа (type punning [?]), ведущая к неминуемому UB [?] по стандарту.

    num в данном случае представляет собой шестнадцатеричное число, при выводе оно переводится в десятичное число типа double.


    Вот что стандарт говорит о подмене типа.
    [basic.lval#11]
    If a program attempts to access the stored value of an object through a glvalue whose type is not similar to one of the following types the behavior is undefined:
    (11.1) -- the dynamic type of the object,
    (11.2) -- a type that is the signed or unsigned type corresponding to the dynamic type of the object, or
    (11.3) -- a char, unsigned char, or std​::​byte type.

    Относительно unsigned long long тип double не обладает ни одним из требуемых стандартом свойств. Отсюда прямой вывод что данный код вносит UB.
    Поэтому под большим вопросом остается то, что выводится данным кодом.

    В итоге, правильным примером подмены типа на другой может быть только пример, где используется подмена на разрешенный тип представления объекта: char, unsigned char или std::byte для C++17.
    C++ Core Guidelines в секции C.183 однозначно не советует для подмены использовать union. Этого действительно не стоит делать даже при условии того, что все современные трансляторы понимают такие конструкции так, как подозревает писатель.

    Почему неверно работает, к примеру, такой фрагмент кода:

    Второй блок кода означает приведение значения из типа unsigned long long в тип double. В этом случае производится именно стандартное преобразование типа, а не подмена с целью интерпретации представления памяти num иным образом.
    0xC068C0C000000000 для типа unsigned long long означает 13864543383726325760, при преобразовании этого значения в тип double значение будет преобразовано в 1.3864543383726326e+19. В таком виде оно и будет выведено.

    Относительно первого блока кода, лучшим примером подмены типа для кода из вопроса будет такой:
    unsigned long long num = 0xC068C0C000000000;
    double representation = {};
    memcpy( &representation, &num, sizeof( num ) );
    cout << representation;

    И не стоит бояться обращения к memcpy тут. Данный код полностью соответствует стандарту и ожидаемо оптимизируется транслятором до желаемого результата.

    Мне не понятно, как работает такая конструкция, т.е зачем передавать именно ссылку на переменную num?

    Иногда требуется произвести приведение типа значения [?], иногда требуется произвести интерпретацию памяти этого значения другим типом. Это и называется подменой типа или алиасингом. Более детальную информацию о подмене типа, и алиасинге вообще, можно узнать из этой заметки.
    Ответ написан
    Комментировать