Ответы пользователя по тегу C++
  • Есть ли способ получать предупреждение при преобразовании char в int?

    by_kapt0xa
    @by_kapt0xa
    Учу кресты катаюсь на велике
    char ToChar(int val)
    {
        if(static_cast<unsigned>(val) <= 255)  // better to use std::numeric_limits<unsigned char>::max() instead of 255
        {
            return static_cast<char>(val);
        }
        else 
        {
            throw "trying to convert int to char with loosing of data"; // better to throw some another exception from the lib #include <stdexcept>
        }
    }


    код написан на коленке, могут быть синтаксические оишбки
    Ответ написан
    Комментировать
  • Как упростить проверку на правильность круглых скобок?

    by_kapt0xa
    @by_kapt0xa
    Учу кресты катаюсь на велике
    попробуй это
    #include <iostream>
    #include <cassert>
    
    using namespace std;
    
    int main()
    {
    	string input;
    	cin >> input;
    	int unclosed_count = 0;
    	for (char c : input)
    	{
    		if (c == '(')
    		{
    			++unclosed_count;
    		}	
    		else if (c == ')')
    		{
    			--unclosed_count;
    			assert(unclosed_count >= 0);//не знаю как надо реагировать на неправильные скобки, но вот тут нужно отслеживать корректность.
    		}
    	}
    }
    Ответ написан
  • Откуда здесь NAN?

    by_kapt0xa
    @by_kapt0xa
    Учу кресты катаюсь на велике
    я при выполнении получил ошибку в 152 строке (delete[] multed;)
    возможно, вы напартичили с указателями и nan получается из мусорных значений
    вы вроде на c++ пишете, а векторами не пользуетесь
    вектора не будут давать ошибок при работе с указателями, и во время дебага отладчик показывает все содержимое вектора а не только 1 число
    все, что связанно с указателями, new, delete надо вычеркнуть из своего кода заменить это все векторами
    и матрицу лучше делать так:
    int n;
        vector<float> maxrix(n * n, 0); // так плохо
        vector<vector<float>> matrix(n, move(vector<float>(n, 0))); // так хорошо


    и еще для примера я тебе переписал функцию subtract, чтобы ты знал как это нормально делается
    vector<vector<float>>& operator -=(vector<vector<float>>& Left, const vector<vector<float>>& Right) {
        assert(Left.size() == Right.size()); // #include <cassert>
        //ассерт выполняется только в режиме дебага. он делает твой код безопаснее
        for (size_t i = 0; i < Left.size(); i++)
        {
            vector<float>& line = Left[i];//принимает по ссылке, а не по значению.
            const vector<float>& r_line = Right[i];
            assert(line.size() == r_line.size()); // #include <cassert>
            for (size_t j = 0; j < line.size(); j++)
            {
                line[j] -= r_line[j];
            }
        }
        return Left;
    }
    
    vector<vector<float>> operator -(const vector<vector<float>>& Left, const vector<vector<float>>& Right) {
        auto copy = Left;
        copy -= Right;
        return copy;
    }

    const type& - значение передается по ссылке, без копирования с запретом на изменение
    type& - значение передается по ссылке, без копирования, можно вносить изменения
    Ответ написан
  • Как поменять код, чтобы при заполнении двумерного массива распознавалась переменная int и не запрашивало указатель?

    by_kapt0xa
    @by_kapt0xa
    Учу кресты катаюсь на велике
    #include <random>
    #include <iostream>
    using namespace std;
    
    void zxc(int* arr, const int row, const int col)
    {
    
    	srand(time(NULL));
    	for (int f = 0; f < row; f++)
    	{
    		for (int j = 0; j < col; j++)
    			arr[f* col + j] = rand() % 10;
    	}
    
    }
    
    void qwe(int* arr, const int row, const int col)
    {
    
    	for (int i = 0; i < col; i++) {
    		for (int f = 0; f < row; f++)
    			cout << arr[f * col + i] << "\t";
    		cout << endl;
    	}
    }
    
    //qwe и zxc это самые удачные названия для функции, из названия сразу ясно что эти функции делают.
    
    int main()
    {
    	const int row = 5;
    	const int col = 7;
    	int arr[row * col];
    	zxc(arr, row, col);
    	qwe(arr, row, col);
    }

    программисты C++ таким не занимаются, это больше похоже на C.
    вот как выглядит нормальный код на C++:
    #include <random>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    void zxc(vector<vector<int>>& arr, const int row, const int col)
    {
    	srand(time(NULL));
    	arr.resize(row);
    	for (auto& line : arr)
    	{
    		line.resize(col);
    		for (auto& x: line)
    		{
    			x = rand() % 10;
    		}
    	}
    
    }
    
    void qwe(const vector<vector<int>>& arr, const int row, const int col)
    {
    	for (const auto& line : arr)
    	{
    		for (const auto& x : line)
    		{
    			cout << x << "\t";
    		}
    		cout << endl;
    	}
    }
    
    int main()
    {
    	const int row = 5;
    	const int col = 7;
    	vector<vector<int>> arr;
    	zxc(arr, row, col);
    	qwe(arr, row, col);
    }

    простые массивы имеют массу неприятностей, связанных с НЕгибкостью кода. если вы пишете на плюсах, познакомьтесь с векторами.
    !!!!!!!!!извиняюсь, предыдущая версия была с ошибками, я отредачил
    Ответ написан
    1 комментарий
  • Можно ли вызвать деструктор void*?

    by_kapt0xa
    @by_kapt0xa
    Учу кресты катаюсь на велике
    нет, нужен полиморфизм
    попробуйте почитать про std::variant
    допустим, вы собираетессь хранить там не все что угодно, а только double, string и bool
    тогда надо написать
    using polimorf_ptr = variant<double*, string*, bool*>;
    vector<polimorf_ptr> ...; // получается у вас не void*, а polimorf_ptr


    !!!!1 обновил:
    попробуй использовать PolimorfPtr вместо void*. я на коленке сделал, возможно тебе идея понравится и ты доработаешь:
    void no_destructor(void*) {}
    
    struct PolimorfPtr
    {
    public:
    	PolimorfPtr()
    		: ptr(nullptr) //надеюсь, ты шаришь за двоеточие
    	{}
    	PolimorfPtr(const PolimorfPtr&) = delete;
    	PolimorfPtr(PolimorfPtr&& other) //надеюсь, ны знаешь что такое r-value - ссылка
    		:ptr(other.ptr),
    		destructor(other.destructor)
    	{
    		other.ptr = nullptr;
    		other.destructor = no_destructor;
    	}
    	//мне лень писать оператор =, оператор *, -> и вот это вот все, надеюсь ты знаешь зачем нужны эти операторы и понимаешь о чем я
    
    	PolimorfPtr(void* pointer, void destructor_calling_function(void*) = no_destructor)
    		: ptr(pointer),
    		destructor(destructor_calling_function)
    	{}
    
    	void* ptr; //====================================================== тут хранится указатель
    	void (*destructor)(void*) = no_destructor; //===========тут хранится указатель на деструктор (на функцию, которая вызывает деструктор)
    
    	~PolimorfPtr()
    	{
    		destructor(ptr);
    		ptr = nullptr;
    		destructor = no_destructor;
    	}
    };

    сори за коментарии для маленьких, я не знаю уровень твоего знания с++, возможно ты с этим уже знаком
    Ответ написан
  • Как сделать метод деления пополам?

    by_kapt0xa
    @by_kapt0xa
    Учу кресты катаюсь на велике
    1) прошагать с мелким шагом найти где функция меняет знак
    2) в каждом диапазоне где функция меняет знак найти корень
    2.1) если функция при изменении знака очень разко меняет значение (оценка производной слишком большая), то это не пересечения нуля, а разрыв.

    такой алгоритм не гарантирует корректное решение.

    #define _USE_MATH_DEFINES
    #include <iostream>
    #include <vector>
    #include <optional>
    #include <cmath>
    #include <cassert>
    using namespace std;
    
    double f(double x)
    {
    	return x * x * x * (cosh(x)) + M_PI - 9 * M_PI * x;// (e^x+e^-x)/2 это "гиперболический косинус" aka "чосинус"
    }
    
    bool has_different_signs(double a, double b)
    {
    	return (a > 0) != (b > 0);
    }
    
    vector<pair<double, double>> find_sign_shanges(double from, double to, double step, double function(double))
    {
    	assert(from < to);
    	assert(step > 0);
    
    	vector<pair<double, double>> result;
    
    	double last_val = function(from);
    	double last_x = from;
    	from += step;
    	for (; from < to; last_x = from, from += step)
    	{
    		double current_val = function(from);
    		if (has_different_signs(current_val, last_val))
    		{
    			result.push_back({last_x, from});
    		}
    		last_val = current_val;
    		last_x = from;
    	}
    	return result;
    }
    
    optional<double> find_root_binary(double from, double to, double function(double), double precision, double slope_limit = +INFINITY)
    {
    	double y1 = function(from);
    	double y2 = function(to);
    	assert(from <= to); // не уверен что это нужно
    	assert(has_different_signs(y1, y2));
    	assert(slope_limit > 0);
    	assert(precision > 0);
    
    	double slope = (y2 - y1) / (to - from);
    	if (abs(slope) >= slope_limit)
    	{
    		return nullopt; // если угол наклона граффика очень боьшой, кторее всего знак меняется не через 0, а через разрыв
    	}
    
    	double middle_x = (from + to) / 2;
    	double middle_y = function(middle_x);
    	if (abs(middle_y) < precision)
    	{
    		return middle_x;
    	}
    	if (has_different_signs(middle_y, y1))
    	{
    		return find_root_binary(from, middle_x, function, slope_limit);
    	}
    	else
    	{
    		return (find_root_binary(middle_x, to, function, slope_limit));
    	}
    }
    
    vector<double> find_roots(double from, double to, double function(double), double precision, double step = 0.1)
    {
    	assert(precision > 0);
    	auto sign_shanges = find_sign_shanges(from, to, step, function);
    	vector<double> result;
    	for (auto [from_mini, to_mini] : sign_shanges) // нужен c++ 17 или более поздняя версия вроде бы как для такого синтаксиса
    	{
    		auto root = find_root_binary(from_mini, to_mini, function, precision);
    		if (root)
    		{
    			result.push_back(*root);
    		}
    	}
    	return result;
    }
    
    int main()
    {
    	auto roots = find_roots(-10, +10, f, 0.0000001);
    	for (double root : roots)
    	{
    		cout << root << endl;
    	}
    	return 0;
    }
    Ответ написан
    Комментировать
  • Как исправить Error C4700: использована неинициализированная локальная переменная "x"?

    by_kapt0xa
    @by_kapt0xa
    Учу кресты катаюсь на велике
    чтобы код не искажался, используйте кнопку для вставки кода (см. прикрепленное изображение)
    просто у вас пропало то, что находится в угловых скобках

    попробуйте вот так:
    float y = 0, x = 0, t = 0, z = 0, k = 0;//при создании задавайте значение поумолчанию


    или так так:
    float y, x = 0, t = 0, z, k;

    с++ не задает переменным значение по умолчанию, если это не структура или класс с конструктором (я упрощаю)
    в переменной будет записан какой-то мусор, оставшийся от работы компьютера.

    6375b2975432d407708901.png
    Ответ написан
    Комментировать