Ответы пользователя по тегу C++
  • Как поместить значение переменной в массив?

    @Alexander1705
    string total_1[] = {};
    Это пустой массив, и так как его размер нельзя изменить, соответственно и значение вы в него не можете поместить.

    string total_1[10];
    total_1[4] = "Hello, world!";

    Так вы создаёте массив из 10 элементов, и в четвёртый (на самом деле пятый) помещаете значение.

    #include <vector>
    ...
    vector<string> total_1;
    total_1.push_back("Hello, world!");

    Так можно создать vector (массив с изменяемым размером), и добавить в конец новое значение.
    Ответ написан
    2 комментария
  • Как сделать нечто подобное в консоли?

    @Alexander1705
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; i < n; ++i)
        {
            if (i == 0 || j == 0 || i == j || i+j == n-1 || i == n-1 || j == n-1)
                std::cout << '*';
            else
                std::cout << ' ';
        }
        std::cout << '\n';
    }
    Ответ написан
    Комментировать
  • Как записать из двох массивов одинаковые значения в третий?

    @Alexander1705
    Посмотрите вниметельней на этот код:
    for (int j=0, i = 0, z=0; i < size,j<size,z<size; i++,j++,z++)
    {
        if (massA[i] == massB[j]) {
            massC[z] = massA[i];
            cout << massC[z] << " ";
        }
    }

    Думаю, вы не понимаете, как работает for. Вы присваиваете трём переменным одинаковое значение и одновременно увеличиваете каждый на единицу. Всё равно, что вы написали бы следующее:
    for (int i = 0; i < size; ++i)
    {
        if (massA[i] == massB[i]) {
            massC[i] = massA[i];
            cout << massC[i] << " ";
        }
    }

    Согласитесь, это не имеет смысла. Чтобы сделать то, что вы задумали, нужно разместить один цикл внутри другого:
    int k = 0;
    for (int j = 0; i < size; ++i)
    {
        for (int j = 0; j < size; ++i)
        {
            if (A[i] == B[j])
            {
                // Здесь можно сделать так:
                C[k] = A[i];
                ++k;
    
                // или одной строчкой
                // C[k++] = A[i]
            }
        }
    }

    Но заметьте, что у такого алгоритма будет один недостаток: если в одном массиве два одинаковых элемента, и в другом два таких же, в новом массиве их будет четыре. В более общем случае, если в одном массиве a одинаковых элементов, а в другом b таких же, в результате вы получите a*b таких элементов, что также может вызвать переполнение вашего массива.

    Вообще странно, что ваш пример скомпилировался. Должно быть, вы используете устаревший компилятор. В C++ функция main должна возвращать int. Использование void приводит к ошибке:
    main.cpp:1:11: error: ‘::main’ must return ‘int’


    Так же обратите внимание, что если используете в C++ заголовочные файлы языка C, их принято называть с префиксом c и без расширения .h
    #include <ctime>
    А вообще, в C++ есть random.

    Также никогда не используйте system("pause"); функция system, приостанавливает вашу программу, и запускает указанную в аргументе. Люди которые не используют Windows, не смогут запустить ваш код, потому что у них нет программы pause.
    Ответ написан
    Комментировать
  • Почему функция не возвращает нужное значение?

    @Alexander1705
    • Обнулить можно переменную, но не значение.
    • Обнулить - значит присвоить ноль.
    • Из предыдущего вытекает, что нельзя обнулить до заданного предела, потому ноль он и в Африке ноль, и нет у него никакого предела.
    • Какой ещё остаток при обнулении?
    • Остаток от деления 99 на 25 - это 24, а не 1
    • Зачем вы создали кучу переменных, которые не используете?
    • В условии цикла вы делаете проверку coin25 > 0, но зачем, если вы никогда не изменяете эту переменную?
    • Выражение surrender - coin25 вычисляет значение, но никуда его не записывает. Если хотите отнять что-то от переменной, можно использовать foo = foo - bar; или foo -= bar;


    Если я правильно понял, и нужно посчитать минимальное количество монет, то вам нужно что-то вроде этого:
    #include <iostream>
    
    int main()
    {
        const int N = 4;
        const int coinsValue[N] = {25, 10, 5, 1};
        int coinsCount[N] =       { 0,  0, 0, 0};
    
        int sum;
        std::cin >> sum;
    
        for (int i = 0; i < N; ++i)
        {
            while (sum >= coinsValue[i])
            {
                coinsCount[i]++;
                sum -= coinsValue[i];
            }
            std::cout << coinsCount[i] << " (" << coinsValue[i] << 
            (coinsCount[i] == 1 ? ") coin\n" : ") coins\n");
        }
    
    
    }
    Ответ написан
    3 комментария
  • Как подключить SDL2 в clion в ubuntu?

    @Alexander1705
    Библиотека не линкуется. Проверьте, что у вас в ${SDL2_LIBRARY}.

    P. S. Не нужно указывать заголовочные файлы в списке исходников.
    Ответ написан
  • Что можно писать в заголовочных файлах С++?

    @Alexander1705
    В заголовочных файлах должны быть объявления, в cpp-файлах - определения.
    Код заголовочного файла вставляется в каждый cpp, который его включает. Поэтому, если вы напишите в заголовочном файле int N = 42; в каждом cpp создастся новая переменная, если же вы добавите только объявление extern int N, компилятор поймёт, что переменную нужно искать в другом месте
    extern int N; // variable declaration
    int N; // variable definition
    
    // function declaration
    float f(float x, float y);
    
    // function definition
    float f(float x, float y)
    {
        return x + y;
    }
    
    // class declaration
    class Foo
    {
    public:
        Foo();
        void bar();
    private:
        static int baz;
    }
    
    // class member definition
    Foo::Foo()
    {
        // do some stuff
    }
    
    // class member definition
    void Foo::bar()
    {
        // do some stuff
    }
    
    // class member definition
    int Foo::baz = 42;
    Ответ написан
    1 комментарий
  • Почему массив заполнился буквой H?

    @Alexander1705
    Вообще это довольно странно, никакого unspecified behavior происходить не должно, так как выражение new вызывает конструктор по умолчанию для каждого объекта, то есть встроенные типы должны быть инициализированы нулём.

    Попробуйте вывести не символ, а его код, заменив одну строчку на:
    cout << static_cast<int>(arr[i][z]) << endl;

    P. S. Несколько советов по коду. Во-первых, после директив препроцессора не нужно ставить точку с запятой:
    #include <iostream>
    Во-вторых, endl не только переводит на новую строку, но и сбрасывает накопленный буфер, то есть сразу выводит всё на экран или в файл. Если у вас много вывода, это может очень серьёзно замедлить вашу программу. Для простого перевода строки выводите специальный управляющий символ '\n'

    Если выводите матрицу (двумерный массив), удобнее делать это так:
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            cout << arr[i][j] << ' '; // пробел можно убрать
        }
        cout << '\n';
    }


    Так же никогда не нужно использовать функцию system. Она приостанавливает вашу программу, и запускает другую (в данном случае pause). Такой вариант не только не оптимальный, но ещё и платформозависимый. Людям, которые используют mac или linux придётся вносить изменения в ваш код, чтоб запустить его, так как в этих ОС нет команды pause. Используйте для этого средства языка C++: cin.get();

    И ещё никогда не используйте заголовочный файл conio.h. Он не является частью стандарта языков C или C++, и не поддерживается большинством компиляторов.

    P. P. S. Какой компилятор вы используете? Какой он версии? Какие ключи компиляции или настройки проекта в IDE?
    Ответ написан
  • Eclipse C++ (The selection cannot be launched) как исправить?

    @Alexander1705
    stackoverflow.com/questions/20380792/eclipse-error...

    P. S. Первая же выдача в гугле по запросу "The selection cannot be launched". Неужели так сложно?
    Ответ написан
    1 комментарий
  • Как запретить копирования указателей?

    @Alexander1705
    Реализуйте оператор присваивания:
    // Так, если хотите, чтоб они указывали на одну область:
    Number& operator = (const Number& other)
    {
        delete val;
        this->val = other.val;
        return *this;
    }
    
    // Так, если должна создаваться копия значения:
    Number& operator = (const Number& other)
    {
        delete val;
        this->val = new float(*(other.val));
        return *this;
    }

    P. S. operator= должен возвращать ссылку на левый операнд.
    Ответ написан
  • Почему нужно указывать количество столбцов?

    @Alexander1705
    В памяти все элементы массива записываются по порядку, то есть последовательно. Двумерный массив можно рассматривать, как массив массивов, тогда станет понятно, что в памяти они записываются строка за строкой.

    Предположим, у нас в памяти записан массив int arr[m][n];, но известен только адрес первого элемента - p = &arr[0][0];, и нам нужно получить доступ к элементу a[i][j] используя указатель p.
    Сначала нам нужно сместится на i строк, то есть i*n элементов, а потом ещё на j элементов в текущей строке. Тогда искомый элемент - p[i*n + j].

    Как видите, не зная длинны строки n мы не сможем получить доступ к элементу только по указателю и двум индексам, с другой стороны, количество строк m не влияет на результат, поэтому его можно опустить.

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

    P. S. Можно добиться и другого поведения, только понадобится выделять память динамически, а после освобождать её.
    void foo(int** arr)
    {
        /* do something */
    }
    
    ...
    
    int** array = new int[m];
    for (size_t i = 0; i < m; ++i)
    {
        array[i] = new int[n];
    }
    
    foo(arr);
    
    for (size_t i = 0; i < m; ++i)
    {
        delete[] array[i];
    }
    delete[] array;
    Ответ написан
  • Можно ли считать константный указатель аналогом ссылки в С++?

    @Alexander1705
    Специально провёл эксперимент:

    1. Пишем две аналогичных программы: одна с использованием указателей, другая - ссылок.
    ptr.cpp
    #include <iostream>
    
    
    using namespace std;
    
    
    void foo(int* x) {*x = 7;}
    
    
    int main(int argc, char** argv)
    {
        int x = 0;
        foo(&x);
        cout << x << endl;
        return 0;
    }

    ref.cpp
    #include <iostream>
    
    
    using namespace std;
    
    
    void foo(int& x) {x = 7;}
    
    
    int main(int argc, char** argv)
    {
        int x = 0;
        foo(x);
        cout << x << endl;
        return 0;
    }

    2. Компилируем в ассемблерный код.
    g++ -S ptr.cpp
    g++ -S ref.cpp


    3. Проверяем, есть ли разница.
    diff ptr.s ref.s

    У меня linux, gcc 5.3.0. Файлы отличаются только именами функций (Z3fooRi у ссылок, Z3fooPi у указателей). То есть, в данном случае действительно нет разницы между ссылками и указателями.

    P. S. Этот эксперимент показывает лишь то, что нет разницы между передачей по ссылке и по указателю. В случае, который указали в других ответах, разница есть.
    Ответ написан
    Комментировать
  • Как изменять значения переменных другого класса в C++?

    @Alexander1705
    Первое:
    Если пишите на C++ и используете заголовочные файлы С, их принято называть ctime, а не time.h

    Второе:
    Для псевдослучайных чисел в C++ используйте заголовочный файл random:
    #include <random>
    ...
    std::random_device rd;
    std::cout << rd() % 10;


    Третье:
    Если вам нужен массив, используйте массив. То что вы написали - очень странный костыль.
    Если нужно заполнить массив случайными числами, напишите функцию:
    void fill_with_random(int* arr, size_t n)
    {
        random_device rand;
        for (size_t i = 0; i < n; ++i)
        {
            arr[i] = rand() % 21 - 10; 
        }
    }


    Четвёртое:
    cout << y[0][0]; //все прекрасно выводится
    /*но если попробовать сделать y[0][0]+=1; то выводится ошибка "выражение должно быть допустимым для изменения левосторонним значением"*/

    Естественно, так происходит потому, что в вашем классе (который и не нужен совсем) вы возвращаете число, там где ожидается ссылка:
    int operator [](int i)
    {
        return x[i];
    }

    Заменить на:
    int& operator [](int i)
    {
        return x[i];
    }


    Пятое:
    int  operator [](int i)
    {
        return y[i][0]; /*совершенно непонятно, какую роль здесь играет [0], и почему не работает с просто return y[i]... при изменении [0] на любое другое число, результат не меняется...*/
    }

    Непонятно потому, что его там и не должно быть. operator[] должен давать доступ к строке (т.е. массиву). А уже второй operator[] будет относится к массиву и возвратит ссылку на элемент.
    massiv& operator [](int i)
    {
        return y[i];
    }


    Шестое:
    Если нужна матрица, используйте двумерный массив и не изобретайте велосипед. Если класс всё же необходим, например, если нужно добавить методы для работы с матрицей, можно написать такой класс, используя двумерный массив:
    class Matrix
    {
    public:
        Matrix() {}
        int* operator[] (size_t i)
        {
            return &arr[i][0]; // Указатель на первый элемент i-ой строки.
        }
    private:
        int arr[5][5];
    }


    Седьмое:
    Классы принято называть с большой буквы. И пожалуйста, не называйте их транслитом.
    Массив - Array
    Матрица - Matrix
    Ответ написан
    Комментировать
  • Как на C++ выполнить параллельные математические вычисления?

    @Alexander1705
    Способов распаралелить много, но хочу заметить, что ваши вычисления получаются бесконечными отчасти благодаря следующей строке:
    cout << sqrt(n) << endl;
    А именно, из-за endl. После каждого вычисления вы зачем-то сбрасываете поток вместо того, чтоб просто вывести символ перевода на новую строку '\n'.

    P.S. В С пишите math.h, а в C++ - cmath. И зачем вы используете while вместо for?
    #include <cstdint>
    ...
    for (uint64_t i = 0; i < UINT64_MAX; ++i)


    P.P.S. Вот пример на чистом C++. Не забудьте подключить библиотеку pthread.
    Код
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <thread>
    #include <mutex>
    #include <chrono>
    #include <cmath>
    #include <cstdint>
    
    
    using namespace std;
    
    
    mutex ios_mutex;
    
    
    void compute(int b, int e)
    {
        stringstream buffer;
        for (uint64_t i = b; i < e; ++i)
        {
            buffer << sqrt(i) << '\n';
        }
    
        ios_mutex.lock();
        cout << buffer.str();
        ios_mutex.unlock();
    }
    
    
    int main(int argc, char** argv)
    {
        thread t0(compute,   0,  99);
        thread t1(compute, 100, 199);
        thread t2(compute, 200, 299);
        thread t3(compute, 300, 399);
        thread t4(compute, 400, 499);
        thread t5(compute, 500, 599);
        thread t6(compute, 600, 699);
        thread t7(compute, 700, 799);
    
        t0.join();
        t1.join();
        t2.join();
        t3.join();
        t4.join();
        t5.join();
        t6.join();
        t7.join();
    
        return 0;
    }

    Ответ написан
    1 комментарий
  • Как циклом перебирать посимвольно string переменную c++?

    @Alexander1705
    string str = "Hello, world!";
    
    for (auto c : str)
    {
        do_something(c);
    }
    Ответ написан
    Комментировать
  • Для чего нужен explicit?

    @Alexander1705
    Если вы определяете конструктор принимающий один и только один аргумент, такой конструктор будет использоваться для неявного приведения из типа аргумента в тип вашего класса. Используйте explicit, если хотите изменить это поведение.
    class Foo
    {
    public:
        Foo(int v) : _v(v) {}
    private:
        int _v;
    };
    
    class Bar
    {
    public:
        explicit Bar(int v) : _v(v) {}
    private:
        int _v;
    };
    
    void baz(Foo foo) {/* some code */}
    void qux(Bar bar) {/* some code */}
    
    int main()
    {
        Foo foo = Foo(4);
        Bar bar = Bar(4);
    
        baz(foo); // Ok.
        baz(4);   // Ok.
        qux(bar); // Ok.
        qux(4);   // Fail.
    }
    Ответ написан
    1 комментарий
  • Нужен целочисленный тип данных размером в 8 и 3 байт С++, как сделать?

    @Alexander1705
    Используйте cstdint. 3-байтного типа не существует, используйте 4-х байтный.

    #include <cstdint>
    
    int64_t foo; uint64_t bar; // 8 байт. Знаковый и беззнаковый.
    int32_t foo; uint32_t bar; // 4 байта. Знаковый и беззнаковый.
    Ответ написан
  • Стоит ли зацикливаться на непонятной теме?

    @Alexander1705
    У каждой переменной есть адресс в памяти (обычное натуральное число, порядковый номер какого-нибудь байта). Когда создаёте массив, его элементы (по сути, те же переменные) рассполагаются в памяти по-порядку.
    Если вы будете передавать массив по значению, вам придётся передавать функции значение каждого элемента, а их могут быть сотни и тысячи. По этому, вы можете сказать адрес первого элемента, и их количество. Зная, что остальные элементы будут рассполагаться сразу за первым, функция сможет получить доступ ко всем остальным элементам.

    Уточните, если что-то непонятно, или если есть вопросы по синтаксису.

    Upd.
    // Функция, которая принимает массив.
    void foo(int* arr, size_t n)
    {
        for (size_t i = 0; i < n; ++i)
            cout << arr[i] << ' ';
    }
    
    // Функция, которая возвращает массив.
    int* bar(size_t n)
    {
        // Массив должен быть выделен динамически, иначе
        // он перестанет существовать после завершения этой функции.
        int* arr = new int[n];
        for (size_t i = 0; i < n; ++i)
            cin >> arr[i];
    
        return arr;
    }

    Обратите внимание, что если функция возвращает указатель на массив, последний должен быть выделен динамически. Иначе массив будет уничтожен при завершении функции, вы просто получите некорректный указатель и undefined behaviour.

    P.S. Не забывайте удалять динамически выделенные массивы (delete[] arr;), после того, как они станут больше не нужны.
    Ответ написан
    4 комментария
  • Итератор - это указатель на адрес элемента контейнера?

    @Alexander1705
    Итератор - это не указатель. Это объект класса vector::iterator, который перегружает свои операторы так, что работа с ним выглядит так же как и с указателем. Например, он перегружает операторы разименования (*), оператор обращения к члену через указатель (->), и арифметические операторы (+ и -).

    Да, ваш код выведет значение первого элемента.
    Ответ написан
    1 комментарий