• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Kontener vector nie działa w programach okienkowych

VPS Starter Arubacloud
0 głosów
157 wizyt
pytanie zadane 13 marca 2017 w C i C++ przez niezalogowany

Mam problem, ponieważ gdy używałem klasy vector w programach konsolowych to wszystko jest ok, ale w programach okienkowych często wywalają dziwne błędy związane z pamięcią albo funkcja wykonuje się tylko do pewnego momentu i nie zwraca tego co trzeba. Oto moja klasa Menu działająca bez zarzutów (tak mi się przynajmniej wydaje po licznych testach) w konsoli.

plik menu.h

#include <iostream>

using namespace std;

class Menu
{
	public:
	
	vector <string> wszystkie; // wszystkie opcje w menu (wszystkie główne oraz ich podopcje)
	vector <string> glowne; // główne opcje w menu (można je wyświetlić, wybrać)
	
	Menu(int,int,string*,string*);
	Menu(int=0,int=1);
	~Menu();
	void wybierz(int wb); // czyta wybór użytkownika
	void cofnij(); // powrót
	
	private:
	
	int w,g;
	vector < vector <string> > poziomow;
	vector <string> tematy;
};

plik menu.cpp

#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include "menu.h"
#include "text.h"

using namespace std;

Menu::Menu(int o, int t, string *op, string *tem)
{
	for(int i=0; i<o; i++)
    {
		if(i!=0)
			wszystkie.push_back(op[i]);
		if( (int)op[i][0] != 9 && i!=0)
			glowne.push_back(op[i]);
    }

	for(int i=0; i<t; i++)
		tematy.push_back(tem[i]);

	poziomow.push_back(wszystkie);
	poziomow.push_back(glowne);
}

Menu::Menu(int ww, int gg)
{
	w=ww;
	g=gg;
}

Menu::~Menu()
{

}

void Menu::wybierz(int wb)
{
	if(wb!=122)
	{
		wszystkie.clear();
		glowne.clear();
		int temat=0;

		for(int i=0; i<poziomow[w].size(); i++)
		{
			if( (int)poziomow[w][i][0]!=9 )
				temat++;

			if(temat == wb)
			{
				i++;

				if(i==poziomow[w].size())
					break;

				while( (int)poziomow[w][i][0]==9 )
				{	
					string dodaj = poziomow[w][i];

					if( is_int_convert(dodaj.erase(0,1)) )
                        wszystkie.push_back( tematy[ atoi(dodaj.c_str())-1 ] );
                    else
                        wszystkie.push_back(dodaj);

					if((int)poziomow[w][i][0]==9 && (int)poziomow[w][i][1]!=9)
					{
						if( is_int_convert(without(poziomow[w][i], '	')) )
						{
							glowne.push_back( tematy[ atoi(without(poziomow[w][i], '	').c_str())-1 ] );
						}
						else
						{
							string dodaj = poziomow[w][i];
							glowne.push_back(dodaj.erase(0,1));
						}
					}

					if(i==poziomow[w].size()-1)
                    {
                        i--;
                        break;
                    }

					i++;
				}
				break;
			}
		}

		poziomow.push_back(wszystkie);
		poziomow.push_back(glowne);
		w+=2;
		g+=2;
	}
}

void Menu::cofnij()
{
	poziomow.erase(poziomow.begin()+w);
	poziomow.erase(poziomow.begin()+w);
	
	wszystkie.clear();
	glowne.clear();
	
	wszystkie = poziomow[poziomow.size()-2];
	glowne = poziomow[poziomow.size()-1];
}

 

Gdy próbuję wywołać funkcję składową wybierz() lub cofnij() obojętnie, w którym miejscu w programie to albo wywala 0xC000005 albo 0xFFFFFF albo program się nie zawiesza, ale gdy kontrolnie wyprowadzam MessageBoxem zawartość zmiennej w to jest ona zawsze przypadkowa. Zrobiłem sobie kilka MessageBoxów żeby sprawdzić dokąd wszystko jest ok (z debuggera nie umiem korzystać i nie wiem co oznaczają treści błędów) i wychodzi na to, że błąd tkwi w linijce 46 w pliku menu.cpp bo to co przed pętlą normalnie się wyświetla, a to co wewnątrz pętli już nie. I nic dziwnego skoro w posiada jakąś przypadkową wartość nawet kilkaset tysięcy czasami, a nie ma elementu vectora o takim indeksie (swoją drogą ciekawe dlaczego w tym miejscu nie wywala). Gdy zrobiłem MessageBoxa wewnatrz konstruktora z dwoma intami to nie wyświetliło mi się nic, co sugeruje, że w momencie tworzenia obiektu akurat ten konstruktor nie jest w ogóle wywoływany i zmienne w i g nie są inicjowane. 

Ktoś może rozjaśnić co nieco sytuację? Czy serio muszę zrezygnować z wektorów? Przecież to dar dla programistów, który powinno się wykorzystywać. Czy w innych bibliotekach jak np. Qt też nie da się ich ogarnąć czy to tylko programowanie w WinAPI jest tak chore? Pomocy.

2 odpowiedzi

0 głosów
odpowiedź 13 marca 2017 przez adrian17 Ekspert (344,100 p.)

W konstruktorze `Menu::Menu(int o, int t, string *op, string *tem)`  nie inicjalizujesz `w`, `g`. Strzelam, że to to.

Reszty nie czytałem, bo wygląda (prze)kompilowanie.

I nie przekazuj obiektów przez wskaźnik...

czy to tylko programowanie w WinAPI jest tak chore? 

Jest chore. Nie mam pojęcia skąd wpadłeś na szalony pomysł żeby iść w tą stronę... ale wyjątkowo to raczej nie ma związku z Twoimi problemami.

0 głosów
odpowiedź 13 marca 2017 przez niezalogowany

Dosłownie parę minut temu wpadłem właśnie na pomysł, żeby tak jak piszesz inicjować zmienne g i w w konstruktorze i wszystko zadziałało! smiley  Ja myślałem, że konstruktory można przeładowywać dla wygody programisty i jeden zainicjuje jedne zmienne, a drugi drugie, więc stworzyłem ten duży konstruktor, któremu trzeba podać parametry i drugi domyślny dla samej inicjalizacji g i w. Z jakiegoś powodu ubzdurałem sobie, że obydwa te konstruktory zostaną wywołane w momencie tworzenia obiektu, a przecież z przeładowaniem konstruktora jest tak samo jak z przeładowaniem funkcji - tylko jedna wersja jest wywoływana w zależności od argumentów.

Nie mam pojęcia czemu tak bez sensu myślałem, ale to jest straszne gdy jakaś jedna błędna myśl siedzi komuś w głowie przez tyle czasu i tyle się trzeba denerwować przez wiele godzin i analizować kod, podczas gdy przyczyna błędu jest tak błaha. Ale taki to już los programisty. Pytanie tylko jakim cudem wersja konsolowa z dwoma oddzielnymi konstruktorami jednak działa ???

A co do WinAPI to po prostu postanowiłem trochę się tym pobawić, w końcu to biblioteka Windowsa. Ale po napisaniu kilku/klikunastu programów zamierzam przejść do środowiska wizualnego, prawdopodobnie Qt, bo z tego co wiem jest bardzo wygodne i rozbudowane.

 

 

komentarz 13 marca 2017 przez criss Mędrzec (172,590 p.)

Na przyszłość: odpowiadaj w komentarzach do odpowiedzi. Wtedy autor odpowiedzi dostanie powiadomienie.

Każdy konstruktor powinien inicjalizować wszystkie pola (chyba, że pole jest obiektem i ma domyślny konstruktor), albo delegować do innego inicjalizującego wszystkie pola.

Pytanie tylko jakim cudem wersja konsolowa z dwoma oddzielnymi konstruktorami jednak działa ?

Przypadek 

Podobne pytania

0 głosów
2 odpowiedzi 378 wizyt
pytanie zadane 7 grudnia 2016 w C i C++ przez Sinnley Stary wyjadacz (12,810 p.)
+1 głos
2 odpowiedzi 292 wizyt
pytanie zadane 17 lipca 2015 w C i C++ przez Dash Nałogowiec (29,650 p.)
0 głosów
3 odpowiedzi 407 wizyt

92,453 zapytań

141,262 odpowiedzi

319,086 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...