Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.11.2018, 14:01   #1
Tpai
 
Регистрация: 09.06.2018
Сообщений: 9
По умолчанию Программа падает

Код:
// ConsoleApplication6.cpp: определяет точку входа для консольного приложения.
//

#include "stdafx.h"
#include <iostream>
using namespace std;

class country {
private:
	char * name ;
	char * stolica;
	char * sch;
	double lud;
	double s;
	country * next;
public:
	void print(void) {
		cout << "nazvaniye: " << name << " stolica: " << stolica << " yazik: " << sch << " naseleniye: " << lud << " ploshad: " << s << endl;
	};
	void set_console() {
		cin >> name >> stolica >> sch >> lud >> s;
		next = NULL;
	};
	country(void) {
		name = new char[16];
		stolica = new char[16];
		sch = new char[16];
		lud = 0;
		s = 0;
		next = 0;
	};
	country(char* c_name, char * c_stolica, char * c_sch, double c_lud, double c_s) {
		name = new char[16];
		stolica = new char[16];
		sch = new char[16];
		set_main(c_name, c_stolica, c_sch, c_lud, c_s);
	};
	void set_main(const char* c_name, const char * c_stolica, const char * c_sch, double c_lud, double c_s) {
		strcpy_s(name, strlen(c_name)+1, c_name);
		strcpy_s(stolica, strlen(c_stolica)+1, c_stolica);
		strcpy_s(sch, strlen(c_sch)+1, c_sch);
		lud = c_lud;
		s = c_s;
		next = NULL;
	};
	void set_next(country * rex) {
		next = rex;
	};
	country * get_next(void) {
		return next;
	};
	char * get_name(void) {
		return name;
	};
	void set_name(const char * c_name) {
		strcpy_s(name, strlen(c_name)+1, c_name);
	};
	void set_stolica(const char * c_stolica) {
		strcpy_s(stolica, strlen(c_stolica)+1, c_stolica);
	};
	void set_sch(const char * c_sch) {
		strcpy_s(sch, strlen(c_sch)+1, c_sch);
	};
	void set_lud(double c_lud) {
		lud = c_lud;
	};
	void set_s(double c_s) {
		s = c_s;
	};
	double get_s(void) {
		return s;
	};
	~country() {
		delete[] name;
		delete[] stolica;
		delete[] sch;
	}
};
class odns {
private:
	country * eins;
	country * end;
public:
	odns(void) {
		eins = NULL;
		end = NULL;
	};
	void add(country * rex) {  //вставка элемента rex в конец списка с конечнымэлементом end
		if (end != NULL) {
			end->set_next(rex);
		}
		else {
			eins = rex;
		}
		end = rex;
	}
	void print(void) {
		country * rex = eins;
		rex->print();
		while ((*rex).get_next() != NULL) {
			rex = rex->get_next();
			rex->print();
		}
	};
	int operacia(double a, double b, char * op) {//функция возвращает результат выполнения операции из строки op над числами a и b
		if (op[0] == '<')
			return (a<b);
		if (op[0] == '>')
			return (a>b);
		if (op[0] == '=')
			return (a == b);
	};
	void insert(country * ctr, int n) { //вставка элемента rex в список с начальным элементом beg под омером n
		country * rex = eins;
		if (n>1) {
			for (int i = 1; i<n - 1; i++) {
				rex = rex->get_next();
			}

			country * rexis = (*rex).get_next();
			rex->set_next(ctr);
			ctr->set_next(rexis);

		}
		else {
			eins = ctr;
			ctr->set_next(rex);
		}


	};
	void my_remove(int n) {//удаление элемента под номером n из списка
		country * rex;
		if (n<2) {
			rex = eins->get_next();
			delete (eins);
			eins = rex;
		}
		else {
			rex = eins;
			for (int i = 1; i<n - 1; i++) {
				rex = rex->get_next();
			}
			if (rex->get_next()->get_next() == NULL)
				end = rex;
			country * rexis = rex->get_next();
			rex->set_next(rex->get_next()->get_next());
			delete(rexis);
		}

	};
	country * get_el(int n) {
		country * rex = eins;
		for (int i = 1; i<n; i++) {
			rex = rex->get_next();
		}
		return rex;
	};
	void set_el(int n, country * ctr) {
		country * rex = eins;
		for (int i = 1; i<n - 1; i++) {
			rex = rex->get_next();
		}
		ctr->set_next(rex->get_next());
		rex->set_next(ctr);
	};
	country * find(char*s) { //функция возвращает элемент из списка с названием страны s
		int len = strlen(s);
		country * rex = eins;
		char * h;
		while (rex != NULL) {
			h = rex->get_name();
			int j = 0;
			if (strlen(h) == len) {
				for (int i = 0; i<len; i++) {
					if (h[i] != s[i]) {
						j = 1;
						break;
					}
				}
			}
			else {
				j = 1;
			}
			if (j == 0) {
				return rex;
			}
			rex = rex->get_next();
		}
		return NULL;
	};
	void fltr(char * op, double r) {//функция удаляет из списка элементы, не удвлетворяющие условию
		int j = 1;
		country * rex = eins;
		country * rexis;
		while (rex != NULL) {
			rexis = rex->get_next();
			if (!(operacia(rex->get_s(), r, op)))
				my_remove(j);
			else
				j++;
			rex = rexis;
		}
	};
};
int main()
{
	odns obj;
	country obje1("1", "1", "1", 1, 1);
	country obje2;
	obje2.set_console();
	country obje3("3", "3", "3", 3, 3);
	country obje4("4", "4", "4", 4, 4);
	obj.add(&obje1);
	obj.add(&obje2);
	obj.add(&obje3);
	obj.insert(&obje4, 3);
	obj.my_remove(2);
	obj.get_el(3)->set_name("68");
	obj.get_el(3)->set_stolica("8");
	obj.get_el(3)->set_sch("10");
	obj.get_el(3)->set_lud(30);
	obj.get_el(3)->set_s(45);
	obj.print();
	country obje5("5", "56", "5", 5, 5);
	cout << endl;
	obj.set_el(2,&obje5);
	obj.print();
	cout << endl;
	obj.find("68")->print();
	cout << endl;
	obj.fltr("=", 1);
	obj.print();
        system ("pause");
	return 0;
}
При попытке удалить элемент списка программа падает.

Последний раз редактировалось Tpai; 05.11.2018 в 14:23.
Tpai вне форума Ответить с цитированием
Старый 05.11.2018, 14:22   #2
KAMLS
Форумчанин
 
Регистрация: 09.04.2017
Сообщений: 598
По умолчанию

С такими приколами она у вас и не встанет никогда..
Почему у вас точка с запятой после каждого метода? Это так сейчас начали писать? };

Последний раз редактировалось KAMLS; 05.11.2018 в 14:25.
KAMLS вне форума Ответить с цитированием
Старый 06.11.2018, 11:18   #3
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

UB

Код:
int operacia(double a, double b, char * op) {//функция возвращает результат выполнения операции из строки op над числами a и b
        if (op[0] == '<')
            return (a < b);
        if (op[0] == '>')
            return (a > b);
        if (op[0] == '=')
            return (a == b);
    };
Цитата:
warning C4715: 'odns:peracia': not all control paths return a value
_Bers вне форума Ответить с цитированием
Старый 06.11.2018, 11:22   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

краш происходит в функции:

Код:
void my_remove(int n) {//удаление элемента под номером n из списка
        country * rex;
        if (n < 2) {
            rex = eins->get_next();
            delete (eins);
            eins = rex;
        }
        else {
            rex = eins;
            for (int i = 1; i < n - 1; i++) {
                rex = rex->get_next();
            }
            if (rex->get_next()->get_next() == NULL)
                end = rex;
            country * rexis = rex->get_next();
            rex->set_next(rex->get_next()->get_next());
            delete(rexis);  // <--- вот здесь
        }
    };

причина краша - попытка удалить данные по адресу,
по которому удалять нельзя.

значит смотрим, как элемент добавлялся
_Bers вне форума Ответить с цитированием
Старый 06.11.2018, 11:24   #5
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

исходный элемент - автоматический объект на стеке:

видно, что в контейнер передаются адреса:

Код:
int main()
{
	odns obj;
	country obje1("1", "1", "1", 1, 1);
	country obje2;
	obje2.set_console();
	country obje3("3", "3", "3", 3, 3);
	country obje4("4", "4", "4", 4, 4);
	obj.add(&obje1);
	obj.add(&obje2);
	obj.add(&obje3);
	obj.insert(&obje4, 3);
	obj.my_remove(2);
_Bers вне форума Ответить с цитированием
Старый 06.11.2018, 11:34   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

функция непосредственно самого добавления:
Код:
void add(country * rex) {  //вставка элемента rex в конец списка с конечнымэлементом end
        if (end != NULL) {
            end->set_next(rex);
        }
        else {
            eins = rex;
        }
        end = rex;
    }
получает на входе адрес исходного автоматического объекта,
а затем тупо его сохраняет.

в дальнейшем, в функции удаления,
выполняется попытка удалить объект по адресу.
но в данном случае получается, что это - адрес автоматического локального объекта, а не выделенного в куче!

нельзя обычные локальные объекты убивать при помощи delete.



1. грубый фикс легко заставит программу работу работать.
(хотя это и не решение настоящей проблемы)

просто заменим локальные объекты на динамические:

Код:
#include <iostream>
using namespace std;

class country {
private:
    char * name;
    char * stolica;
    char * sch;
    double lud;
    double s;
    country * next;
public:
    void print(void) {
        cout << "nazvaniye: " << name << " stolica: " << stolica << " yazik: " << sch << " naseleniye: " << lud << " ploshad: " << s << endl;
    };
    void set_console() {
        cin >> name >> stolica >> sch >> lud >> s;
        next = NULL;
    };
    country(void) {
        name = new char[16];
        stolica = new char[16];
        sch = new char[16];
        lud = 0;
        s = 0;
        next = 0;
    };
    country(char* c_name, char * c_stolica, char * c_sch, double c_lud, double c_s) {
        name = new char[16];
        stolica = new char[16];
        sch = new char[16];
        set_main(c_name, c_stolica, c_sch, c_lud, c_s);
    };
    void set_main(const char* c_name, const char * c_stolica, const char * c_sch, double c_lud, double c_s) {
        strcpy_s(name, strlen(c_name) + 1, c_name);
        strcpy_s(stolica, strlen(c_stolica) + 1, c_stolica);
        strcpy_s(sch, strlen(c_sch) + 1, c_sch);
        lud = c_lud;
        s = c_s;
        next = NULL;
    };
    void set_next(country * rex) {
        next = rex;
    };
    country * get_next(void) {
        return next;
    };
    char * get_name(void) {
        return name;
    };
    void set_name(const char * c_name) {
        strcpy_s(name, strlen(c_name) + 1, c_name);
    };
    void set_stolica(const char * c_stolica) {
        strcpy_s(stolica, strlen(c_stolica) + 1, c_stolica);
    };
    void set_sch(const char * c_sch) {
        strcpy_s(sch, strlen(c_sch) + 1, c_sch);
    };
    void set_lud(double c_lud) {
        lud = c_lud;
    };
    void set_s(double c_s) {
        s = c_s;
    };
    double get_s(void) {
        return s;
    };
    ~country() {
        delete[] name;
        delete[] stolica;
        delete[] sch;
    }
};
class odns {
private:
    country * eins;
    country * end;
public:
    odns(void) {
        eins = NULL;
        end = NULL;
    };
    void add(country * rex) {  //вставка элемента rex в конец списка с конечнымэлементом end
        if (end != NULL) {
            end->set_next(rex);
        }
        else {
            eins = rex;
        }
        end = rex;
    }
    void print(void) {
        country * rex = eins;
        rex->print();
        while ((*rex).get_next() != NULL) {
            rex = rex->get_next();
            rex->print();
        }
    };
    int operacia(double a, double b, char * op) {//функция возвращает результат выполнения операции из строки op над числами a и b
        if (op[0] == '<')
            return (a < b);
        if (op[0] == '>')
            return (a > b);
        if (op[0] == '=')
            return (a == b);
    };
    void insert(country * ctr, int n) { //вставка элемента rex в список с начальным элементом beg под омером n
        country * rex = eins;
        if (n > 1) {
            for (int i = 1; i < n - 1; i++) {
                rex = rex->get_next();
            }

            country * rexis = (*rex).get_next();
            rex->set_next(ctr);
            ctr->set_next(rexis);
        }
        else {
            eins = ctr;
            ctr->set_next(rex);
        }
    };
    void my_remove(int n) {//удаление элемента под номером n из списка
        country * rex;
        if (n < 2) {
            rex = eins->get_next();
            delete (eins);
            eins = rex;
        }
        else {
            rex = eins;
            for (int i = 1; i < n - 1; i++) {
                rex = rex->get_next();
            }
            if (rex->get_next()->get_next() == NULL)
                end = rex;
            country * rexis = rex->get_next();
            rex->set_next(rex->get_next()->get_next());
            delete (rexis);
        }

    };
    country * get_el(int n) {
        country * rex = eins;
        for (int i = 1; i < n; i++) {
            rex = rex->get_next();
        }
        return rex;
    };
    void set_el(int n, country * ctr) {
        country * rex = eins;
        for (int i = 1; i < n - 1; i++) {
            rex = rex->get_next();
        }
        ctr->set_next(rex->get_next());
        rex->set_next(ctr);
    };
    country * find(char*s) { //функция возвращает элемент из списка с названием страны s
        int len = strlen(s);
        country * rex = eins;
        char * h;
        while (rex != NULL) {
            h = rex->get_name();
            int j = 0;
            if (strlen(h) == len) {
                for (int i = 0; i < len; i++) {
                    if (h[i] != s[i]) {
                        j = 1;
                        break;
                    }
                }
            }
            else {
                j = 1;
            }
            if (j == 0) {
                return rex;
            }
            rex = rex->get_next();
        }
        return NULL;
    };
    void fltr(char * op, double r) {//функция удаляет из списка элементы, не удвлетворяющие условию
        int j = 1;
        country * rex = eins;
        country * rexis;
        while (rex != NULL) {
            rexis = rex->get_next();
            if (!(operacia(rex->get_s(), r, op)))
                my_remove(j);
            else
                j++;
            rex = rexis;
        }
    };
};
int main()
{
    odns obj;
    country* obje1 = new country("1", "1", "1", 1, 1);
    country* obje2 = new country();
    obje2->set_console();
    country* obje3 = new country("3", "3", "3", 3, 3);
    country* obje4 = new country("4", "4", "4", 4, 4);
    obj.add(obje1);
    obj.add(obje2);
    obj.add(obje3);
    obj.insert(obje4, 3);
    obj.my_remove(2);
    obj.get_el(3)->set_name("68");
    obj.get_el(3)->set_stolica("8");
    obj.get_el(3)->set_sch("10");
    obj.get_el(3)->set_lud(30);
    obj.get_el(3)->set_s(45);
    obj.print();
    country* obje5 = new country("5", "56", "5", 5, 5);
    cout << endl;
    obj.set_el(2, obje5);
    obj.print();
    cout << endl;
    obj.find("68")->print();
    cout << endl;
    obj.fltr("=", 1);
    obj.print();
}
по хорошему, конечно, нужно выкидывать весь код в мусорку,
и заново переписывать код контейнера.
_Bers вне форума Ответить с цитированием
Старый 06.11.2018, 23:01   #7
CppLinux345
Пользователь
 
Регистрация: 26.09.2018
Сообщений: 23
По умолчанию

А по детальней с коментариеми можно?
CppLinux345 вне форума Ответить с цитированием
Старый 07.11.2018, 07:12   #8
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Так по сути в коде ничего не поменялось, кроме динамического выделения. Вы ТС или просто пришли скопипастить себе лабу?
p51x вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Падает VS ZoxWatt Windows 0 05.12.2012 20:55
Почему С++ падает Sylar9 Общие вопросы C/C++ 5 27.03.2012 01:50
ВСЕ ПИЩИТ И ПАДАЕТ! легенькая программа pinkiller Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 1 20.03.2012 21:16
Сервер падает Х) Slusar PHP 2 05.10.2009 22:47
Программа падает при добавлении кода, который не используется. Protsv Общие вопросы Delphi 16 03.04.2008 08:01